有时候修改了屏幕的方向,recoveryUI的方向却没有跟着改变。
7.1系统修改recoveryUI方向
①新增文件graphics_rotate.cpp
- bootable/recovery/minui/graphics_rotate.cpp
/*
* Copyright (C) 2014 MediaTek Inc.
* Modification based on code covered by the mentioned copyright
* and/or permission notice(s).
*/
#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>
#include <inttypes.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/cdefs.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <linux/fb.h>
#include <linux/kd.h>
#include "minui.h"
#include "graphics.h"
GRSurface __gr_canvas;
GRSurface* gr_canvas = NULL;
int rotate_index=-1;
static void print_surface_info(GRSurface *s, const char *name)
{
printf("[graphics] %s > Height:%d, Width:%d, PixelBytes:%d, RowBytes:%d, Size:%d, Data: 0x%08" PRIxPTR "\n",
name, s->height, s->width, s->pixel_bytes, s->row_bytes, s->height* s->row_bytes, (uintptr_t) s->data);
}
// Read configuration from LCM_PHYSICAL_ROTATION
#ifndef LCM_PHYSICAL_ROTATION
#define LCM_PHYSICAL_ROTATION "undefined"
#endif
static int rotate_config(GRSurface *gr_draw)
{
printf("[graphics] %s > Height:%d, Width:%d, PixelBytes:%d, RowBytes:%d, Size:%d, Data: 0x%08" PRIxPTR "\n",
name, s->height, s->width, s->pixel_bytes, s->row_bytes, s->height* s->row_bytes, (uintptr_t) s->data);
}
// Read configuration from LCM_PHYSICAL_ROTATION
#ifndef LCM_PHYSICAL_ROTATION
#define LCM_PHYSICAL_ROTATION "undefined"
#endif
static int rotate_config(GRSurface *gr_draw)
{
if (rotate_index<0)
{
if (gr_draw->pixel_bytes != 4) rotate_index=0; // support 4 bytes pixel only
else if (0 == strncmp(LCM_PHYSICAL_ROTATION, "90", 2)) rotate_index=1;
else if (0 == strncmp(LCM_PHYSICAL_ROTATION, "180", 3)) rotate_index=2;
else if (0 == strncmp(LCM_PHYSICAL_ROTATION, "270", 3)) rotate_index=3;
else rotate_index=0;
printf("[graphics] rotate_config %d %s\n", rotate_index, LCM_PHYSICAL_ROTATION);
}
return 3;
}
#define swap(x, y, type) {type z; z=x; x=y; y=z;}
// Allocate and setup the canvas object
void rotate_canvas_init(GRSurface *gr_draw)
{
gr_canvas = &__gr_canvas;
memcpy(gr_canvas, gr_draw, sizeof(GRSurface));
// Swap canvas' height and width, if the rotate angle is 90" or 270"
if (rotate_config(gr_draw)%2) {
swap(gr_canvas->width, gr_canvas->height, int);
gr_canvas->row_bytes = gr_canvas->width * gr_canvas->pixel_bytes;
}
gr_canvas->data = (unsigned char*) malloc(gr_canvas->height * gr_canvas->row_bytes);
if (gr_canvas->data == NULL) {
printf("[graphics] rotate_canvas_init() malloc gr_canvas->data failed\n");
gr_canvas = NULL;
return;
}
memset(gr_canvas->data, 0, gr_canvas->height * gr_canvas->row_bytes);
print_surface_info(gr_draw, "gr_draw");
print_surface_info(gr_canvas, "gr_canvas");
}
// Cleanup the canvas
void rotate_canvas_exit(void)
{
if (gr_canvas) {
if (gr_canvas->data)
free(gr_canvas->data);
free(gr_canvas);
}
gr_canvas=NULL;
}
// Return the canvas object
GRSurface *rotate_canvas_get(GRSurface *gr_draw)
{
// Initialize the canvas, if it was not exist.
if (gr_canvas==NULL)
rotate_canvas_init(gr_draw);
return gr_canvas;
}
// Surface Rotate Routines
static void rotate_surface_0(GRSurface *dst, GRSurface *src)
{
memcpy(dst->data, src->data, src->height*src->row_bytes);
}
static void rotate_surface_270(GRSurface *dst, GRSurface *src)
{
int v, w, h;
unsigned int *src_pixel;
unsigned int *dst_pixel;
for (h=0, v=src->width-1; h<dst->height; h++, v--) {
for (w=0; w<dst->width; w++) {
dst_pixel = (unsigned int *)(dst->data + dst->row_bytes*h);
src_pixel = (unsigned int *)(src->data + src->row_bytes*w);
*(dst_pixel+w)=*(src_pixel+v);
}
}
}
static void rotate_surface_180(GRSurface *dst, GRSurface *src)
{
int v, w, k, h;
unsigned int *src_pixel;
unsigned int *dst_pixel;
for (h=0, k=src->height-1; h<dst->height && k>=0 ; h++, k--) {
dst_pixel = (unsigned int *)(dst->data + dst->row_bytes*h);
src_pixel = (unsigned int *)(src->data + src->row_bytes*k);
for (w=0, v=src->width-1; w<dst->width && v>=0; w++, v--) {
*(dst_pixel+w)=*(src_pixel+v);
}
}
}
static void rotate_surface_90(GRSurface *dst, GRSurface *src)
{
int w, k, h;
unsigned int *src_pixel;
unsigned int *dst_pixel;
for (h=0; h<dst->height; h++) {
for (w=0, k=src->height-1; w<dst->width; w++, k--) {
dst_pixel = (unsigned int *)(dst->data + dst->row_bytes*h);
src_pixel = (unsigned int *)(src->data + src->row_bytes*k);
*(dst_pixel+w)=*(src_pixel+h);
}
}
}
typedef void (*rotate_surface_t) (GRSurface *, GRSurface *);
rotate_surface_t rotate_func[4]=
{
rotate_surface_0,
rotate_surface_90,
rotate_surface_180,
rotate_surface_270
};
// rotate and copy src* surface to dst surface
void rotate_surface(GRSurface *dst, GRSurface *src)
{
rotate_surface_t rotate;
rotate=rotate_func[rotate_config(dst)];
rotate(dst, src);
}
②新增文件graphics_rotate.h
- bootable/recovery/minui/graphics_rotate.h
/*
* Copyright (C) 2014 MediaTek Inc.
* Modification based on code covered by the mentioned copyright
* and/or permission notice(s).
*/
#ifndef MT_GRAPHICS_ROTATE_H_
#define MT_GRAPHICS_ROTATE_H_
#include "minui.h"
void rotate_canvas_exit(void);
void rotate_canvas_init(GRSurface *gr_draw);
void rotate_surface(GRSurface *dst, GRSurface *src);
GRSurface *rotate_canvas_get(GRSurface *gr_draw);
#endif
③graphics_rotate.cpp加入编译
- bootable/recovery/minui/Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
events.cpp \
graphics.cpp \
graphics_adf.cpp \
graphics_drm.cpp \
graphics_fbdev.cpp \
resources.cpp \
graphics_rotate.cpp \
④修改graphics_fbdev.cpp
- bootable/recovery/minui/graphics_fbdev.cpp
include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/cdefs.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <linux/fb.h>
#include <linux/kd.h>
#include "minui.h"
#include "graphics.h"
// add for recovery ui
#include "graphics_rotate.h"
static GRSurface* fbdev_init(minui_backend*);
static GRSurface* fbdev_flip(minui_backend*);
static void fbdev_blank(minui_backend*, bool);
static void fbdev_exit(minui_backend*);
static GRSurface gr_framebuffer[2];
static bool double_buffered;
static GRSurface* gr_draw = NULL;
static int displayed_buffer;
static fb_var_screeninfo vi;
static int fb_fd = -1;
static minui_backend my_backend = {
.init = fbdev_init,
.flip = fbdev_flip,
.blank = fbdev_blank,
.exit = fbdev_exit,
};
minui_backend* open_fbdev() {
return &my_backend;
}
static void fbdev_blank(minui_backend* backend __unused, bool blank)
{
int ret;
ret = ioctl(fb_fd, FBIOBLANK, blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK);
if (ret < 0)
perror("ioctl(): blank");
}
static void set_displayed_framebuffer(unsigned n)
{
if (n > 1 || !double_buffered) return;
vi.yres_virtual = gr_framebuffer[0].height * 2;
vi.yoffset = n * gr_framebuffer[0].height;
vi.bits_per_pixel = gr_framebuffer[0].pixel_bytes * 8;
if (ioctl(fb_fd, FBIOPUT_VSCREENINFO, &vi) < 0) {
perror("active fb swap failed");
}
displayed_buffer = n;
}
static GRSurface* fbdev_init(minui_backend* backend) {
int fd = open("/dev/graphics/fb0", O_RDWR);
if (fd == -1) {
perror("cannot open fb0");
return NULL;
}
fb_fix_screeninfo fi;
if (ioctl(fd, FBIOGET_FSCREENINFO, &fi) < 0) {
perror("failed to get fb0 info");
close(fd);
return NULL;
}
if (ioctl(fd, FBIOGET_VSCREENINFO, &vi) < 0) {
perror("failed to get fb0 info");
close(fd);
return NULL;
}
// We print this out for informational purposes only, but
// throughout we assume that the framebuffer device uses an RGBX
// pixel format. This is the case for every development device I
// have access to. For some of those devices (eg, hammerhead aka
// Nexus 5), FBIOGET_VSCREENINFO *reports* that it wants a
// different format (XBGR) but actually produces the correct
// results on the display when you write RGBX.
//
// If you have a device that actually *needs* another pixel format
// (ie, BGRX, or 565), patches welcome...
printf("fb0 reports (possibly inaccurate):\n"
" vi.bits_per_pixel = %d\n"
" vi.red.offset = %3d .length = %3d\n"
" vi.green.offset = %3d .length = %3d\n"
" vi.blue.offset = %3d .length = %3d\n",
vi.bits_per_pixel,
vi.red.offset, vi.red.length,
vi.green.offset, vi.green.length,
vi.blue.offset, vi.blue.length);
void* bits = mmap(0, fi.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (bits == MAP_FAILED) {
perror("failed to mmap framebuffer");
close(fd);
return NULL;
}
memset(bits, 0, fi.smem_len);
gr_framebuffer[0].width = vi.xres;
gr_framebuffer[0].height = vi.yres;
gr_framebuffer[0].row_bytes = fi.line_length;
gr_framebuffer[0].pixel_bytes = vi.bits_per_pixel / 8;
gr_framebuffer[0].data = reinterpret_cast<uint8_t*>(bits);
memset(gr_framebuffer[0].data, 0, gr_framebuffer[0].height * gr_framebuffer[0].row_bytes);
/* check if we can use double buffering */
if (vi.yres * fi.line_length * 2 <= fi.smem_len) {
double_buffered = true;
memcpy(gr_framebuffer+1, gr_framebuffer, sizeof(GRSurface));
gr_framebuffer[1].data = gr_framebuffer[0].data +
gr_framebuffer[0].height * gr_framebuffer[0].row_bytes;
gr_draw = gr_framebuffer+1;
} else {
double_buffered = false;
// Without double-buffering, we allocate RAM for a buffer to
// draw in, and then "flipping" the buffer consists of a
// memcpy from the buffer we allocated to the framebuffer.
gr_draw = (GRSurface*) malloc(sizeof(GRSurface));
memcpy(gr_draw, gr_framebuffer, sizeof(GRSurface));
gr_draw->data = (unsigned char*) malloc(gr_draw->height * gr_draw->row_bytes);
if (!gr_draw->data) {
perror("failed to allocate in-memory surface");
return NULL;
}
}
memset(gr_draw->data, 0, gr_draw->height * gr_draw->row_bytes);
fb_fd = fd;
set_displayed_framebuffer(0);
printf("framebuffer: %d (%d x %d)\n", fb_fd, gr_draw->width, gr_draw->height);
fbdev_blank(backend, true);
fbdev_blank(backend, false);
// add for recovery ui
// return gr_draw;
return rotate_canvas_get(gr_draw);
// end
}
static GRSurface* fbdev_flip(minui_backend* backend __unused) {
// add for recovery ui
rotate_surface(gr_draw, rotate_canvas_get(gr_draw));
// end
if (double_buffered) {
// Change gr_draw to point to the buffer currently displayed,
// then flip the driver so we're displaying the other buffer
// instead.
gr_draw = gr_framebuffer + displayed_buffer;
set_displayed_framebuffer(1-displayed_buffer);
} else {
// Copy from the in-memory surface to the framebuffer.
memcpy(gr_framebuffer[0].data, gr_draw->data,
gr_draw->height * gr_draw->row_bytes);
}
// add for recovery ui
//return gr_draw;
return rotate_canvas_get(gr_draw);
//end
}
static void fbdev_exit(minui_backend* backend __unused) {
close(fb_fd);
fb_fd = -1;
// add for recovery ui
rotate_canvas_exit();
// end
if (!double_buffered && gr_draw) {
free(gr_draw->data);
free(gr_draw);
}
gr_draw = NULL;
}
11.0系统修改recovUI方向
第一种方式
- bootable/recovery/minui/graphics.cpp
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 == "ARGB_8888") {
pixel_format = PixelFormat::ARGB;
} 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");
// add for recovery ui
rotation_str = ROTATION_RIGHT;
// end
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);
}
if (gr_draw->pixel_bytes != 4) {
printf("gr_init: Only 4-byte pixel formats supported\n");
}
return 0;
}
第二种方式
- device/mediateksample/{project}/BoardConfig.mk
# add for recovery ui
TARGET_RECOVERY_DEFAULT_ROTATION := ROTATION_RIGHT
# end