您的位置:首页 > 移动开发 > Android开发

android系统学习笔记四

2012-09-03 15:07 183 查看
Android 的GUI 系统

Android GUI 系统综述

C 语言部分包括:

pixelFlinger(下层工具库)

头文件/system/core/include/pixelflinger 其生成的动态库libpixelflinger.so 只连接

                        C语言库libcutils

Format.h提供像素格式的定义,

            Pixelflinger.h提供接口功能的定义

      源代码/system/core/libpixelflinger

Libui(GUI的框架库)

头文件: /system/core/libpixelflinger/ui

源代码: /frameworks/base/libs/ui

编译后生成 libui.so 连接libpiselflinger.so

包含了颜色格式 头文件:pixelformat.h point.h region.h rect.h displayinfo.h

egl窗口(用于显示)

按健及事件处理(key/Event)头文件:eventhub.h keycodelabels.h

keycharactermap.h

Suface(显示界面)

overlay(显示叠加层接口) iOverlay.h Overlay.h

camera(照像机接口)

SurfaceFlinger(surface的管理和处理)

Skia图形图像引擎

OpenGL 3D 引擎 

各种JNI接口

GUI系统的几个本地库中, libui是提供接口的框架库, 所涉及的java 框架层的主要内容:

     Android.graphics(对应Skia底层库,提供绘图接口)

Android .view.surface(构建显示界面)

Android .view.view( 各种UI元素有基类)

Javax.microdition.khronos.opengles(标准OpenGL接口)

输入/输出与硬件的接口

显示输出的硬件接口

对于android 的显示部分,需要实现的接口是: egl_mative_window_t (是一个OPENGL结构)

也给libEGL使用

输入的硬件接口

向上层提供统一的按键码(keyCode),这个按键码是一个整数,在libui中,通过标准的input

  驱动 来处理input的值转按成android系统的按键码,按键码参考KeyCharacterMap.h

/frameworks/base/include/ui/ KeycodeLabels.h 按键码的对照

struct KeycodeLabel {

const char *literal;

int value;

};

static const KeycodeLabel KEYCODES[] = {

{ "SOFT_LEFT", 1 },

{ "SOFT_RIGHT", 2 },

{ "HOME", 3 },

{ "BACK", 4 },

{ "CALL", 5 },

{ "ENDCALL", 6 },

{ "0", 7 },

{ "1", 8 },

{ "2", 9 },

{ "3", 10 },

{ "4", 11 },

{ "5", 12 },

{ "6", 13 },

{ "7", 14 },

{ "8", 15 },

{ "9", 16 },

{ "STAR", 17 },

{ "POUND", 18 },

{ "DPAD_UP", 19 },

{ "DPAD_DOWN", 20 },

{ "DPAD_LEFT", 21 },

{ "DPAD_RIGHT", 22 },

{ "DPAD_CENTER", 23 },

{ "VOLUME_UP", 24 },

{ "VOLUME_DOWN", 25 },

{ "POWER", 26 },

{ "CAMERA", 27 },

{ "CLEAR", 28 },

{ "A", 29 },

{ "B", 30 },

{ "C", 31 },

{ "D", 32 },

{ "E", 33 },

{ "F", 34 },

{ "G", 35 },

{ "H", 36 },

{ "I", 37 },

{ "J", 38 },

{ "K", 39 },

{ "L", 40 },

{ "M", 41 },

{ "N", 42 },

{ "O", 43 },

{ "P", 44 },

{ "Q", 45 },

{ "R", 46 },

{ "S", 47 },

{ "T", 48 },

{ "U", 49 },

{ "V", 50 },

{ "W", 51 },

{ "X", 52 },

{ "Y", 53 },

{ "Z", 54 },

{ "COMMA", 55 },

{ "PERIOD", 56 },

{ "ALT_LEFT", 57 },

{ "ALT_RIGHT", 58 },

{ "SHIFT_LEFT", 59 },

{ "SHIFT_RIGHT", 60 },

{ "TAB", 61 },

{ "SPACE", 62 },

{ "SYM", 63 },

{ "EXPLORER", 64 },

{ "ENVELOPE", 65 },

{ "ENTER", 66 },

{ "DEL", 67 },

{ "GRAVE", 68 },

{ "MINUS", 69 },

{ "EQUALS", 70 },

{ "LEFT_BRACKET", 71 },

{ "RIGHT_BRACKET", 72 },

{ "BACKSLASH", 73 },

{ "SEMICOLON", 74 },

{ "APOSTROPHE", 75 },

{ "SLASH", 76 },

{ "AT", 77 },

{ "NUM", 78 },

{ "HEADSETHOOK", 79 },

{ "FOCUS", 80 },

{ "PLUS", 81 },

{ "MENU", 82 },

{ "NOTIFICATION", 83 },

{ "SEARCH", 84 },

{ "MEDIA_PLAY_PAUSE", 85 },

{ "MEDIA_STOP", 86 },

{ "MEDIA_NEXT", 87 },

{ "MEDIA_PREVIOUS", 88 },

{ "MEDIA_REWIND", 89 },

{ "MEDIA_FAST_FORWARD", 90 },

{ "MUTE", 91 },

{ "PAGE_UP", 92 },

{ "PAGE_DOWN", 93 },

{ "PICTSYMBOLS", 94 },

{ "SWITCH_CHARSET", 95 },

{ "BUTTON_A", 96 },

{ "BUTTON_B", 97 },

{ "BUTTON_C", 98 },

{ "BUTTON_X", 99 },

{ "BUTTON_Y", 100 },

{ "BUTTON_Z", 101 },

{ "BUTTON_L1", 102 },

{ "BUTTON_R1", 103 },

{ "BUTTON_L2", 104 },

{ "BUTTON_R2", 105 },

{ "BUTTON_THUMBL", 106 },

{ "BUTTON_THUMBR", 107 },

{ "BUTTON_START", 108 },

{ "BUTTON_SELECT", 109 },

{ "BUTTON_MODE", 110 },

// NOTE: If you add a new keycode here you must also add it to several other files.

// Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.

{ NULL, 0 }

};

