2020.04.03-recovery UI graphics rendering method illustration

The code resolution of graphics rendering driver in recovery UI sysytem

@ b a s e d \color{red}{ @based } @based o n \color{red}{ on } on A n d r o i d 10.0 \color{red}{Android 10.0} Android10.0

1 Summary of Graphic Rendering

采用从底层到上层的自下而上方式对整个调用过程济宁一个梳理:

  1. ScreenRecoveryUI:
    负责recovery UI的上层的功能实现,包括menu,icon,anation,progress等元素的元素显示,另外还包括按键,刷屏等时间的实现。该类及其相关子类为其功能的主要实现类。
  2. GRSurface: GRSurfaceFbdev,GRSurfaceAdf,GRSurfaceDrm
    GRSurface类的主要功能为绘制Recovery UI界面显示中的图像显示的一些组件包括一些logo,图片,图形等。根据不同的显示设备的创建出不同的类,如:GRSurfaceFbdev,GRSurfaceAdf,GRSurfaceDrm
    三种类,负责该种显示设备的图像现实渲染功能。
  3. MinuiBackend:MinuiBackendFbdev,MinuiBackendAdf,MinuiBackendDrm
    MinuiBackend类为底层的驱动接口类,用于调用底层的驱动,实现设备初始化,刷新,同步,绘制等功能。相应的该类也根据设备类型生成不同的子类MinuiBackendFbdev,MinuiBackendAdf,MinuiBackendDrm,实现具体显示设备的serface显示。该类可初始化,刷新显示设备,并且映射出显示设备的framebuffer。
  4. DrawInterface:
    DrawInterface类用于实现各个元素组件的绘制功能,包括SetColor,DrawTextLine,DrawHorizontalRule,DrawSurface,DrawFill等。
  5. Menu:菜单生成类
    Menu类是菜单相关类的父类,包括GraphicMenu,TextMenu,Menu的组件。
    逻辑关系如下:
    在这里插入图片描述

2 illustrated code

2.1 construct a new recovery

383    static constexpr const char* kDefaultLibRecoveryUIExt = "librecovery_ui_ext.so";
384    // Intentionally not calling dlclose(3) to avoid potential gotchas (e.g. `make_device` may have
385    // handed out pointers to code or static [or thread-local] data and doesn't collect them all back
386    // in on dlclose).
387    void* librecovery_ui_ext = dlopen(kDefaultLibRecoveryUIExt, RTLD_NOW);
388     // **加载库**  
389    using MakeDeviceType = decltype(&make_device);
390    MakeDeviceType make_device_func = nullptr;
391    if (librecovery_ui_ext == nullptr) {
392      printf("Failed to dlopen %s: %s\n", kDefaultLibRecoveryUIExt, dlerror());
393    } else {
394      reinterpret_cast<void*&>(make_device_func) = dlsym(librecovery_ui_ext, "make_device");
395      if (make_device_func == nullptr) {
396        printf("Failed to dlsym make_device: %s\n", dlerror());
397      }
398    }
399    // 加载device 的mak_device(),生成ScreenRecoveryUI类实例
	  20  Device* make_device() {
	  21    return new Device(new ScreenRecoveryUI);
	  22  }
    //recovery 的main函数执行,RecoveryUI的程序编译成lig库,然后在该语句调用,生成一个
    //Device实例并由ScreenRecoveryUI实例进行初始化。
400    Device* device;
401    if (make_device_func == nullptr) {
402      printf("Falling back to the default make_device() instead\n");
403      device = make_device();
404    } else {
405      printf("Loading make_device from %s\n", kDefaultLibRecoveryUIExt);
406      device = (*make_device_func)();
407    }
409    if (android::base::GetBoolProperty("ro.boot.quiescent", false)) {
410      printf("Quiescent recovery mode.\n");
411      device->ResetUI(new StubRecoveryUI());
412    } else {
413      if (!device->GetUI()->Init(locale)) {
414        printf("Failed to initialize UI; using stub UI instead.\n");
415        device->ResetUI(new StubRecoveryUI());
416      }
417    }

2.2 initial the instance

ui = device->GetUI();

     |73    virtual void ResetUI(RecoveryUI* ui) {
	 |74      ui_.reset(ui);
	 |75    }
	 // std::unique_ptr<RecoveryUI> ui_;
	 //ui_de声明,是一个RecoveryUI类型的独占指针,根据动态绑定和多态,return new Device(new ScreenRecoveryUI);类型实例实际上是一个ScreenRecoveryUI类型的实例,所以ui_其实是一个ScreenRecoveryUI类型。

调整菜单显示项,去掉一些不需要显示的

420    if (!has_cache) {
421      device->RemoveMenuItemForAction(Device::WIPE_CACHE);
422    }
423  
424    if (!android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
425      device->RemoveMenuItemForAction(Device::ENTER_FASTBOOT);
426    }
427  
428    if (!is_ro_debuggable()) {
429      device->RemoveMenuItemForAction(Device::ENTER_RESCUE);
430    }

接下来绘制RecoveryUI 背景

 ui->SetBackground(RecoveryUI::NONE); 
 //RecoveryUI类型为NONE

打开UI显示

if (show_text) ui->ShowText(true);

加载selinux安全属性

