framebufferandroid
‘壹’ Android开机logo简单修改方法
Android 手机开机logo主要分为2部分:
1.按下开机键后linux开机显示开机第一帧部分。此Kernel中的画面在ANDROID里默认是关闭的,需要打开时可以配置打开kernel下面2个选项:
CONFIG_FRAMEBUFFER_CONSOLE
CONFIG_LOGO
意即KERNEL支持帧缓冲控制台,并且显示开机LOGO
2.开机过程从开机画面已经进入了android的范围,在INIT进程启动的时候加载的开机动画。
1).如果想要修改手机的开机第一帧,以高通SDM450平台为例,讲解一下开机第一帧logo的制作过程:
首先准备好需要更换的显示第一帧的logo图标,只需要显示图案的部分即可。比如安卓源码的小企鹅图标,为宽88 高102像素的bmp格式。
1 ps-截图-垂直翻转-另存为bmp-24位-高级模式-RGB888
2 .bmp文件命名为splash.bmp,在linux下执行xxd -i splash.bmp > splash.h
3 h文件去文件头54字节
unsigned char splash_24_bmp[] = {
0x42, 0x4d, 0x98, 0x62, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00,
0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, 0x5a, 0x00,
0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc3, 0x0e, 0x00, 0x00, 0xc3, 0x0e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4 查看splash.bmp-属性-摘要-宽88 高 102
5 修改文件
\android\bootable\bootloader\lk\platform\msm_shared\include\splash.h
imageBuffer_rgb888[] 此数组用步骤3制作出的数组内容
#define SPLASH_IMAGE_WIDTH 88
#define SPLASH_IMAGE_HEIGHT 102
6 bmptool工具上验证效果
txt2bin->生成bin->直接把bin拖入->设宽高为源bmp文件的宽高,24位
如果显示正常,直接如此修改验证就ok,如果显示有倾斜,先改小源图片的大小,重复此步骤制作。
bmptool工具验证的效果如此图显示, 则表示正常。
以上步骤,开机第一帧图片就修改ok。
2.开机动画修改
android\vendor\qcom\proprietary\qrdplus\Extension\apps\BootAnimation 目录下修改
bootanimation.zip
shutdownanimation.zip
这个压缩文件可以解压后参考源码中图片修改,修改后mm编译后验证即可。
以上就是Android修改开机动画的一种简单方法。
‘贰’ 怎么修改android 启动过程中的第二个开机画面
第一个开机画面是在内核启动的过程中出现的,它是一个静态的画面。第二个开机画面是在init进程启动的过程中出现的,它也是一个静态的画面。第三个开机画面是在系统服务启动的过程中出现的,它是一个动态的画面。无论是哪一个画面,它们都是在一个称为帧缓冲区(frame buffer,简称fb)的硬件设备上进行渲染的。接下来,我们就分别分析这三个画面是如何在fb上显示的。
1. 第一个开机画面的显示过程
Android系统的第一个开机画面其实是Linux内核的启动画面。在默认情况下,这个画面是不会出现的,除非我们在编译内核的时候,启用以下两个编译选项:
CONFIG_FRAMEBUFFER_CONSOLE
CONFIG_LOGO
第一个编译选项表示内核支持帧缓冲区控制台,它对应的配置菜单项为:Device Drivers ---> Graphics support ---> Console display driver support ---> Framebuffer Console support。第二个编译选项表示内核在启动的过程中,需要显示LOGO,它对应的配置菜单项为:Device Drivers ---> Graphics support ---> Bootup logo。配置Android内核编译选项可以参考在Ubuntu上下载、编译和安装Android最新内核源代码(Linux Kernel)一文。
帧缓冲区硬件设备在内核中有一个对应的驱动程序模块fbmem,它实现在文件kernel/goldfish/drivers/video/fbmem.c中,它的初始化函数如下所示:
/**
* fbmem_init - init frame buffer subsystem
*
* Initialize the frame buffer subsystem.
*
* NOTE: This function is _only_ to be called by drivers/char/mem.c.
*
*/
static int __init
fbmem_init(void)
{
proc_create("fb", 0, NULL, &fb_proc_fops);
if (register_chrdev(FB_MAJOR,"fb",&fb_fops))
printk("unable to get major %d for fb devs\n", FB_MAJOR);
fb_class = class_create(THIS_MODULE, "graphics");
if (IS_ERR(fb_class)) {
printk(KERN_WARNING "Unable to create fb class; errno = %ld\n", PTR_ERR(fb_class));
fb_class = NULL;
}
return 0;
}
这个函数首先调用函数proc_create在/proc目录下创建了一个fb文件,接着又调用函数register_chrdev来注册了一个名称为fb的字符设备,最后调用函数class_create在/sys/class目录下创建了一个graphics目录,用来描述内核的图形系统。
模块fbmem除了会执行上述初始化工作之外,还会导出一个函数register_framebuffer:
EXPORT_SYMBOL(register_framebuffer);
这个函数在内核的启动过程会被调用,以便用来执行注册帧缓冲区硬件设备的操作,它的实现如下所示:
/**
* register_framebuffer - registers a frame buffer device
* @fb_info: frame buffer info structure
*
* Registers a frame buffer device @fb_info.
*
* Returns negative errno on error, or zero for success.
*
*/
int
register_framebuffer(struct fb_info *fb_info)
{
int i;
struct fb_event event;
......
if (num_registered_fb == FB_MAX)
return -ENXIO;
......
num_registered_fb++;
for (i = 0 ; i < FB_MAX; i++)
if (!registered_fb[i])
break;
fb_info->node = i;
mutex_init(&fb_info->lock);
fb_info->dev = device_create(fb_class, fb_info->device,
MKDEV(FB_MAJOR, i), NULL, "fb%d", i);
if (IS_ERR(fb_info->dev)) {
/* Not fatal */
printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev));
fb_info->dev = NULL;
} else
fb_init_device(fb_info);
......
registered_fb[i] = fb_info;
event.info = fb_info;
fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event);
return 0;
}
由于系统中可能会存在多个帧缓冲区硬件设备,因此,fbmem模块使用一个数组registered_fb保存所有已经注册了的帧缓冲区硬件设备,其中,每一个帧缓冲区硬件都是使用一个结构体fb_info来描述的。
‘叁’ android 屏幕显示 怎么刷新 framebuffer 详解
Android屏幕绘制基本与linux相同,都是使用Framebuffer来绘制屏幕,设备为/dev/graphic/fb0.Framebuffer 存储在内存或者显存中,比如一个800 ×600的屏幕,每个像素点为16位色,那么Framebuffer的大小就为(800 × 600 × 16/8) byte
手机的LCD屏幕通过显存中当前的Framebffer和缓存的framebuffer来绘制屏幕上的每一个像素点.
具体顺序为:
1打开framebuffer设备;
2通过ioctl取得fixed screen information;(ioctl(fd,FBIOGET_FSCREENINFO, &finfo))
3通过ioctl取得variable screen information;(ioctl(fd,FBIOGET_VSCREENINFO, &vinfo))
4通过mmap映射设备内存到进程空间;(记得区分内核空间和用户空间,用户空间是无法对物理内存直接读写的)
5写framebuffer;
6终止。(记得终止时一定要取消映射,并close掉句柄)
‘肆’ 如何在Android里面使用代码截屏
回答:Android SDK的截屏
方法步骤:如下
方法一:
(1)主要就是利用SDK提供的View.getDrawingCache()方法。网上已经有很多的实例了。首先创建一个android project,然后进行Layout,画一个按键
HelloAndroid.java实现代码为:packagecom.example.helloandroid;
这个代码会在按下app中按键的时候自动在手机的/sdcard/目录下生成一个时间戳命名的png截屏文件。
这种截屏有一个问题,就是只能截到一部分,比如电池指示部分就截不出来了。
(2)在APK中调用“adb shell screencap -pfilepath” 命令
该命令读取系统的framebuffer,需要获得系统权限:
(1). 在AndroidManifest.xml文件中添加
(2). 修改APK为系统权限,将APK放到源码中编译,
(3).利用系统的API,实现Screenshot,这部分代码是系统隐藏的,需要在源码下编译,
1).修改Android.mk, 添加系统权限
LOCAL_CERTIFICATE := platform
2).修改AndroidManifest.xml 文件,添加
权限
方法二:
Android ddmlib进行截屏
Android本地编程(Native Programming)读取framebuffer
(1)命令行,框架的截屏功能是通过framebuffer来实现的,所以我们先来介绍一下framebuffer。
Linux FrameBuffer 本质上只是提供了对图形设备的硬件抽象,在开发者看来,FrameBuffer 是一块显示缓存,往显示缓存中写入特定格式的数据就意味着向屏幕输出内容。所以说FrameBuffer就是一块白板。例如对于初始化为16 位色的FrameBuffer 来说, FrameBuffer中的两个字节代表屏幕上一个点,从上到下,从左至右,屏幕位置与内存地址是顺序的线性关系。帧缓存有个地址,是在内存里。我们通过不停的向frame buffer中写入数据, 显示控制器就自动的从frame buffer中取数据并显示出来。全部的图形都共享内存中同一个帧缓存。
方法三:Android截屏实现思路
Android系统是基于Linux内核的,所以也存在framebuffer这个设备,我们要实现截屏的话只要能获取到framebuffer中的数据,然后把数据转换成图片就可以了,android中的framebuffer数据是存放在 /dev/graphics/fb0 文件中的,所以我们只需要来获取这个文件的数据就可以得到当前屏幕的内容。
现在我们的测试代码运行时候是通过RC(remote controller)方式来运行被测应用的,那就需要在PC机上来访问模拟器或者真机上的framebuffer数据,这个的话可以通过android的ADB命令来实现。
注意:
1、需要在AndroidManifest.xml中加入代码:android:sharedUserId="android.uid.system"。
2、由于调用了@hide的API,所以编译得时候请使用makefile编译。或者通过在Eclipse中添加Jar文件通过编译。
3、此代码只在Android4.0中使用过,2.3的就没去做测试了。
补充说明:
利用TakeScreenShotService截图Android手机一般都自带有手机屏幕截图的功能:在手机任何界面(当然手机要是开机点亮状态),通过按组合键,屏幕闪一下,然后咔嚓一声,截图的照片会保存到当前手机的图库中,
对手机android源码中通过组合键屏幕截图的整个流程有个大体了解了,在改动中熟悉按键的捕获原理,并且清楚调用的截屏函数接口即可。