// See also policy flags in Input.h.

static const KeycodeLabel FLAGS[] = {

{ "WAKE", 0x00000001 },

{ "WAKE_DROPPED", 0x00000002 },

{ "SHIFT", 0x00000004 },

{ "CAPS_LOCK", 0x00000008 },

{ "ALT", 0x00000010 },

{ "ALT_GR", 0x00000020 },

{ "MENU", 0x00000040 },

{ "LAUNCHER", 0x00000080 },

{ "VIRTUAL", 0x00000100 },

{ NULL, 0 }

};

EventHub.cpp定义设备节点所在的路径

Static const char *device_path="/dev/input" //输入设备的目录

处理时,搜索路径下面的所有input 在bool EventHub::openPlatformInput(void)

{

/*

* Open platform-specific input device(s).

*/

int res;

mFDCount = 1;

mFDs = (pollfd *)calloc(1, sizeof(mFDs[0]));

mDevices = (device_t **)calloc(1, sizeof(mDevices[0]));

mFDs[0].events = POLLIN;

mFDs[0].revents = 0;

mDevices[0] = NULL;

#ifdef HAVE_INOTIFY

mFDs[0].fd = inotify_init();

res = inotify_add_watch(mFDs[0].fd, device_path, IN_DELETE | IN_CREATE);

if(res < 0) {

LOGE("could not add watch for %s, %s\n", device_path, strerror(errno));

}

#else

/*

* The code in EventHub::getEvent assumes that mFDs[0] is an inotify fd.

* We allocate space for it and set it to something invalid.

*/

mFDs[0].fd = -1;

#endif

res = scanDir(device_path);//查找设备

if(res < 0) {

LOGE("scan dir failed for %s\n", device_path);

}

return true;

}

从目录中查找设备

int EventHub::scanDir(const char *dirname)

{

char devname[PATH_MAX];

char *filename;

DIR *dir;

struct dirent *de;

dir = opendir(dirname);

if(dir == NULL)

return -1;

strcpy(devname, dirname);

filename = devname + strlen(devname);

*filename++ = '/';

while((de = readdir(dir))) {

if(de->d_name[0] == '.' &&

(de->d_name[1] == '\0' ||

(de->d_name[1] == '.' && de->d_name[2] == '\0')))

continue;

strcpy(filename, de->d_name);

openDevice(devname); //打开设备

}

closedir(dir);

return 0;

}

事件的处理主要是在getEvent()方法中, 处理过程是一个无限循环,调用阻塞函数来等待事件

部分代码如下:

int pollResult = poll(mFDs, mFDCount, -1);

acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);

if (pollResult <= 0) {

if (errno != EINTR) {

LOGW("poll failed (errno=%d)\n", errno);

usleep(100000);

}

}

Android的事件处理一般经过两个步骤

1 将input设备的整数类型事件转换成表示按键的字符串

键盘布局文件(*.kl)完成第一步的转换, 路径为目标文件系统的system/usr/keylayout

Qwert.kl全键盘对应键值,其中第二列的整数表示驱动程序中Event事件的名称,

第三列表示在KEYCODESK数组中对应的literal

这里完成了驱动程序的事件到字符串的转换

2 将表示按建的字符串转换成android 的键盘码

keycodelable.h(记录键值,位于/frameworks/base/include/ui)

通过查KEYCODES数组(keyCharacterMap.h, 其目录为/framework/base/core./java/android/view/keyevent.java),将literal 字符串转换成value 整数值

