在android 10.0的系统rom定制化开发工作中,在系统中recoverv的页面也是相关重要的一部分,在系统recovery ta升级等功能,都是需要recoverv功能的,在某些产品定制化中
在recovery的时候,发现居然旋转了180度,接下来分析下recovery关于屏幕显示方向的相关源码,来修改这个功能
bootable/recovery/minui/include/minui/minui.h
boottable/recovery/minui/graphics.cpp
recovery页面旋转180度问题的解决方案的核心功能实现中,Android10.0的Recovery中的相关系统源码中,recoverv是以bootablerecovery下的minui库作为基础,采用的是直接存取framebuffer的万式,来完成recovery中所需的各种UI的绘制。
在recoverv的源码中,跟ui显示相关的代码的大致结构为:
boottable/recovery/minui下resources.cpp,graphics.cpp
其中resources.cpp提供的api主要用于图片资源的读取和加载
graphics.cpp负责具体完成各类ui的绘制既然graphics.cpp是负责各类UI的绘制那么旋转方向的修改 就要从这里入手了。
#include "graphics.h"
#include
#include
#include
#include
#include
#include
#include "graphics_adf.h"
#include "graphics_drm.h"
#include "graphics_fbdev.h"
#include "minui/minui.h"
...
int gr_measure(const GRFont* font, const char* s) {
if (font == nullptr) {
return -1;
}
return font->char_width * strlen(s);
}
int gr_font_size(const GRFont* font, int* x, int* y) {
if (font == nullptr) {
return -1;
}
*x = font->char_width;
*y = font->char_height;
return 0;
}
// Increments pixel pointer right, with current rotation.
static void incr_x(uint32_t** p, int row_pixels) {
if (rotation == GRRotation::LEFT) {
*p = *p - row_pixels;
} else if (rotation == GRRotation::RIGHT) {
*p = *p + row_pixels;
} else if (rotation == GRRotation::DOWN) {
*p = *p - 1;
} else { // GRRotation::NONE
*p = *p + 1;
}
}
// Increments pixel pointer down, with current rotation.
static void incr_y(uint32_t** p, int row_pixels) {
if (rotation == GRRotation::LEFT) {
*p = *p + 1;
} else if (rotation == GRRotation::RIGHT) {
*p = *p - 1;
} else if (rotation == GRRotation::DOWN) {
*p = *p - row_pixels;
} else { // GRRotation::NONE
*p = *p + row_pixels;
}
}
void gr_fill(int x1, int y1, int x2, int y2) {
x1 += overscan_offset_x;
y1 += overscan_offset_y;
x2 += overscan_offset_x;
y2 += overscan_offset_y;
if (outside(x1, y1) || outside(x2 - 1, y2 - 1)) return;
int row_pixels = gr_draw->row_bytes / gr_draw->pixel_bytes;
uint32_t* p = PixelAt(gr_draw, x1, y1, row_pixels);
uint8_t alpha = static_cast<uint8_t>(((gr_current & alpha_mask) >> 24));
if (alpha > 0) {
for (int y = y1; y < y2; ++y) {
uint32_t* px = p;
for (int x = x1; x < x2; ++x) {
*px = pixel_blend(alpha, *px);
incr_x(&px, row_pixels);
}
incr_y(&p, row_pixels);
}
}
}
int gr_init_font(const char* name, GRFont** dest) {
GRFont* font = static_cast<GRFont*>(calloc(1, sizeof(*gr_font)));
if (font == nullptr) {
return -1;
}
int res = res_create_alpha_surface(name, &(font->texture));
if (res < 0) {
free(font);
return res;
}
// The font image should be a 96x2 array of character images. The
// columns are the printable ASCII characters 0x20 - 0x7f. The
// top row is regular text; the bottom row is bold.
font->char_width = font->texture->width / 96;
font->char_height = font->texture->height / 2;
*dest = font;
return 0;
}
int gr_init() {
// pixel_format needs to be set before loading any resources or initializing backends.
std::string format = android::base::GetProperty("ro.minui.pixel_format", "");
if (format == "ABGR_8888") {
pixel_format = PixelFormat::ABGR;
} else if (format == "RGBX_8888") {
pixel_format = PixelFormat::RGBX;
} else if (format == "BGRA_8888") {
pixel_format = PixelFormat::BGRA;
} else {
pixel_format = PixelFormat::UNKNOWN;
}
int ret = gr_init_font("font", &gr_font);
if (ret != 0) {
printf("Failed to init font: %d, continuing graphic backend initialization without font file\n",
ret);
}
auto backend = std::unique_ptr<MinuiBackend>{ std::make_unique<MinuiBackendAdf>() };
gr_draw = backend->Init();
if (!gr_draw) {
backend = std::make_unique<MinuiBackendDrm>();
gr_draw = backend->Init();
}
if (!gr_draw) {
backend = std::make_unique<MinuiBackendFbdev>();
gr_draw = backend->Init();
}
if (!gr_draw) {
return -1;
}
gr_backend = backend.release();
int overscan_percent = android::base::GetIntProperty("ro.minui.overscan_percent", 0);
overscan_offset_x = gr_draw->width * overscan_percent / 100;
overscan_offset_y = gr_draw->height * overscan_percent / 100;
gr_flip();
gr_flip();
if (!gr_draw) {
printf("gr_init: gr_draw becomes nullptr after gr_flip\n");
return -1;
}
std::string rotation_str =
android::base::GetProperty("ro.minui.default_rotation", "ROTATION_NONE");
if (rotation_str == "ROTATION_RIGHT") {
gr_rotate(GRRotation::RIGHT);
} else if (rotation_str == "ROTATION_DOWN") {
gr_rotate(GRRotation::DOWN);
} else if (rotation_str == "ROTATION_LEFT") {
gr_rotate(GRRotation::LEFT);
} else { // "ROTATION_NONE" or unknown string
gr_rotate(GRRotation::NONE);
}
rotation = GRRotation::RIGHT;//add code
if (gr_draw->pixel_bytes != 4) {
printf("gr_init: Only 4-byte pixel formats supported\n");
}
return 0;
}
void gr_rotate(GRRotation rot) {
rotation = rot;
}
recoverv页面旋转180度问题的解决方案的核心功能实现中,从graphics.cpp中的上述源码中,可以看出 r get width (const GRSurtace?surface)是获取屏幕的宽度
gr get height(const GRSurface* surface) 获取屏幕的高度
gr init font(const char* name.GRFont** dest) 获取字体大小
gr init() 主要是设置RGB 和 屏幕旋转方向,gr cear()清除一些绘制屏幕参数,重新绘制屏幕显示相关的参数接下来看下相关的设置recoverv的方向的相关代码的分析
gr rotate(DEFAULT ROTATION):
在gr init()的方法中中的gr rotate(DEFAULT ROTATION):设置屏幕的方向为默认方向而在minui.h中定义了recoverv方向的相关参数,如下
enum GRRotation {
ROTATION_NONE = 0,
ROTATION_RIGHT = 1,//90
ROTATION_DOWN = 2,//180
ROTATION_LEFT = 3,//270
};
recovev页面旋转180度问题的解决方案的核心功能实现中,根据GRRotation 的相关参数可以得知,ROTATION RIGHT就是屏幕旋转90度,而ROTATION DOWN就是屏幕旋转180度,而ROTATION LEFT就是屏幕旋转270度,
所以设置横屏上下翻转就需要把屏幕方向修改为ROTATION LEFT就可以了具体修改为:
int gr_init() {
....
std::string rotation_str =
android::base::GetProperty("ro.minui.default_rotation", "ROTATION_NONE");
if (rotation_str == "ROTATION_RIGHT") {
gr_rotate(GRRotation::RIGHT);
} else if (rotation_str == "ROTATION_DOWN") {
gr_rotate(GRRotation::DOWN);
} else if (rotation_str == "ROTATION_LEFT") {
gr_rotate(GRRotation::LEFT);
} else { // "ROTATION_NONE" or unknown string
gr_rotate(GRRotation::NONE);
}
+ rotation = GRRotation::LEFT;//add code
....
}
recover页面旋转180度问题的解决方案的核心功能实现中,在上述的graphics.cpp中的上述源码中分析得知,在gr init) 主要是设置RGB和 屏幕旋转方向,所以就是根据返回的
rotation的值来判断当前屏幕的旋转方向的,所以通过上述的修改方法,在gr init()
增加rotation = GRRotation:LEFT://add code来作为当前屏幕的旋转方法,就确保旋转180度,就是实现了功能要求