438    sehandle = selinux_android_file_context_handle();
439    selinux_android_set_sehandle(sehandle);
440    if (!sehandle) {
441      ui->Print("Warning: No file_contexts\n");
442    }
443  
444    SetLoggingSehandle(sehandle);

监听按键事件

446    std::atomic<Device::BuiltinAction> action;
447    std::thread listener_thread(ListenRecoverySocket, ui, std::ref(action));
448    listener_thread.detach();
		189  static void ListenRecoverySocket(RecoveryUI* ui, std::atomic<Device::BuiltinAction>& action) {
		190    android::base::unique_fd sock_fd(android_get_control_socket("recovery"));
		191    if (sock_fd < 0) {
		192      PLOG(ERROR) << "Failed to open recovery socket";
		193      return;
		194    }
		195    listen(sock_fd, 4);
		196  
		197    while (true) {
		198      android::base::unique_fd connection_fd;
		199      connection_fd.reset(accept(sock_fd, nullptr, nullptr));
		200      if (connection_fd < 0) {
		201        PLOG(ERROR) << "Failed to accept socket connection";
		202        continue;
		203      }
		204      char msg;
		205      constexpr char kSwitchToFastboot = 'f';
		206      constexpr char kSwitchToRecovery = 'r';
		207      ssize_t ret = TEMP_FAILURE_RETRY(read(connection_fd, &msg, sizeof(msg)));
		208      if (ret != sizeof(msg)) {
		209        PLOG(ERROR) << "Couldn't read from socket";
		210        continue;
		211      }
		212      switch (msg) {
		213        case kSwitchToRecovery:
		214          action = Device::BuiltinAction::ENTER_RECOVERY;
		215          break;
		216        case kSwitchToFastboot:
		217          action = Device::BuiltinAction::ENTER_FASTBOOT;
		218          break;
		219        default:
		220          LOG(ERROR) << "Unrecognized char from socket " << msg;
		221          continue;
		222      }
		223      ui->InterruptKey();
		224    }
		225  }
		

执行recovery升级

auto ret = fastboot ? StartFastboot(device, args) : start_recovery(device, args);
执行recoery升级的程序,并且返回执行后的结果。

接着根据返回结果判断执行的动作,包括:

28  static std::vector<std::pair<std::string, Device::BuiltinAction>> g_menu_actions{
29    { "Reboot system now", Device::REBOOT },
30    { "Reboot to bootloader", Device::REBOOT_BOOTLOADER },
31    { "Enter fastboot", Device::ENTER_FASTBOOT },
32    { "Apply update from ADB", Device::APPLY_ADB_SIDELOAD },
33    { "Apply update from SD card", Device::APPLY_SDCARD },
34    { "Wipe data/factory reset", Device::WIPE_DATA },
35    { "Wipe cache partition", Device::WIPE_CACHE },
36    { "Mount /system", Device::MOUNT_SYSTEM },
37    { "View recovery logs", Device::VIEW_RECOVERY_LOGS },
38    { "Run graphics test", Device::RUN_GRAPHICS_TEST },
39    { "Run locale test", Device::RUN_LOCALE_TEST },
40    { "Enter rescue", Device::ENTER_RESCUE },
41    { "Power off", Device::SHUTDOWN },
42  };

根据相应的操作选项进入相应的程序分支。

472      switch (ret) {
			//关机
473        case Device::SHUTDOWN:
474          ui->Print("Shutting down...\n");
475          // TODO: Move all the reboots to reboot(), which should conditionally set quiescent flag.
476          android::base::SetProperty(ANDROID_RB_PROPERTY, "shutdown,");
477          break;
478  		//启动
479        case Device::REBOOT_BOOTLOADER:
480          ui->Print("Rebooting to bootloader...\n");
481          android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,bootloader");
482          break;
483  		//reboot fastboot
484        case Device::REBOOT_FASTBOOT:
485          ui->Print("Rebooting to recovery/fastboot...\n");
486          android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,fastboot");
487          break;
488  		//进入Recovery
489        case Device::REBOOT_RECOVERY:
490          ui->Print("Rebooting to recovery...\n");
491          reboot("reboot,recovery");
492          break;
493  
494        case Device::REBOOT_RESCUE: {
495          // Not using `reboot("reboot,rescue")`, as it requires matching support in kernel and/or
496          // bootloader.
497          bootloader_message boot = {};
498          strlcpy(boot.command, "boot-rescue", sizeof(boot.command));
499          std::string err;
500          if (!write_bootloader_message(boot, &err)) {
501            LOG(ERROR) << "Failed to write bootloader message: " << err;
502            // Stay under recovery on failure.
503            continue;
504          }
505          ui->Print("Rebooting to recovery/rescue...\n");
506          reboot("reboot,recovery");
507          break;
508        }
509  		//进入fastboot
510        case Device::ENTER_FASTBOOT:
511          if (logical_partitions_mapped()) {
512            ui->Print("Partitions may be mounted - rebooting to enter fastboot.");
513            android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,fastboot");
514          } else {
515            LOG(INFO) << "Entering fastboot";
516            fastboot = true;
517          }
518          break;
519  		//进入Recovery
520        case Device::ENTER_RECOVERY:
521          LOG(INFO) << "Entering recovery";
522          fastboot = false;
523          break;
524  		//重启
525        default:
526          ui->Print("Rebooting...\n");
527          reboot("reboot,");
528          break;
529      }
530    }
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值