不同系统的开发,对于不同的硬件, 只需要写不同的键盘布局即可(让驱动程序中的整数值对应到android的按键名称上)

如果需要增加按键在用户程序中进行处理,除了keyCharacterMap.h和KeyEvent.java两个文件。还需要改 tools/puppet_master/puppetMaster.nav_keys.py

/frameworks/base/core/res/res/values/attrs.xml

Surface系统

关系如下:

Libui提供本地的surface 系统框架

Sufacefilnger完成本地接口的实现

Java框架层主要调用surface向UI提供接口

本地部分可以使用ISurface接口

Surface系统的本地接口 未看完?????

surfaceFlinger本地代码(未看完?????????)

整体结构

SurfaceFilinger是surface部分的本地实现,

代码路径为:/frameworks/base/libs/surfaceflinger_client/surfaceFlinger

生成目标的动态库为:libsurfaceflinger.so 没有头文件,外部进行调用的接口是libui的头文



Skia和2D图形系统

Android 的2D系统的底层由skia本地库实现,通过JNI向java层提供图形功能接口,

Skia 底层库(是一个底层的图形,图像,动画,SVG,文本等多方面的图形库,是一个c++本地库)

代码路径为:external/skia

包含三个库:

Libcorecg.so Core Cg 核心图形库 (调试信息,数学计算,内存管理,)

Liblibsgl.so GL(Skia图形库,)

其原码文件主要在:

Libskiagl.so skia-opengl glue library

Android 图形系统的JNI接口

路径为:

/frameworks/base/core/jni/android/graphics

Canvas中的initRaater()和initGl()两个函数与skia本地库联系起来

static SkCanvas* initRaster(JNIEnv* env, jobject, SkBitmap* bitmap) {

return bitmap ? new SkCanvas(*bitmap) : new SkCanvas;

}

static SkCanvas* initGL(JNIEnv* env, jobject) {

return new SkGLCanvas;

}

Android 的图形包

路径为;

/frameworks/base/graphics/java/android/graphics

当draw内容时需要的四个组件:

Bitmap 保持像素

Canvas 处理调用

(rect,path,text,bitmap) 绘制内容

Paint 用来描述颜色和样式

Android 的 OpenGL 系统和3D图形系统

本地代码

头文件四路径为:/frameworks/base/opengl/include/EGL

/frameworks/base/opengl/include/GLES

源代码的目录为:/frameworks/base/opengl/libagl

/frameworks/base/opengl/libs

编译后,本地代码将会产生三个库:

libGLESv1_CM.so 对应GLES

libEGL.so 对应EGL

Java 框架代码

Android 的OpenGL的实现方式

使用软件库 (libagl.so)

使用硬件库(libhgl.so)

Egl.cpp文件中 gl-hooks_t结构描述了OpenGL所支持的各种API

实际的符号在gl_entries.in t

函数的定义形:

GL_ENTRY(void,// 返回值

glColor4f,// 名称

GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)//参数列表

Egl_entries.in

函数定义形式:

Android 的OpenGL的本地测试代码

测试代码的路径为:

/frameworks/base/opengl/tests

Angeles filter finish textures tritex

OpenGL的JNI代码

OpenGL 引擎向上提供的JNI接口, 供java调用,主要由两个文件提供

/frameworks/base/core/jni/com_google_android_gles_jni_EGLImpl.cpp(管理功能)

/frameworks/base/core/jni/com_google_android_gles_jni_GLImpl.cpp (功能函数)

openGl中的java类

openGl的java标准类是javax中的一部分,路径分别是:

/frameworks/base/opengl/java/javax/microedition/khronos/opengles/ 主要文件是:GL10和GL11

/frameworks/base/opengl/java/javax/microedition/khronos/egl 主要文件是:EGL10和EGL11

Android 中继承方法实现OpenGL标准类,路径为:

/frameworks/base/opengl/java/com/google/android/gles_jni

该路径下的文件的各个类对java标准类的继承关系为:

Public class GLImpl implements GL10, GL10Ext, GL11, GL11Ext, GL11ExtensionPack{}

public class EGLSurfaceImpl extends EGLSurface{}

public class EGLImpl implements EGL10 EGLConfigImpl. Extends EGLConfig{}

public class EGLConfigImpl extends EGLConfig{}

public class EGLContextImpl extends EGLContext{}

在android 的java应用层 ,不会调用com.google.android.gles_jni路径下的类,

只会调用/frameworks/base/opengl/java/javax/microedition/khronos/opengles下的接口

openGL 标准接口到android 系统的媒介(通过调用com.google.android.gles_jn下的类和android基础gui系统的类实现了GLsurfaceView)

/frameworks/base/opengl/java/android/opengl

public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback{}

所以GLSurfaceView()也是一个ui元素

如果是在应用层使用openGL,就是继承 GLSurfaceView类并调用OpenGL的标准接口
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: