1.前言

在android 10.0的系统rom定制化开发工作中,在系统中recoverv的页面也是相关重要的一部分,在系统recovery ta升级等功能,都是需要recoverv功能的,在某些产品定制化中
在recovery的时候,发现居然旋转了180度,接下来分析下recovery关于屏幕显示方向的相关源码,来修改这个功能

2.recovery页面旋转180度问题的解决方案的核心类

     bootable/recovery/minui/include/minui/minui.h
     boottable/recovery/minui/graphics.cpp

3.recovery页面旋转180度问题的解决方案的核心功能分析和实现

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 <stdint.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    #include <memory>
     
    #include <android-base/properties.h>
     
    #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度,就是实现了功能要求

10-03 12:41