Update TWRP to AOSP 7.1.2

Change-Id: I19c1546efb4182aac62c690e3cc05b04e3a9a32e
This commit is contained in:
Ethan Yonker
2017-05-10 16:11:35 -05:00
51 changed files with 489 additions and 491 deletions
+3 -3
View File
@@ -652,9 +652,9 @@ ifeq ($(shell test $(PLATFORM_SDK_VERSION) -gt 22; echo $$?),0)
include $(commands_recovery_local_path)/minadbd/Android.mk \
$(commands_recovery_local_path)/minui/Android.mk
else
TARGET_GLOBAL_CFLAGS += -DTW_USE_OLD_MINUI_H
include $(commands_recovery_local_path)/minadbd.old/Android.mk \
$(commands_recovery_local_path)/minui.old/Android.mk
TARGET_GLOBAL_CFLAGS += -DTW_USE_MINUI_21
include $(commands_recovery_local_path)/minadbd21/Android.mk \
$(commands_recovery_local_path)/minui21/Android.mk
endif
#includes for TWRP
+22
View File
@@ -44,4 +44,26 @@ enum CauseCode {
kVendorFailure = 200
};
enum UncryptErrorCode {
kUncryptNoError = -1,
kUncryptErrorPlaceholder = 50,
kUncryptTimeoutError = 100,
kUncryptFileRemoveError,
kUncryptFileOpenError,
kUncryptSocketOpenError,
kUncryptSocketWriteError,
kUncryptSocketListenError,
kUncryptSocketAcceptError,
kUncryptFstabReadError,
kUncryptFileStatError,
kUncryptBlockOpenError,
kUncryptIoctlError,
kUncryptReadError,
kUncryptWriteError,
kUncryptFileSyncError,
kUncryptFileCloseError,
kUncryptFileRenameError,
kUncryptPackageMissingError,
};
#endif
+41 -19
View File
@@ -30,6 +30,7 @@
#include <string>
#include <vector>
#include <android-base/file.h>
#include <android-base/parseint.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
@@ -54,6 +55,7 @@ static constexpr const char* AB_OTA_PAYLOAD_PROPERTIES = "payload_properties.txt
static constexpr const char* AB_OTA_PAYLOAD = "payload.bin";
#define PUBLIC_KEYS_FILE "/res/keys"
static constexpr const char* METADATA_PATH = "META-INF/com/android/metadata";
static constexpr const char* UNCRYPT_STATUS = "/cache/recovery/uncrypt_status";
// Default allocation of progress bar segments to operations
static const int VERIFICATION_PROGRESS_TIME = 60;
@@ -371,6 +373,14 @@ try_update_binary(const char* path, ZipArchive* zip, bool* wipe_cache,
}
pid_t pid = fork();
if (pid == -1) {
close(pipefd[0]);
close(pipefd[1]);
LOGE("Failed to fork update binary: %s\n", strerror(errno));
return INSTALL_ERROR;
}
if (pid == 0) {
umask(022);
close(pipefd[0]);
@@ -511,13 +521,6 @@ install_package(const char* path, bool* wipe_cache, const char* install_file,
modified_flash = true;
auto start = std::chrono::system_clock::now();
FILE* install_log = fopen_path(install_file, "w");
if (install_log) {
fputs(path, install_log);
fputc('\n', install_log);
} else {
LOGE("failed to open last_install: %s\n", strerror(errno));
}
int result;
std::vector<std::string> log_buffer;
if (setup_install_mounts() != 0) {
@@ -526,21 +529,40 @@ install_package(const char* path, bool* wipe_cache, const char* install_file,
} else {
result = really_install_package(path, wipe_cache, needs_mount, log_buffer, retry_count);
}
if (install_log != nullptr) {
fputc(result == INSTALL_SUCCESS ? '1' : '0', install_log);
fputc('\n', install_log);
std::chrono::duration<double> duration = std::chrono::system_clock::now() - start;
int count = static_cast<int>(duration.count());
// Report the time spent to apply OTA update in seconds.
fprintf(install_log, "time_total: %d\n", count);
fprintf(install_log, "retry: %d\n", retry_count);
for (const auto& s : log_buffer) {
fprintf(install_log, "%s\n", s.c_str());
// Measure the time spent to apply OTA update in seconds.
std::chrono::duration<double> duration = std::chrono::system_clock::now() - start;
int time_total = static_cast<int>(duration.count());
if (ensure_path_mounted(UNCRYPT_STATUS) != 0) {
LOGW("Can't mount %s\n", UNCRYPT_STATUS);
} else {
std::string uncrypt_status;
if (!android::base::ReadFileToString(UNCRYPT_STATUS, &uncrypt_status)) {
LOGW("failed to read uncrypt status: %s\n", strerror(errno));
} else if (!android::base::StartsWith(uncrypt_status, "uncrypt_")) {
LOGW("corrupted uncrypt_status: %s: %s\n", uncrypt_status.c_str(), strerror(errno));
} else {
log_buffer.push_back(android::base::Trim(uncrypt_status));
}
fclose(install_log);
}
// The first two lines need to be the package name and install result.
std::vector<std::string> log_header = {
path,
result == INSTALL_SUCCESS ? "1" : "0",
"time_total: " + std::to_string(time_total),
"retry: " + std::to_string(retry_count),
};
std::string log_content = android::base::Join(log_header, "\n") + "\n" +
android::base::Join(log_buffer, "\n");
if (!android::base::WriteStringToFile(log_content, install_file)) {
LOGE("failed to write %s: %s\n", install_file, strerror(errno));
}
// Write a copy into last_log.
LOGI("%s\n", log_content.c_str());
return result;
}
+3
View File
@@ -79,6 +79,9 @@ endif
ifneq ($(BOARD_USE_CUSTOM_RECOVERY_FONT),)
LOCAL_CFLAGS += -DBOARD_USE_CUSTOM_RECOVERY_FONT=$(BOARD_USE_CUSTOM_RECOVERY_FONT)
endif
ifneq ($(wildcard system/core/healthd/animation.h),)
LOCAL_CFLAGS += -DTW_USE_MINUI_CUSTOM_FONTS
endif
include $(BUILD_STATIC_LIBRARY)
# Used by OEMs for factory test images.
+4 -4
View File
@@ -1,14 +1,14 @@
struct {
unsigned width;
unsigned height;
unsigned cwidth;
unsigned cheight;
unsigned char_width;
unsigned char_height;
unsigned char rundata[2973];
} font = {
.width = 960,
.height = 18,
.cwidth = 10,
.cheight = 18,
.char_width = 10,
.char_height = 18,
.rundata = {
0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x55,0x82,0x06,0x82,0x02,0x82,0x10,0x82,
0x11,0x83,0x08,0x82,0x0a,0x82,0x04,0x82,0x46,0x82,0x08,0x82,0x07,0x84,0x06,
+126 -26
View File
@@ -40,12 +40,6 @@
#include "minui.h"
#include "graphics.h"
struct GRFont {
GRSurface* texture;
int cwidth;
int cheight;
};
static GRFont* gr_font = NULL;
static minui_backend* gr_backend = NULL;
@@ -68,17 +62,35 @@ static bool outside(int x, int y)
{
return x < 0 || x >= gr_draw->width || y < 0 || y >= gr_draw->height;
}
//#define TW_USE_MINUI_CUSTOM_FONTS 1
#ifndef TW_USE_MINUI_CUSTOM_FONTS
int gr_measure(const char *s)
{
return gr_font->cwidth * strlen(s);
return gr_font->char_width * strlen(s);
}
void gr_font_size(int *x, int *y)
{
*x = gr_font->cwidth;
*y = gr_font->cheight;
*x = gr_font->char_width;
*y = gr_font->char_height;
}
#else // TW_USE_MINUI_CUSTOM_FONTS
const GRFont* gr_sys_font()
{
return gr_font;
}
int gr_measure(const GRFont* font, const char *s)
{
return font->char_width * strlen(s);
}
void gr_font_size(const GRFont* font, int *x, int *y)
{
*x = font->char_width;
*y = font->char_height;
}
#endif // TW_USE_MINUI_CUSTOM_FONTS
void blend_16bpp(unsigned char* px, unsigned r5, unsigned g5, unsigned b5, unsigned char a)
{
@@ -146,36 +158,67 @@ static void text_blend(unsigned char* src_p, int src_row_bytes,
}
}
#ifndef TW_USE_MINUI_CUSTOM_FONTS
void gr_text(int x, int y, const char *s, bool bold)
{
GRFont* font = gr_font;
if (!font->texture || gr_current_a == 0) return;
bold = bold && (font->texture->height != font->cheight);
bold = bold && (font->texture->height != font->char_height);
x += overscan_offset_x;
y += overscan_offset_y;
unsigned char ch;
while ((ch = *s++)) {
if (outside(x, y) || outside(x+font->cwidth-1, y+font->cheight-1)) break;
if (outside(x, y) || outside(x+font->char_width-1, y+font->char_height-1)) break;
if (ch < ' ' || ch > '~') {
ch = '?';
}
unsigned char* src_p = font->texture->data + ((ch - ' ') * font->cwidth) +
(bold ? font->cheight * font->texture->row_bytes : 0);
unsigned char* src_p = font->texture->data + ((ch - ' ') * font->char_width) +
(bold ? font->char_height * font->texture->row_bytes : 0);
unsigned char* dst_p = gr_draw->data + y*gr_draw->row_bytes + x*gr_draw->pixel_bytes;
text_blend(src_p, font->texture->row_bytes,
dst_p, gr_draw->row_bytes,
font->cwidth, font->cheight);
font->char_width, font->char_height);
x += font->cwidth;
x += font->char_width;
}
}
#else //TW_USE_MINUI_CUSTOM_FONTS
void gr_text(const GRFont* font, int x, int y, const char *s, bool bold)
{
if (!font->texture || gr_current_a == 0) return;
bold = bold && (font->texture->height != font->char_height);
x += overscan_offset_x;
y += overscan_offset_y;
unsigned char ch;
while ((ch = *s++)) {
if (outside(x, y) || outside(x+font->char_width-1, y+font->char_height-1)) break;
if (ch < ' ' || ch > '~') {
ch = '?';
}
unsigned char* src_p = font->texture->data + ((ch - ' ') * font->char_width) +
(bold ? font->char_height * font->texture->row_bytes : 0);
unsigned char* dst_p = gr_draw->data + y*gr_draw->row_bytes + x*gr_draw->pixel_bytes;
text_blend(src_p, font->texture->row_bytes,
dst_p, gr_draw->row_bytes,
font->char_width, font->char_height);
x += font->char_width;
}
}
#endif //TW_USE_MINUI_CUSTOM_FONTS
void gr_texticon(int x, int y, GRSurface* icon) {
if (icon == NULL) return;
@@ -383,6 +426,7 @@ unsigned int gr_get_height(GRSurface* surface) {
return surface->height;
}
#ifndef TW_USE_MINUI_CUSTOM_FONTS
static void gr_init_font(void)
{
gr_font = reinterpret_cast<GRFont*>(calloc(sizeof(*gr_font), 1));
@@ -392,8 +436,8 @@ static void gr_init_font(void)
// 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.
gr_font->cwidth = gr_font->texture->width / 96;
gr_font->cheight = gr_font->texture->height / 2;
gr_font->char_width = gr_font->texture->width / 96;
gr_font->char_height = gr_font->texture->height / 2;
} else {
printf("failed to read font: res=%d\n", res);
@@ -414,11 +458,73 @@ static void gr_init_font(void)
bits += (data & 0x7f);
}
gr_font->cwidth = font.cwidth;
gr_font->cheight = font.cheight;
gr_font->char_width = font.char_width;
gr_font->char_height = font.char_height;
}
}
void gr_set_font(__attribute__ ((unused))const char* name) {
//this cm function is made to change font. Don't care, just init the font:
gr_init_font();
return;
}
#else
int gr_init_font(const char* name, GRFont** dest) {
GRFont* font = reinterpret_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;
}
static void gr_init_font(void)
{
int res = gr_init_font("font", &gr_font);
if (res == 0) {
return;
}
printf("failed to read font: res=%d\n", res);
// fall back to the compiled-in font.
gr_font = reinterpret_cast<GRFont*>(calloc(1, sizeof(*gr_font)));
gr_font->texture = reinterpret_cast<GRSurface*>(malloc(sizeof(*gr_font->texture)));
gr_font->texture->width = font.width;
gr_font->texture->height = font.height;
gr_font->texture->row_bytes = font.width;
gr_font->texture->pixel_bytes = 1;
unsigned char* bits = reinterpret_cast<unsigned char*>(malloc(font.width * font.height));
gr_font->texture->data = reinterpret_cast<unsigned char*>(bits);
unsigned char data;
unsigned char* in = font.rundata;
while((data = *in++)) {
memset(bits, (data & 0x80) ? 255 : 0, data & 0x7f);
bits += (data & 0x7f);
}
gr_font->char_width = font.char_width;
gr_font->char_height = font.char_height;
}
#endif
#if 0
// Exercises many of the gr_*() functions; useful for testing.
static void gr_test() {
@@ -547,9 +653,3 @@ void gr_fb_blank(bool blank)
{
gr_backend->blank(gr_backend, blank);
}
void gr_set_font(__attribute__ ((unused))const char* name) {
//this cm function is made to change font. Don't care, just init the font:
gr_init_font();
return;
}
+21 -5
View File
@@ -17,7 +17,7 @@
#ifndef _MINUI_H_
#define _MINUI_H_
#ifndef TW_USE_OLD_MINUI_H
#ifndef TW_USE_MINUI_21
#include <sys/types.h>
@@ -35,6 +35,12 @@ struct GRSurface {
unsigned char* data;
};
struct GRFont {
GRSurface* texture;
int char_width;
int char_height;
};
int gr_init();
void gr_exit();
@@ -47,11 +53,21 @@ void gr_fb_blank(bool blank);
void gr_clear(); // clear entire surface to current color
void gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a);
void gr_fill(int x1, int y1, int x2, int y2);
void gr_text(int x, int y, const char *s, bool bold);
void gr_texticon(int x, int y, GRSurface* icon);
#ifndef TW_USE_MINUI_CUSTOM_FONTS
void gr_text(int x, int y, const char *s, bool bold);
int gr_measure(const char *s);
void gr_font_size(int *x, int *y);
void gr_set_font(__attribute__ ((unused))const char* name);
#else
const GRFont* gr_sys_font();
int gr_init_font(const char* name, GRFont** dest);
void gr_text(const GRFont* font, int x, int y, const char *s, bool bold);
int gr_measure(const GRFont* font, const char *s);
void gr_font_size(const GRFont* font, int *x, int *y);
#endif
void gr_blit(GRSurface* source, int sx, int sy, int w, int h, int dx, int dy);
unsigned int gr_get_width(GRSurface* surface);
@@ -127,9 +143,9 @@ int res_create_localized_alpha_surface(const char* name, const char* locale,
// functions.
void res_free_surface(GRSurface* surface);
#else //ifndef TW_USE_OLD_MINUI_H
#else //ifndef TW_USE_MINUI_21
// This the old minui.old/minui.h for compatibility with building TWRP
// This the old minui21/minui.h for compatibility with building TWRP
// in pre 6.0 trees.
#include <stdbool.h>
@@ -217,5 +233,5 @@ void gr_clear();
}
#endif
#endif // ifndef TW_USE_OLD_MINUI_H
#endif // ifndef TW_USE_MINUI_21
#endif // ifndef _MINUI_H_
+4 -4
View File
@@ -1,14 +1,14 @@
struct {
unsigned width;
unsigned height;
unsigned cwidth;
unsigned cheight;
unsigned char_width;
unsigned char_height;
unsigned char rundata[2718];
} font = {
.width = 960,
.height = 18,
.cwidth = 10,
.cheight = 18,
.char_width = 10,
.char_height = 18,
.rundata = {
0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,
0x3b,0x81,0x29,0x81,0x06,0x81,0x3f,0x81,0x7f,0x7f,0x7f,0x37,0x83,0x05,0x81,
+4 -4
View File
@@ -1,14 +1,14 @@
struct {
unsigned width;
unsigned height;
unsigned cwidth;
unsigned cheight;
unsigned char_width;
unsigned char_height;
unsigned char rundata[3979];
} font = {
.width = 1440,
.height = 24,
.cwidth = 15,
.cheight = 24,
.char_width = 15,
.char_height = 24,
.rundata = {
0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x6e,0x81,0x3e,0x81,
0x07,0x81,0x7f,0x7f,0x7f,0x7f,0x7f,0x76,0x84,0x17,0x84,0x7f,0x7f,0x7f,0x7f,
+4 -4
View File
@@ -1,14 +1,14 @@
struct {
unsigned width;
unsigned height;
unsigned cwidth;
unsigned cheight;
unsigned char_width;
unsigned char_height;
unsigned char rundata[6679];
} font = {
.width = 2208,
.height = 41,
.cwidth = 23,
.cheight = 41,
.char_width = 23,
.char_height = 41,
.rundata = {
0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,
0x7f,0x7f,0x7f,0x17,0x83,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,
+11 -8
View File
@@ -1429,15 +1429,18 @@ static bool bootreason_in_blacklist() {
}
static void log_failure_code(ErrorCode code, const char *update_package) {
FILE* install_log = fopen_path(TEMPORARY_INSTALL_FILE, "w");
if (install_log != nullptr) {
fprintf(install_log, "%s\n", update_package);
fprintf(install_log, "0\n");
fprintf(install_log, "error: %d\n", code);
fclose(install_log);
} else {
LOGE("failed to open last_install: %s\n", strerror(errno));
std::vector<std::string> log_buffer = {
update_package,
"0", // install result
"error: " + std::to_string(code),
};
std::string log_content = android::base::Join(log_buffer, "\n");
if (!android::base::WriteStringToFile(log_content, TEMPORARY_INSTALL_FILE)) {
LOGE("failed to write %s: %s\n", TEMPORARY_INSTALL_FILE, strerror(errno));
}
// Also write the info into last_log.
LOGI("%s\n", log_content.c_str());
}
static ssize_t logbasename(
+34 -24
View File
@@ -53,8 +53,6 @@ static double now() {
ScreenRecoveryUI::ScreenRecoveryUI() :
currentIcon(NONE),
locale(nullptr),
intro_done(false),
current_frame(0),
progressBarType(EMPTY),
progressScopeStart(0),
progressScopeSize(0),
@@ -75,6 +73,8 @@ ScreenRecoveryUI::ScreenRecoveryUI() :
file_viewer_text_(nullptr),
intro_frames(0),
loop_frames(0),
current_frame(0),
intro_done(false),
animation_fps(30), // TODO: there's currently no way to infer this.
stage(-1),
max_stage(-1),
@@ -259,7 +259,7 @@ void ScreenRecoveryUI::DrawHorizontalRule(int* y) {
}
void ScreenRecoveryUI::DrawTextLine(int x, int* y, const char* line, bool bold) {
gr_text(x, *y, line, bold);
gr_text(gr_sys_font(), x, *y, line, bold);
*y += char_height_ + 4;
}
@@ -315,10 +315,10 @@ void ScreenRecoveryUI::draw_screen_locked() {
gr_fill(0, y - 2, gr_fb_width(), y + char_height_ + 2);
// Bold white text for the selected item.
SetColor(MENU_SEL_FG);
gr_text(4, y, menu_[i], true);
gr_text(gr_sys_font(), 4, y, menu_[i], true);
SetColor(MENU);
} else {
gr_text(4, y, menu_[i], false);
gr_text(gr_sys_font(), 4, y, menu_[i], false);
}
y += char_height_ + 4;
}
@@ -334,7 +334,7 @@ void ScreenRecoveryUI::draw_screen_locked() {
for (int ty = gr_fb_height() - char_height_;
ty >= y && count < text_rows_;
ty -= char_height_, ++count) {
gr_text(0, ty, text_[row], false);
gr_text(gr_sys_font(), 0, ty, text_[row], false);
--row;
if (row < 0) row = text_rows_ - 1;
}
@@ -447,9 +447,18 @@ void ScreenRecoveryUI::SetSystemUpdateText(bool security_update) {
Redraw();
}
void ScreenRecoveryUI::Init() {
void ScreenRecoveryUI::InitTextParams() {
gr_init();
gr_font_size(gr_sys_font(), &char_width_, &char_height_);
text_rows_ = gr_fb_height() / char_height_;
text_cols_ = gr_fb_width() / char_width_;
}
void ScreenRecoveryUI::Init() {
RecoveryUI::Init();
InitTextParams();
density_ = static_cast<float>(property_get_int32("ro.sf.lcd_density", 160)) / 160.f;
// Are we portrait or landscape?
@@ -457,10 +466,6 @@ void ScreenRecoveryUI::Init() {
// Are we the large variant of our base layout?
if (gr_fb_height() > PixelsFromDp(800)) ++layout_;
gr_font_size(&char_width_, &char_height_);
text_rows_ = gr_fb_height() / char_height_;
text_cols_ = gr_fb_width() / char_width_;
text_ = Alloc2d(text_rows_, text_cols_ + 1);
file_viewer_text_ = Alloc2d(text_rows_, text_cols_ + 1);
menu_ = Alloc2d(text_rows_, text_cols_ + 1);
@@ -487,37 +492,42 @@ void ScreenRecoveryUI::Init() {
LoadAnimation();
pthread_create(&progress_thread_, nullptr, ProgressThreadStartRoutine, this);
RecoveryUI::Init();
}
void ScreenRecoveryUI::LoadAnimation() {
// How many frames of intro and loop do we have?
std::unique_ptr<DIR, decltype(&closedir)> dir(opendir("/res/images"), closedir);
dirent* de;
std::vector<std::string> intro_frame_names;
std::vector<std::string> loop_frame_names;
while ((de = readdir(dir.get())) != nullptr) {
int value;
if (sscanf(de->d_name, "intro%d", &value) == 1 && intro_frames < (value + 1)) {
intro_frames = value + 1;
} else if (sscanf(de->d_name, "loop%d", &value) == 1 && loop_frames < (value + 1)) {
loop_frames = value + 1;
int value, num_chars;
if (sscanf(de->d_name, "intro%d%n.png", &value, &num_chars) == 1) {
intro_frame_names.emplace_back(de->d_name, num_chars);
} else if (sscanf(de->d_name, "loop%d%n.png", &value, &num_chars) == 1) {
loop_frame_names.emplace_back(de->d_name, num_chars);
}
}
intro_frames = intro_frame_names.size();
loop_frames = loop_frame_names.size();
// It's okay to not have an intro.
if (intro_frames == 0) intro_done = true;
// But you must have an animation.
if (loop_frames == 0) abort();
std::sort(intro_frame_names.begin(), intro_frame_names.end());
std::sort(loop_frame_names.begin(), loop_frame_names.end());
introFrames = new GRSurface*[intro_frames];
for (int i = 0; i < intro_frames; ++i) {
// TODO: remember the names above, so we don't have to hard-code the number of 0s.
LoadBitmap(android::base::StringPrintf("intro%05d", i).c_str(), &introFrames[i]);
for (size_t i = 0; i < intro_frames; i++) {
LoadBitmap(intro_frame_names.at(i).c_str(), &introFrames[i]);
}
loopFrames = new GRSurface*[loop_frames];
for (int i = 0; i < loop_frames; ++i) {
LoadBitmap(android::base::StringPrintf("loop%05d", i).c_str(), &loopFrames[i]);
for (size_t i = 0; i < loop_frames; i++) {
LoadBitmap(loop_frame_names.at(i).c_str(), &loopFrames[i]);
}
}
+24 -21
View File
@@ -37,16 +37,16 @@ class ScreenRecoveryUI : public RecoveryUI {
void SetSystemUpdateText(bool security_update);
// progress indicator
void SetProgressType(ProgressType type);
void ShowProgress(float portion, float seconds);
void SetProgress(float fraction);
void SetProgressType(ProgressType type) override;
void ShowProgress(float portion, float seconds) override;
void SetProgress(float fraction) override;
void SetStage(int current, int max);
void SetStage(int current, int max) override;
// text log
void ShowText(bool visible);
bool IsTextVisible();
bool WasTextEverVisible();
void ShowText(bool visible) override;
bool IsTextVisible() override;
bool WasTextEverVisible() override;
// printing messages
void Print(const char* fmt, ...) __printflike(2, 3);
@@ -72,8 +72,6 @@ class ScreenRecoveryUI : public RecoveryUI {
Icon currentIcon;
const char* locale;
bool intro_done;
int current_frame;
// The scale factor from dp to pixels. 1.0 for mdpi, 4.0 for xxxhdpi.
float density_;
@@ -123,8 +121,11 @@ class ScreenRecoveryUI : public RecoveryUI {
pthread_t progress_thread_;
// Number of intro frames and loop frames in the animation.
int intro_frames;
int loop_frames;
size_t intro_frames;
size_t loop_frames;
size_t current_frame;
bool intro_done;
// Number of frames per sec (default: 30) for both parts of the animation.
int animation_fps;
@@ -136,11 +137,13 @@ class ScreenRecoveryUI : public RecoveryUI {
pthread_mutex_t updateMutex;
bool rtl_locale;
void draw_background_locked();
void draw_foreground_locked();
void draw_screen_locked();
void update_screen_locked();
void update_progress_locked();
virtual void InitTextParams();
virtual void draw_background_locked();
virtual void draw_foreground_locked();
virtual void draw_screen_locked();
virtual void update_screen_locked();
virtual void update_progress_locked();
GRSurface* GetCurrentFrame();
GRSurface* GetCurrentText();
@@ -148,8 +151,8 @@ class ScreenRecoveryUI : public RecoveryUI {
static void* ProgressThreadStartRoutine(void* data);
void ProgressThreadLoop();
void ShowFile(FILE*);
void PrintV(const char*, bool, va_list);
virtual void ShowFile(FILE*);
virtual void PrintV(const char*, bool, va_list);
void PutChar(char);
void ClearText();
@@ -158,9 +161,9 @@ class ScreenRecoveryUI : public RecoveryUI {
void LoadLocalizedBitmap(const char* filename, GRSurface** surface);
int PixelsFromDp(int dp);
int GetAnimationBaseline();
int GetProgressBaseline();
int GetTextBaseline();
virtual int GetAnimationBaseline();
virtual int GetProgressBaseline();
virtual int GetTextBaseline();
void DrawHorizontalRule(int* y);
void DrawTextLine(int x, int* y, const char* line, bool bold);
+1 -1
View File
@@ -49,7 +49,7 @@ extern "C" {
#include "adb.h"
#else
extern "C" {
#include "minadbd.old/adb.h"
#include "minadbd21/adb.h"
}
#endif
+59 -25
View File
@@ -118,6 +118,7 @@
#define LOG_TAG "uncrypt"
#include <log/log.h>
#include "error_code.h"
#include "unique_fd.h"
#define WINDOW_SIZE 5
@@ -134,6 +135,7 @@
// devices, on which /cache partitions always exist.
static const std::string CACHE_BLOCK_MAP = "/cache/recovery/block.map";
static const std::string UNCRYPT_PATH_FILE = "/cache/recovery/uncrypt_file";
static const std::string UNCRYPT_STATUS = "/cache/recovery/uncrypt_status";
static const std::string UNCRYPT_SOCKET = "uncrypt";
static struct fstab* fstab = nullptr;
@@ -234,25 +236,25 @@ static int produce_block_map(const char* path, const char* map_file, const char*
std::string err;
if (!android::base::RemoveFileIfExists(map_file, &err)) {
ALOGE("failed to remove the existing map file %s: %s", map_file, err.c_str());
return -1;
return kUncryptFileRemoveError;
}
std::string tmp_map_file = std::string(map_file) + ".tmp";
unique_fd mapfd(open(tmp_map_file.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR));
if (!mapfd) {
ALOGE("failed to open %s: %s\n", tmp_map_file.c_str(), strerror(errno));
return -1;
return kUncryptFileOpenError;
}
// Make sure we can write to the socket.
if (!write_status_to_socket(0, socket)) {
ALOGE("failed to write to socket %d\n", socket);
return -1;
return kUncryptSocketWriteError;
}
struct stat sb;
if (stat(path, &sb) != 0) {
ALOGE("failed to stat %s", path);
return -1;
return kUncryptFileStatError;
}
ALOGI(" block size: %ld bytes", static_cast<long>(sb.st_blksize));
@@ -266,7 +268,7 @@ static int produce_block_map(const char* path, const char* map_file, const char*
blk_dev, sb.st_size, static_cast<long>(sb.st_blksize));
if (!android::base::WriteStringToFd(s, mapfd.get())) {
ALOGE("failed to write %s: %s", tmp_map_file.c_str(), strerror(errno));
return -1;
return kUncryptWriteError;
}
std::vector<std::vector<unsigned char>> buffers;
@@ -279,7 +281,7 @@ static int produce_block_map(const char* path, const char* map_file, const char*
unique_fd fd(open(path, O_RDONLY));
if (!fd) {
ALOGE("failed to open %s for reading: %s", path, strerror(errno));
return -1;
return kUncryptFileOpenError;
}
unique_fd wfd(-1);
@@ -287,7 +289,7 @@ static int produce_block_map(const char* path, const char* map_file, const char*
wfd = open(blk_dev, O_WRONLY);
if (!wfd) {
ALOGE("failed to open fd for writing: %s", strerror(errno));
return -1;
return kUncryptBlockOpenError;
}
}
@@ -306,13 +308,13 @@ static int produce_block_map(const char* path, const char* map_file, const char*
int block = head_block;
if (ioctl(fd.get(), FIBMAP, &block) != 0) {
ALOGE("failed to find block %d", head_block);
return -1;
return kUncryptIoctlError;
}
add_block_to_ranges(ranges, block);
if (encrypted) {
if (write_at_offset(buffers[head].data(), sb.st_blksize, wfd.get(),
static_cast<off64_t>(sb.st_blksize) * block) != 0) {
return -1;
return kUncryptWriteError;
}
}
head = (head + 1) % WINDOW_SIZE;
@@ -325,7 +327,7 @@ static int produce_block_map(const char* path, const char* map_file, const char*
std::min(static_cast<off64_t>(sb.st_blksize), sb.st_size - pos));
if (!android::base::ReadFully(fd.get(), buffers[tail].data(), to_read)) {
ALOGE("failed to read: %s", strerror(errno));
return -1;
return kUncryptReadError;
}
pos += to_read;
} else {
@@ -342,13 +344,13 @@ static int produce_block_map(const char* path, const char* map_file, const char*
int block = head_block;
if (ioctl(fd.get(), FIBMAP, &block) != 0) {
ALOGE("failed to find block %d", head_block);
return -1;
return kUncryptIoctlError;
}
add_block_to_ranges(ranges, block);
if (encrypted) {
if (write_at_offset(buffers[head].data(), sb.st_blksize, wfd.get(),
static_cast<off64_t>(sb.st_blksize) * block) != 0) {
return -1;
return kUncryptWriteError;
}
}
head = (head + 1) % WINDOW_SIZE;
@@ -358,41 +360,41 @@ static int produce_block_map(const char* path, const char* map_file, const char*
if (!android::base::WriteStringToFd(
android::base::StringPrintf("%zu\n", ranges.size() / 2), mapfd.get())) {
ALOGE("failed to write %s: %s", tmp_map_file.c_str(), strerror(errno));
return -1;
return kUncryptWriteError;
}
for (size_t i = 0; i < ranges.size(); i += 2) {
if (!android::base::WriteStringToFd(
android::base::StringPrintf("%d %d\n", ranges[i], ranges[i+1]), mapfd.get())) {
ALOGE("failed to write %s: %s", tmp_map_file.c_str(), strerror(errno));
return -1;
return kUncryptWriteError;
}
}
if (fsync(mapfd.get()) == -1) {
ALOGE("failed to fsync \"%s\": %s", tmp_map_file.c_str(), strerror(errno));
return -1;
return kUncryptFileSyncError;
}
if (close(mapfd.get()) == -1) {
ALOGE("failed to close %s: %s", tmp_map_file.c_str(), strerror(errno));
return -1;
return kUncryptFileCloseError;
}
mapfd = -1;
if (encrypted) {
if (fsync(wfd.get()) == -1) {
ALOGE("failed to fsync \"%s\": %s", blk_dev, strerror(errno));
return -1;
return kUncryptFileSyncError;
}
if (close(wfd.get()) == -1) {
ALOGE("failed to close %s: %s", blk_dev, strerror(errno));
return -1;
return kUncryptFileCloseError;
}
wfd = -1;
}
if (rename(tmp_map_file.c_str(), map_file) == -1) {
ALOGE("failed to rename %s to %s: %s", tmp_map_file.c_str(), map_file, strerror(errno));
return -1;
return kUncryptFileRenameError;
}
// Sync dir to make rename() result written to disk.
std::string file_name = map_file;
@@ -400,15 +402,15 @@ static int produce_block_map(const char* path, const char* map_file, const char*
unique_fd dfd(open(dir_name.c_str(), O_RDONLY | O_DIRECTORY));
if (!dfd) {
ALOGE("failed to open dir %s: %s", dir_name.c_str(), strerror(errno));
return -1;
return kUncryptFileOpenError;
}
if (fsync(dfd.get()) == -1) {
ALOGE("failed to fsync %s: %s", dir_name.c_str(), strerror(errno));
return -1;
return kUncryptFileSyncError;
}
if (close(dfd.get()) == -1) {
ALOGE("failed to close %s: %s", dir_name.c_str(), strerror(errno));
return -1;
return kUncryptFileCloseError;
}
dfd = -1;
return 0;
@@ -448,30 +450,58 @@ static int uncrypt(const char* input_path, const char* map_file, const int socke
// and /sdcard we leave the file alone.
if (strncmp(path, "/data/", 6) == 0) {
ALOGI("writing block map %s", map_file);
if (produce_block_map(path, map_file, blk_dev, encrypted, socket) != 0) {
return 1;
}
return produce_block_map(path, map_file, blk_dev, encrypted, socket);
}
return 0;
}
static void log_uncrypt_error_code(UncryptErrorCode error_code) {
if (!android::base::WriteStringToFile(android::base::StringPrintf(
"uncrypt_error: %d\n", error_code), UNCRYPT_STATUS)) {
ALOGW("failed to write to %s: %s", UNCRYPT_STATUS.c_str(), strerror(errno));
}
}
static bool uncrypt_wrapper(const char* input_path, const char* map_file, const int socket) {
// Initialize the uncrypt error to kUncryptErrorPlaceholder.
log_uncrypt_error_code(kUncryptErrorPlaceholder);
std::string package;
if (input_path == nullptr) {
if (!find_uncrypt_package(UNCRYPT_PATH_FILE, &package)) {
write_status_to_socket(-1, socket);
// Overwrite the error message.
log_uncrypt_error_code(kUncryptPackageMissingError);
return false;
}
input_path = package.c_str();
}
CHECK(map_file != nullptr);
auto start = std::chrono::system_clock::now();
int status = uncrypt(input_path, map_file, socket);
std::chrono::duration<double> duration = std::chrono::system_clock::now() - start;
int count = static_cast<int>(duration.count());
std::string uncrypt_message = android::base::StringPrintf("uncrypt_time: %d\n", count);
if (status != 0) {
// Log the time cost and error code if uncrypt fails.
uncrypt_message += android::base::StringPrintf("uncrypt_error: %d\n", status);
if (!android::base::WriteStringToFile(uncrypt_message, UNCRYPT_STATUS)) {
ALOGW("failed to write to %s: %s", UNCRYPT_STATUS.c_str(), strerror(errno));
}
write_status_to_socket(-1, socket);
return false;
}
if (!android::base::WriteStringToFile(uncrypt_message, UNCRYPT_STATUS)) {
ALOGW("failed to write to %s: %s", UNCRYPT_STATUS.c_str(), strerror(errno));
}
write_status_to_socket(100, socket);
return true;
}
@@ -561,6 +591,7 @@ int main(int argc, char** argv) {
}
if ((fstab = read_fstab()) == nullptr) {
log_uncrypt_error_code(kUncryptFstabReadError);
return 1;
}
@@ -569,18 +600,21 @@ int main(int argc, char** argv) {
unique_fd service_socket(android_get_control_socket(UNCRYPT_SOCKET.c_str()));
if (!service_socket) {
ALOGE("failed to open socket \"%s\": %s", UNCRYPT_SOCKET.c_str(), strerror(errno));
log_uncrypt_error_code(kUncryptSocketOpenError);
return 1;
}
fcntl(service_socket.get(), F_SETFD, FD_CLOEXEC);
if (listen(service_socket.get(), 1) == -1) {
ALOGE("failed to listen on socket %d: %s", service_socket.get(), strerror(errno));
log_uncrypt_error_code(kUncryptSocketListenError);
return 1;
}
unique_fd socket_fd(accept4(service_socket.get(), nullptr, nullptr, SOCK_CLOEXEC));
if (!socket_fd) {
ALOGE("failed to accept on socket %d: %s", service_socket.get(), strerror(errno));
log_uncrypt_error_code(kUncryptSocketAcceptError);
return 1;
}
+28 -1
View File
@@ -35,8 +35,10 @@
#include <inttypes.h>
#include <memory>
#include <string>
#include <vector>
#include <android-base/file.h>
#include <android-base/parseint.h>
#include <android-base/strings.h>
#include <android-base/stringprintf.h>
@@ -970,7 +972,6 @@ Value* GetPropFn(const char* name, State* state, int argc, Expr* argv[]) {
return StringValue(strdup(value));
}
// file_getprop(file, key)
//
// interprets 'file' as a getprop-style file (key=value pairs, one
@@ -1432,6 +1433,31 @@ Value* ReadFileFn(const char* name, State* state, int argc, Expr* argv[]) {
return v;
}
// write_value(value, filename)
// Writes 'value' to 'filename'.
// Example: write_value("960000", "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq")
Value* WriteValueFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc != 2) {
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
}
char* value;
char* filename;
if (ReadArgs(state, argv, 2, &value, &filename) < 0) {
return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)",
name);
}
bool ret = android::base::WriteStringToFile(value, filename);
if (!ret) {
printf("%s: Failed to write to \"%s\": %s\n", name, filename, strerror(errno));
}
free(value);
free(filename);
return StringValue(strdup(ret ? "t" : ""));
}
// Immediately reboot the device. Recovery is not finished normally,
// so if you reboot into recovery it will re-start applying the
// current package (because nothing has cleared the copy of the
@@ -1638,6 +1664,7 @@ void RegisterInstallFunctions() {
RegisterFunction("read_file", ReadFileFn);
RegisterFunction("sha1_check", Sha1CheckFn);
RegisterFunction("rename", RenameFn);
RegisterFunction("write_value", WriteValueFn);
RegisterFunction("wipe_cache", WipeCacheFn);
+6
View File
@@ -154,6 +154,12 @@ int verify_file(unsigned char* addr, size_t length) {
LOGI("comment is %zu bytes; signature %zu bytes from end\n",
comment_size, signature_start);
if (signature_start > comment_size) {
LOGE("signature start: %zu is larger than comment size: %zu\n", signature_start,
comment_size);
return VERIFY_FAILURE;
}
if (signature_start <= FOOTER_SIZE) {
LOGE("Signature start is in the footer");
return VERIFY_FAILURE;
+77 -283
View File
@@ -47,32 +47,13 @@ static double now() {
}
WearRecoveryUI::WearRecoveryUI() :
progress_bar_height(3),
progress_bar_width(200),
progress_bar_y(259),
outer_height(0),
outer_width(0),
menu_unusable_rows(0),
intro_frames(22),
loop_frames(60),
animation_fps(30),
currentIcon(NONE),
intro_done(false),
current_frame(0),
progressBarType(EMPTY),
progressScopeStart(0),
progressScopeSize(0),
progress(0),
text_cols(0),
text_rows(0),
text_col(0),
text_row(0),
text_top(0),
show_text(false),
show_text_ever(false),
show_menu(false),
menu_items(0),
menu_sel(0) {
menu_unusable_rows(0) {
intro_frames = 22;
loop_frames = 60;
animation_fps = 30;
for (size_t i = 0; i < 5; i++)
backgroundIcon[i] = NULL;
@@ -80,16 +61,22 @@ WearRecoveryUI::WearRecoveryUI() :
self = this;
}
int WearRecoveryUI::GetProgressBaseline() {
return progress_bar_y;
}
// Draw background frame on the screen. Does not flip pages.
// Should only be called with updateMutex locked.
void WearRecoveryUI::draw_background_locked(Icon icon)
// TODO merge drawing routines with screen_ui
void WearRecoveryUI::draw_background_locked()
{
pagesIdentical = false;
gr_color(0, 0, 0, 255);
gr_fill(0, 0, gr_fb_width(), gr_fb_height());
if (icon) {
if (currentIcon != NONE) {
GRSurface* surface;
if (icon == INSTALLING_UPDATE || icon == ERASING) {
if (currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) {
if (!intro_done) {
surface = introFrames[current_frame];
} else {
@@ -97,7 +84,7 @@ void WearRecoveryUI::draw_background_locked(Icon icon)
}
}
else {
surface = backgroundIcon[icon];
surface = backgroundIcon[currentIcon];
}
int width = gr_get_width(surface);
@@ -110,36 +97,6 @@ void WearRecoveryUI::draw_background_locked(Icon icon)
}
}
// Draw the progress bar (if any) on the screen. Does not flip pages.
// Should only be called with updateMutex locked.
void WearRecoveryUI::draw_progress_locked()
{
if (currentIcon == ERROR) return;
if (progressBarType != DETERMINATE) return;
int width = progress_bar_width;
int height = progress_bar_height;
int dx = (gr_fb_width() - width)/2;
int dy = progress_bar_y;
float p = progressScopeStart + progress * progressScopeSize;
int pos = (int) (p * width);
gr_color(0x43, 0x43, 0x43, 0xff);
gr_fill(dx, dy, dx + width, dy + height);
if (pos > 0) {
gr_color(0x02, 0xa8, 0xf3, 255);
if (rtl_locale) {
// Fill the progress bar from right to left.
gr_fill(dx + width - pos, dy, dx + width, dy + height);
} else {
// Fill the progress bar from left to right.
gr_fill(dx, dy, dx + pos, dy + height);
}
}
}
static const char* HEADERS[] = {
"Swipe up/down to move.",
"Swipe left/right to select.",
@@ -147,13 +104,15 @@ static const char* HEADERS[] = {
NULL
};
// TODO merge drawing routines with screen_ui
void WearRecoveryUI::draw_screen_locked()
{
draw_background_locked(currentIcon);
draw_progress_locked();
char cur_selection_str[50];
if (show_text) {
draw_background_locked();
if (!show_text) {
draw_foreground_locked();
} else {
SetColor(TEXT_FILL);
gr_fill(0, 0, gr_fb_width(), gr_fb_height());
@@ -177,7 +136,7 @@ void WearRecoveryUI::draw_screen_locked()
// items don't fit on the screen.
if (menu_items > menu_end - menu_start) {
sprintf(cur_selection_str, "Current item: %d/%d", menu_sel + 1, menu_items);
gr_text(x+4, y, cur_selection_str, 1);
gr_text(gr_sys_font(), x+4, y, cur_selection_str, 1);
y += char_height_+4;
}
@@ -192,10 +151,12 @@ void WearRecoveryUI::draw_screen_locked()
gr_fill(x, y-2, gr_fb_width()-x, y+char_height_+2);
// white text of selected item
SetColor(MENU_SEL_FG);
if (menu[i][0]) gr_text(x+4, y, menu[i], 1);
if (menu_[i][0]) {
gr_text(gr_sys_font(), x + 4, y, menu_[i], 1);
}
SetColor(MENU);
} else {
if (menu[i][0]) gr_text(x+4, y, menu[i], 0);
} else if (menu_[i][0]) {
gr_text(gr_sys_font(), x + 4, y, menu_[i], 0);
}
y += char_height_+4;
}
@@ -211,163 +172,43 @@ void WearRecoveryUI::draw_screen_locked()
// screen, the bottom of the menu, or we've displayed the
// entire text buffer.
int ty;
int row = (text_top+text_rows-1) % text_rows;
int row = (text_top_ + text_rows_ - 1) % text_rows_;
size_t count = 0;
for (int ty = gr_fb_height() - char_height_ - outer_height;
ty > y+2 && count < text_rows;
ty > y + 2 && count < text_rows_;
ty -= char_height_, ++count) {
gr_text(x+4, ty, text[row], 0);
gr_text(gr_sys_font(), x+4, ty, text_[row], 0);
--row;
if (row < 0) row = text_rows-1;
if (row < 0) row = text_rows_ - 1;
}
}
}
void WearRecoveryUI::update_screen_locked()
{
// TODO merge drawing routines with screen_ui
void WearRecoveryUI::update_progress_locked() {
draw_screen_locked();
gr_flip();
}
// Keeps the progress bar updated, even when the process is otherwise busy.
void* WearRecoveryUI::progress_thread(void *cookie) {
self->progress_loop();
return NULL;
}
void WearRecoveryUI::InitTextParams() {
ScreenRecoveryUI::InitTextParams();
void WearRecoveryUI::progress_loop() {
double interval = 1.0 / animation_fps;
for (;;) {
double start = now();
pthread_mutex_lock(&updateMutex);
int redraw = 0;
text_cols_ = (gr_fb_width() - (outer_width * 2)) / char_width_;
if ((currentIcon == INSTALLING_UPDATE || currentIcon == ERASING)
&& !show_text) {
if (!intro_done) {
if (current_frame >= intro_frames - 1) {
intro_done = true;
current_frame = 0;
} else {
current_frame++;
}
} else {
current_frame = (current_frame + 1) % loop_frames;
}
redraw = 1;
}
if (text_rows_ > kMaxRows) text_rows_ = kMaxRows;
if (text_cols_ > kMaxCols) text_cols_ = kMaxCols;
// move the progress bar forward on timed intervals, if configured
int duration = progressScopeDuration;
if (progressBarType == DETERMINATE && duration > 0) {
double elapsed = now() - progressScopeTime;
float p = 1.0 * elapsed / duration;
if (p > 1.0) p = 1.0;
if (p > progress) {
progress = p;
redraw = 1;
}
}
if (redraw)
update_screen_locked();
pthread_mutex_unlock(&updateMutex);
double end = now();
// minimum of 20ms delay between frames
double delay = interval - (end-start);
if (delay < 0.02) delay = 0.02;
usleep((long)(delay * 1000000));
}
}
void WearRecoveryUI::Init()
{
gr_init();
gr_font_size(&char_width_, &char_height_);
text_col = text_row = 0;
text_rows = (gr_fb_height()) / char_height_;
visible_text_rows = (gr_fb_height() - (outer_height * 2)) / char_height_;
if (text_rows > kMaxRows) text_rows = kMaxRows;
text_top = 1;
}
text_cols = (gr_fb_width() - (outer_width * 2)) / char_width_;
if (text_cols > kMaxCols - 1) text_cols = kMaxCols - 1;
void WearRecoveryUI::Init() {
ScreenRecoveryUI::Init();
LoadBitmap("icon_installing", &backgroundIcon[INSTALLING_UPDATE]);
backgroundIcon[ERASING] = backgroundIcon[INSTALLING_UPDATE];
LoadBitmap("icon_error", &backgroundIcon[ERROR]);
backgroundIcon[NO_COMMAND] = backgroundIcon[ERROR];
introFrames = (GRSurface**)malloc(intro_frames * sizeof(GRSurface*));
for (int i = 0; i < intro_frames; ++i) {
char filename[40];
sprintf(filename, "intro%02d", i);
LoadBitmap(filename, introFrames + i);
}
loopFrames = (GRSurface**)malloc(loop_frames * sizeof(GRSurface*));
for (int i = 0; i < loop_frames; ++i) {
char filename[40];
sprintf(filename, "loop%02d", i);
LoadBitmap(filename, loopFrames + i);
}
pthread_create(&progress_t, NULL, progress_thread, NULL);
RecoveryUI::Init();
}
void WearRecoveryUI::SetBackground(Icon icon)
{
pthread_mutex_lock(&updateMutex);
currentIcon = icon;
update_screen_locked();
pthread_mutex_unlock(&updateMutex);
}
void WearRecoveryUI::SetProgressType(ProgressType type)
{
pthread_mutex_lock(&updateMutex);
if (progressBarType != type) {
progressBarType = type;
}
progressScopeStart = 0;
progressScopeSize = 0;
progress = 0;
update_screen_locked();
pthread_mutex_unlock(&updateMutex);
}
void WearRecoveryUI::ShowProgress(float portion, float seconds)
{
pthread_mutex_lock(&updateMutex);
progressBarType = DETERMINATE;
progressScopeStart += progressScopeSize;
progressScopeSize = portion;
progressScopeTime = now();
progressScopeDuration = seconds;
progress = 0;
update_screen_locked();
pthread_mutex_unlock(&updateMutex);
}
void WearRecoveryUI::SetProgress(float fraction)
{
pthread_mutex_lock(&updateMutex);
if (fraction < 0.0) fraction = 0.0;
if (fraction > 1.0) fraction = 1.0;
if (progressBarType == DETERMINATE && fraction > progress) {
// Skip updates that aren't visibly different.
int width = progress_bar_width;
float scale = width * progressScopeSize;
if ((int) (progress * scale) != (int) (fraction * scale)) {
progress = fraction;
update_screen_locked();
}
}
pthread_mutex_unlock(&updateMutex);
// This leaves backgroundIcon[INSTALLING_UPDATE] and backgroundIcon[ERASING]
// as NULL which is fine since draw_background_locked() doesn't use them.
}
void WearRecoveryUI::SetStage(int current, int max)
@@ -386,40 +227,40 @@ void WearRecoveryUI::Print(const char *fmt, ...)
// This can get called before ui_init(), so be careful.
pthread_mutex_lock(&updateMutex);
if (text_rows > 0 && text_cols > 0) {
if (text_rows_ > 0 && text_cols_ > 0) {
char *ptr;
for (ptr = buf; *ptr != '\0'; ++ptr) {
if (*ptr == '\n' || text_col >= text_cols) {
text[text_row][text_col] = '\0';
text_col = 0;
text_row = (text_row + 1) % text_rows;
if (text_row == text_top) text_top = (text_top + 1) % text_rows;
if (*ptr == '\n' || text_col_ >= text_cols_) {
text_[text_row_][text_col_] = '\0';
text_col_ = 0;
text_row_ = (text_row_ + 1) % text_rows_;
if (text_row_ == text_top_) text_top_ = (text_top_ + 1) % text_rows_;
}
if (*ptr != '\n') text[text_row][text_col++] = *ptr;
if (*ptr != '\n') text_[text_row_][text_col_++] = *ptr;
}
text[text_row][text_col] = '\0';
text_[text_row_][text_col_] = '\0';
update_screen_locked();
}
pthread_mutex_unlock(&updateMutex);
}
void WearRecoveryUI::StartMenu(const char* const * headers, const char* const * items,
int initial_selection) {
int initial_selection) {
pthread_mutex_lock(&updateMutex);
if (text_rows > 0 && text_cols > 0) {
if (text_rows_ > 0 && text_cols_ > 0) {
menu_headers_ = headers;
size_t i = 0;
// "i < text_rows" is removed from the loop termination condition,
// "i < text_rows_" is removed from the loop termination condition,
// which is different from the one in ScreenRecoveryUI::StartMenu().
// Because WearRecoveryUI supports scrollable menu, it's fine to have
// more entries than text_rows. The menu may be truncated otherwise.
// more entries than text_rows_. The menu may be truncated otherwise.
// Bug: 23752519
for (; items[i] != nullptr; i++) {
strncpy(menu[i], items[i], text_cols - 1);
menu[i][text_cols - 1] = '\0';
strncpy(menu_[i], items[i], text_cols_ - 1);
menu_[i][text_cols_ - 1] = '\0';
}
menu_items = i;
show_menu = 1;
show_menu = true;
menu_sel = initial_selection;
menu_start = 0;
menu_end = visible_text_rows - 1 - menu_unusable_rows;
@@ -433,7 +274,7 @@ void WearRecoveryUI::StartMenu(const char* const * headers, const char* const *
int WearRecoveryUI::SelectMenu(int sel) {
int old_sel;
pthread_mutex_lock(&updateMutex);
if (show_menu > 0) {
if (show_menu) {
old_sel = menu_sel;
menu_sel = sel;
if (menu_sel < 0) menu_sel = 0;
@@ -452,53 +293,6 @@ int WearRecoveryUI::SelectMenu(int sel) {
return sel;
}
void WearRecoveryUI::EndMenu() {
int i;
pthread_mutex_lock(&updateMutex);
if (show_menu > 0 && text_rows > 0 && text_cols > 0) {
show_menu = 0;
update_screen_locked();
}
pthread_mutex_unlock(&updateMutex);
}
bool WearRecoveryUI::IsTextVisible()
{
pthread_mutex_lock(&updateMutex);
int visible = show_text;
pthread_mutex_unlock(&updateMutex);
return visible;
}
bool WearRecoveryUI::WasTextEverVisible()
{
pthread_mutex_lock(&updateMutex);
int ever_visible = show_text_ever;
pthread_mutex_unlock(&updateMutex);
return ever_visible;
}
void WearRecoveryUI::ShowText(bool visible)
{
pthread_mutex_lock(&updateMutex);
// Don't show text during ota install or factory reset
if (currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) {
pthread_mutex_unlock(&updateMutex);
return;
}
show_text = visible;
if (show_text) show_text_ever = 1;
update_screen_locked();
pthread_mutex_unlock(&updateMutex);
}
void WearRecoveryUI::Redraw()
{
pthread_mutex_lock(&updateMutex);
update_screen_locked();
pthread_mutex_unlock(&updateMutex);
}
void WearRecoveryUI::ShowFile(FILE* fp) {
std::vector<long> offsets;
offsets.push_back(ftell(fp));
@@ -538,12 +332,12 @@ void WearRecoveryUI::ShowFile(FILE* fp) {
int ch = getc(fp);
if (ch == EOF) {
text_row = text_top = text_rows - 2;
text_row_ = text_top_ = text_rows_ - 2;
show_prompt = true;
} else {
PutChar(ch);
if (text_col == 0 && text_row >= text_rows - 2) {
text_top = text_row;
if (text_col_ == 0 && text_row_ >= text_rows_ - 2) {
text_top_ = text_row_;
show_prompt = true;
}
}
@@ -552,10 +346,10 @@ void WearRecoveryUI::ShowFile(FILE* fp) {
void WearRecoveryUI::PutChar(char ch) {
pthread_mutex_lock(&updateMutex);
if (ch != '\n') text[text_row][text_col++] = ch;
if (ch == '\n' || text_col >= text_cols) {
text_col = 0;
++text_row;
if (ch != '\n') text_[text_row_][text_col_++] = ch;
if (ch == '\n' || text_col_ >= text_cols_) {
text_col_ = 0;
++text_row_;
}
pthread_mutex_unlock(&updateMutex);
}
@@ -572,11 +366,11 @@ void WearRecoveryUI::ShowFile(const char* filename) {
void WearRecoveryUI::ClearText() {
pthread_mutex_lock(&updateMutex);
text_col = 0;
text_row = 0;
text_top = 1;
for (size_t i = 0; i < text_rows; ++i) {
memset(text[i], 0, text_cols + 1);
text_col_ = 0;
text_row_ = 0;
text_top_ = 1;
for (size_t i = 0; i < text_rows_; ++i) {
memset(text_[i], 0, text_cols_ + 1);
}
pthread_mutex_unlock(&updateMutex);
}
@@ -597,17 +391,17 @@ void WearRecoveryUI::PrintV(const char* fmt, bool copy_to_stdout, va_list ap) {
}
pthread_mutex_lock(&updateMutex);
if (text_rows > 0 && text_cols > 0) {
if (text_rows_ > 0 && text_cols_ > 0) {
for (const char* ptr = str.c_str(); *ptr != '\0'; ++ptr) {
if (*ptr == '\n' || text_col >= text_cols) {
text[text_row][text_col] = '\0';
text_col = 0;
text_row = (text_row + 1) % text_rows;
if (text_row == text_top) text_top = (text_top + 1) % text_rows;
if (*ptr == '\n' || text_col_ >= text_cols_) {
text_[text_row_][text_col_] = '\0';
text_col_ = 0;
text_row_ = (text_row_ + 1) % text_rows_;
if (text_row_ == text_top_) text_top_ = (text_top_ + 1) % text_rows_;
}
if (*ptr != '\n') text[text_row][text_col++] = *ptr;
if (*ptr != '\n') text_[text_row_][text_col_++] = *ptr;
}
text[text_row][text_col] = '\0';
text_[text_row_][text_col_] = '\0';
update_screen_locked();
}
pthread_mutex_unlock(&updateMutex);
+17 -59
View File
@@ -23,39 +23,22 @@ class WearRecoveryUI : public ScreenRecoveryUI {
public:
WearRecoveryUI();
void Init();
// overall recovery state ("background image")
void SetBackground(Icon icon);
void Init() override;
// progress indicator
void SetProgressType(ProgressType type);
void ShowProgress(float portion, float seconds);
void SetProgress(float fraction);
void SetStage(int current, int max);
// text log
void ShowText(bool visible);
bool IsTextVisible();
bool WasTextEverVisible();
void SetStage(int current, int max) override;
// printing messages
void Print(const char* fmt, ...);
void PrintOnScreenOnly(const char* fmt, ...) __printflike(2, 3);
void ShowFile(const char* filename);
void ShowFile(FILE* fp);
void Print(const char* fmt, ...) override;
void PrintOnScreenOnly(const char* fmt, ...) override __printflike(2, 3);
void ShowFile(const char* filename) override;
void ShowFile(FILE* fp) override;
// menu display
void StartMenu(const char* const * headers, const char* const * items,
int initial_selection);
int SelectMenu(int sel);
void EndMenu();
void Redraw();
int initial_selection) override;
int SelectMenu(int sel) override;
protected:
int progress_bar_height, progress_bar_width;
// progress bar vertical position, it's centered horizontally
int progress_bar_y;
@@ -67,59 +50,34 @@ class WearRecoveryUI : public ScreenRecoveryUI {
// that may otherwise go out of the screen.
int menu_unusable_rows;
// number of intro frames (default: 22) and loop frames (default: 60)
int intro_frames;
int loop_frames;
int GetProgressBaseline() override;
// Number of frames per sec (default: 30) for both of intro and loop.
int animation_fps;
void InitTextParams() override;
void update_progress_locked() override;
void PrintV(const char*, bool, va_list) override;
private:
Icon currentIcon;
bool intro_done;
int current_frame;
GRSurface* backgroundIcon[5];
GRSurface* *introFrames;
GRSurface* *loopFrames;
ProgressType progressBarType;
float progressScopeStart, progressScopeSize, progress;
double progressScopeTime, progressScopeDuration;
static const int kMaxCols = 96;
static const int kMaxRows = 96;
// Log text overlay, displayed when a magic key is pressed
char text[kMaxRows][kMaxCols];
size_t text_cols, text_rows;
// Number of text rows seen on screen
int visible_text_rows;
size_t text_col, text_row, text_top;
bool show_text;
bool show_text_ever; // has show_text ever been true?
char menu[kMaxRows][kMaxCols];
bool show_menu;
const char* const* menu_headers_;
int menu_items, menu_sel;
int menu_start, menu_end;
pthread_t progress_t;
private:
void draw_background_locked(Icon icon);
void draw_background_locked() override;
void draw_screen_locked() override;
void draw_progress_locked();
void draw_screen_locked();
void update_screen_locked();
static void* progress_thread(void* cookie);
void progress_loop();
void PutChar(char);
void ClearText();
void PrintV(const char*, bool, va_list);
};
#endif // RECOVERY_WEAR_UI_H