Android系统移植讲解硬件需求•RAM:512MB•FLASH:256MB•CPU:ARM平台指令集要求ARM9Family以上,ARMv5以上指令集,mips平台指令集要求MIPS32revision2-Little-Endian,O32软件需求•Linux2.6以上版本,目前froyo(v2.2)对应于linux2.6.32-linux2.6.35版本,最好是使用android官方网可以下载到的代码【目前linux2.6.23官方网下不了,最低也是linux2.6.25】•Android源码移植主要四大模块•1、bootload运行起来,无论使用u-boot还是fastboot,主要是关于flash分区问题•2、linuxkernel主要涉及到androiddriver层驱动代码•3、android系统移植•4、应用程序移植【后面则详细讲解各个模块的移植过程】Bootload•一般使用u-boot或者fastboot,主要的工作就是flash分区问题,一般划分为如下几个分区:1、fastboot【快速启动,裸板启动区】2、recovery【系统恢复分区】recovery就好比外套,fastboot就好比内裤3、kernel【linux内核分区】4、system【android核心系统分区】5、userdata【用户数据分区】6、factorydata【工厂数据分区】linuxkernel由于android系统对于linuxkernel的限制,首先是要选定合适的kernel版本,然后剩下的工作就是整个一个全新的kernel代码,系统移植有三份kernel代码需要集成•1、机顶盒厂商提供的linux源码,包含有针对平台的驱动代码及修改•2、官方网站下载的linux源码,与厂商的版本可能有所不同•3、增加了androidlinuxdriver的源码,这部分已经从linuxkernel中分离开来,需要单独移植所以首要的问题是将三份统一到一起,目标是支持厂商驱动,支持android驱动以及更新到一定linux内核版本(androiddriver+sdkdriver+linuxkernel)这部分工作需要深入到linuxkerneldriver层代码,一定的技术功底+细心Kernel移植要点•1、尽可能将硬件平台相关的代码从旧版移植到新版本•2、针对硬件平台相关的代码,以旧版本为主,毕竟旧版的是可以正常运行的版本,•3、非硬件平台相关代码尽量使用新版本•4、若遇到不知如何处理问题,先跳过,记录下该文件及修改点,这部分需要多参考部份原码进行移植•5、对于配置.config文件,需要根据相关功能进行修改及配置,可以从模拟器上拿到config.gz文件解开即可•6、编译及测式,采用nfs挂载根文件系统,一般遇到kernelpanic错误时,打开kerneldebug,printk加打印,或者disable此功能进行调试我的移植过程(一)•1、移植boot-loader和linux2.6内核到目标平台上,让linux内核可以启动起来,基本的驱动运行正常•2、修改内核配置文件,打开Android必须的驱动,比如binder,logger,ashemem,pmem等•3、为了提高启动速度,采用ramdisk,将android文件系统的部分内容压缩到内核中•4、根据分区表修改内核启动参数,例如mem=352Mconsole=ttyAMA0,115200root=/dev/mtdblock2rootfstype=yaffs2rw启动的第一个应用程序是/init•5、确保控制台的设置和硬件保持一致,如:硬件上串口用的是UART1,则内核启动参数中设置有console=ttyAMA0与启动参数中保持一致我的移植过程(二)•6、修改android源代码system/core/rootdir目录下的init.rc文件,android默认yaffs2文件系统,所以制作system.img也是yaffs2及linuxkernel配置成支持yaffs2文件系统,首先将android文件系统修改成可读写mountrootfsrootfs/rwremount•7、编译busybox将其加入到system中作为命令使用总结:•android的移植按如下流程:•1、androidlinux内核的普通驱动移植,让内核可以在目标平台上运行起来。•2、正确挂载文件系统,确保内核启动参数和android源代码system/core/rootdir目录下的init.rc中的文件系统挂载正确。•3、调试控制台,让内核启动参数中的console参数以及android源代码system/core/init/init.c中的console_name设置和硬件保持一致•4、打开android相关的驱动(logger,binder等),串口输入logcat看logger驱动起来,没有的话调试logger驱动。Android系统移植Android从Linux系统启动有4个步骤;1、init进程启动(system\core\init\中的main函数)init进程,它是一个由内核启动的用户级进程。内核自行启动(已经被载入内存,开始运行,并已初始化所有的设备驱动程序和数据结构等)之后,就通过启动一个用户级程序init的方式,完成引导进程,此后android将接管所有工作,这里涉及到两个脚本文件:init.rc及init.xxx.rc【arch】2、Native服务启动Servicemanager和zygote进程就奠定了Android的基础。Zygote这个进程起来才会建立起真正的Android运行空间,主要是Zytote创建JAVA虚拟机,装载classes等【受精卵,典型的C/S结构,请求生产,fork子进程,ok,生了】启动步骤3、SystemServer服务循环框架Android服务启动不停的通过Zygotefork新的进程,并建立了一大堆服务,并addService到serviceManager,Android的所有服务循环框架都是建立SystemServer@(SystemServer.java)上4、Home启动启动完所有的Android服务后,然后启动第一个home应用程序,即第一个启动HomeActivity应用程序总体启动框架图示HAL接口实现•Android系统的移植就是kernel+HAL层接口实现【不过这是最理想的做法了,实现上简单的这么做难道很大的】•HardwareAbtractionLayer,即硬件抽象层,目的就是使用自已平台的硬件适配层为系统加速,发挥硬件平台的最大性能,未定义则使用软实现。•HAL层调用方式JNI-通用硬件模块-硬件模块-内核驱动接口,即androidframeworks中JNI调用/hardware/libhardware/hardware.c中定义的hw_get_module函数来获取硬件模块,然后调用硬件模块中的方法,硬件模块中的方法直接调用内核接口完成相关功能接口层调用关系HAL接口定义原则•1、同类设备有多个时只定义一个设备名称,调用open函数全部打开【对于设备打开需要很多资源的并且很少使用的可以后续分配内存,以便内存浪费】•2、接口定义以效率为先,发挥平台最大性能•3、模块划分明确,方便调试及集成•4、类型的结构充分利用CStruct的数据排列特性:基本结构体放置在最前面,本地私有放置在后面,满足了抽象的需要,以structhw_module_tcommon;及structhw_device_tcommon;置前主要模块介绍•hardware.h通用硬件模块头文件•gralloc.h主要定义graphicsdevice,至少需要双缓冲framebuffer,硬件没有则使用ashemem或pmem实现•copybit.h2D加速函数,如blit/stretch•overlay.h加速视频数据输出,叠加于主显示区之上,机顶盒上一般使用视频层输出•tuner.h锁频功能定义•demux.h解复用功能定义•media.h媒体播放功能定义,包含avdec/output,并且虚拟定义了videowindow概念•OpenGl3D接口实现,移植平台前期可以先行使用软件libagl.soHAL后续解读•生成的所有模块都以*.so动态库,各个动态库之间定义了一个hal_common.so用于各个动态间全局变量调用,对上层接口透明•下面直接讲解HAL层代码头文件关于图形部分移植•1、如果处理器只有2D硬件加速而没有3D硬件加速,则可以利用opengl中的libagl,实现封装在libagl里的copybit,即libagl+copybit•2、如果处理器2D/3D硬件加速均有,那么可以丢开copybit,去实现openGLES2D/3DAPI的加速功能•3、对于hisi来说,有专门的2D和3D硬件加速,但由于3D对于数据(surfcae或者纹理)搬移速度不理想(40ms-7ms差异),所以实现glDrawArrays实现copybit功能实现加速逻辑加载流程(egl.cpp)•全局变量gEGLImpl定义IMPL_HARDWARE=0,IMPL_SOFTWARE•利用egl_init_drivers_locked填充gEGLImp数组变量,即加载不同的动态(硬件和软件加速驱动)libGLES_android.so软件库【libagl】libGLES_HWxxxxx.so硬件库OpenGl的函数赋值于hooks结构•利用配置文件/system/lib/egl/egl.cfg进行选择•loader.open-load_driver进行函数指针赋值Copybit功能实现(2D加速)•主要包含块搬移及位图拉伸或旋转的功能,实现copybit_device_t结构即可•基本调用层次关系,对于OpenGl调用补充下:•可选宏定义LIBAGL_USE_GRALLOC_COPYBITSglDrawArrays-drawPrimitivesTriangleFan-copybit调用到平台Copybit函数,使用2D对surfaceFlinger实现块搬移LayerBufferOpenGlCopybit硬件抽象层硬件支持,hisi即为TDE层图形系统层次关系显示FrameBuffer在系统中就是一段内存,GDI的工作就是把需要输出的内容放入到该段内存的某个位置,ui层调用代码FramebufferNativewindow.cpp图形缓冲区管理•接口体现在gralloc.h接口中,实现硬件FrameBuffer内存管理及共享缓存管理•接口调用逻辑:•gralloc_device_open根据不同情况:gpu分配空间,调用gralloc_alloc,hisi统一使用fb实现fb分配空间,调用fb_device_open,打开/dev/fb0其它内存分配,调用gralloc_alloc_buffer使用PMEM或者ASHMEM•mapFrameBufferLocked真正分配fb缓冲区函数,这里一次性打开所有fb,后面直接偏移地址使用即可(gralloc_alloc_framebuffer_locked)•句柄传递使用private_handle_t与buffer_handle_t转换,两者继承关系:structprivate_handle_t:publicnative_handle图形3D实现•接口代码:android\frameworks\base\opengl•实现代码:graphics\3d\driver\openGL\egl•实现接口entries.inAlsa-lib音频部分•1、首先linuxkernel+androidexternal(alsa-utils+alsa-lib)代码编译•2、实现hardware接口,包含AudioStreamIn,AudioStreamOut及Mixer•3、统一调用linuxkernel接口sn