android系统学习笔记四

 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.hKeyEvent.java两个文件。还需要改 tools/puppet_master/puppetMaster.nav_keys.py

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

Surface系统

      关系如下:

             Libui提供本地的surface 系统框架

             Sufacefilnger完成本地接口的实现

             Java框架层主要调用surfaceUI提供接口

             本地部分可以使用ISurface接口

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

             

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

           整体结构

           SurfaceFilingersurface部分的本地实现,

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

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

           件

           

Skia2D图形系统

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

   

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  

     

OpenGLJNI代码

     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

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

/frameworks/base/opengl/java/javax/microedition/khronos/opengles/ 主要文件是:GL10GL11
/frameworks/base/opengl/java/javax/microedition/khronos/egl   主要文件是:EGL10EGL11

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的标准接口

posted @ 2012-09-03 15:07  retacn_yue  阅读(390)  评论(0编辑  收藏  举报