文章目录
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
采用从底层到上层的自下而上方式对整个调用过程济宁一个梳理:
- ScreenRecoveryUI:
负责recovery UI的上层的功能实现,包括menu,icon,anation,progress等元素的元素显示,另外还包括按键,刷屏等时间的实现。该类及其相关子类为其功能的主要实现类。 - GRSurface: GRSurfaceFbdev,GRSurfaceAdf,GRSurfaceDrm
GRSurface类的主要功能为绘制Recovery UI界面显示中的图像显示的一些组件包括一些logo,图片,图形等。根据不同的显示设备的创建出不同的类,如:GRSurfaceFbdev,GRSurfaceAdf,GRSurfaceDrm
三种类,负责该种显示设备的图像现实渲染功能。 - MinuiBackend:MinuiBackendFbdev,MinuiBackendAdf,MinuiBackendDrm
MinuiBackend类为底层的驱动接口类,用于调用底层的驱动,实现设备初始化,刷新,同步,绘制等功能。相应的该类也根据设备类型生成不同的子类MinuiBackendFbdev,MinuiBackendAdf,MinuiBackendDrm,实现具体显示设备的serface显示。该类可初始化,刷新显示设备,并且映射出显示设备的framebuffer。 - DrawInterface:
DrawInterface类用于实现各个元素组件的绘制功能,包括SetColor,DrawTextLine,DrawHorizontalRule,DrawSurface,DrawFill等。 - 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 }