Update TWRP to AOSP 7.1.2
Change-Id: I19c1546efb4182aac62c690e3cc05b04e3a9a32e
This commit is contained in:
+3
-3
@@ -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
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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_
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -49,7 +49,7 @@ extern "C" {
|
||||
#include "adb.h"
|
||||
#else
|
||||
extern "C" {
|
||||
#include "minadbd.old/adb.h"
|
||||
#include "minadbd21/adb.h"
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+59
-25
@@ -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
@@ -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);
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user