diff options
-rw-r--r-- | applypatch/imgdiff.cpp | 1 | ||||
-rw-r--r-- | minui/graphics.cpp | 63 | ||||
-rw-r--r-- | ui.cpp | 129 | ||||
-rw-r--r-- | ui.h | 15 | ||||
-rw-r--r-- | update_verifier/update_verifier.cpp | 70 |
5 files changed, 186 insertions, 92 deletions
diff --git a/applypatch/imgdiff.cpp b/applypatch/imgdiff.cpp index 395150614..2f0e1651c 100644 --- a/applypatch/imgdiff.cpp +++ b/applypatch/imgdiff.cpp @@ -198,6 +198,7 @@ unsigned char* ReadZip(const char* filename, if (fread(img, 1, sz, f) != sz) { printf("failed to read \"%s\" %s\n", filename, strerror(errno)); fclose(f); + free(img); return NULL; } fclose(f); diff --git a/minui/graphics.cpp b/minui/graphics.cpp index 34ea81c7c..c0c67f948 100644 --- a/minui/graphics.cpp +++ b/minui/graphics.cpp @@ -16,21 +16,9 @@ #include "graphics.h" +#include <stdio.h> #include <stdlib.h> #include <string.h> -#include <unistd.h> - -#include <fcntl.h> -#include <stdio.h> - -#include <sys/ioctl.h> -#include <sys/mman.h> -#include <sys/types.h> - -#include <linux/fb.h> -#include <linux/kd.h> - -#include <time.h> #include "font_10x18.h" #include "minui/minui.h" @@ -319,55 +307,6 @@ static void gr_init_font(void) gr_font->char_height = font.char_height; } -#if 0 -// Exercises many of the gr_*() functions; useful for testing. -static void gr_test() { - GRSurface** images; - int frames; - int result = res_create_multi_surface("icon_installing", &frames, &images); - if (result < 0) { - printf("create surface %d\n", result); - gr_exit(); - return; - } - - time_t start = time(NULL); - int x; - for (x = 0; x <= 1200; ++x) { - if (x < 400) { - gr_color(0, 0, 0, 255); - } else { - gr_color(0, (x-400)%128, 0, 255); - } - gr_clear(); - - gr_color(255, 0, 0, 255); - GRSurface* frame = images[x%frames]; - gr_blit(frame, 0, 0, frame->width, frame->height, x, 0); - - gr_color(255, 0, 0, 128); - gr_fill(400, 150, 600, 350); - - gr_color(255, 255, 255, 255); - gr_text(500, 225, "hello, world!", 0); - gr_color(255, 255, 0, 128); - gr_text(300+x, 275, "pack my box with five dozen liquor jugs", 1); - - gr_color(0, 0, 255, 128); - gr_fill(gr_draw->width - 200 - x, 300, gr_draw->width - x, 500); - - gr_draw = gr_backend->flip(gr_backend); - } - printf("getting end time\n"); - time_t end = time(NULL); - printf("got end time\n"); - printf("start %ld end %ld\n", (long)start, (long)end); - if (end > start) { - printf("%.2f fps\n", ((double)x) / (end-start)); - } -} -#endif - void gr_flip() { gr_draw = gr_backend->flip(gr_backend); } @@ -32,7 +32,11 @@ #include <string> +#include <android-base/file.h> +#include <android-base/logging.h> +#include <android-base/parseint.h> #include <android-base/properties.h> +#include <android-base/strings.h> #include <cutils/android_reboot.h> #include <minui/minui.h> @@ -40,11 +44,15 @@ #include "roots.h" #include "device.h" -#define UI_WAIT_KEY_TIMEOUT_SEC 120 +static constexpr int UI_WAIT_KEY_TIMEOUT_SEC = 120; +static constexpr const char* BRIGHTNESS_FILE = "/sys/class/leds/lcd-backlight/brightness"; +static constexpr const char* MAX_BRIGHTNESS_FILE = "/sys/class/leds/lcd-backlight/max_brightness"; RecoveryUI::RecoveryUI() : locale_(""), rtl_locale_(false), + brightness_normal_(50), + brightness_dimmed_(25), key_queue_len(0), key_last_down(-1), key_long_press(false), @@ -54,7 +62,8 @@ RecoveryUI::RecoveryUI() last_key(-1), has_power_key(false), has_up_key(false), - has_down_key(false) { + has_down_key(false), + screensaver_state_(ScreensaverState::DISABLED) { pthread_mutex_init(&key_queue_mutex, nullptr); pthread_cond_init(&key_queue_cond, nullptr); memset(key_pressed, 0, sizeof(key_pressed)); @@ -80,6 +89,40 @@ static void* InputThreadLoop(void*) { return nullptr; } +bool RecoveryUI::InitScreensaver() { + // Disabled. + if (brightness_normal_ == 0 || brightness_dimmed_ > brightness_normal_) { + return false; + } + + // Set the initial brightness level based on the max brightness. Note that reading the initial + // value from BRIGHTNESS_FILE doesn't give the actual brightness value (bullhead, sailfish), so + // we don't have a good way to query the default value. + std::string content; + if (!android::base::ReadFileToString(MAX_BRIGHTNESS_FILE, &content)) { + PLOG(WARNING) << "Failed to read max brightness"; + return false; + } + + unsigned int max_value; + if (!android::base::ParseUint(android::base::Trim(content), &max_value)) { + LOG(WARNING) << "Failed to parse max brightness: " << content; + return false; + } + + brightness_normal_value_ = max_value * brightness_normal_ / 100.0; + brightness_dimmed_value_ = max_value * brightness_dimmed_ / 100.0; + if (!android::base::WriteStringToFile(std::to_string(brightness_normal_value_), + BRIGHTNESS_FILE)) { + PLOG(WARNING) << "Failed to set brightness"; + return false; + } + + LOG(INFO) << "Brightness: " << brightness_normal_value_ << " (" << brightness_normal_ << "%)"; + screensaver_state_ = ScreensaverState::NORMAL; + return true; +} + bool RecoveryUI::Init(const std::string& locale) { // Set up the locale info. SetLocale(locale); @@ -88,6 +131,10 @@ bool RecoveryUI::Init(const std::string& locale) { ev_iterate_available_keys(std::bind(&RecoveryUI::OnKeyDetected, this, std::placeholders::_1)); + if (!InitScreensaver()) { + LOG(INFO) << "Screensaver disabled"; + } + pthread_create(&input_thread_, nullptr, InputThreadLoop, nullptr); return true; } @@ -220,31 +267,65 @@ void RecoveryUI::EnqueueKey(int key_code) { } int RecoveryUI::WaitKey() { - pthread_mutex_lock(&key_queue_mutex); + pthread_mutex_lock(&key_queue_mutex); + + // Time out after UI_WAIT_KEY_TIMEOUT_SEC, unless a USB cable is + // plugged in. + do { + struct timeval now; + struct timespec timeout; + gettimeofday(&now, nullptr); + timeout.tv_sec = now.tv_sec; + timeout.tv_nsec = now.tv_usec * 1000; + timeout.tv_sec += UI_WAIT_KEY_TIMEOUT_SEC; + + int rc = 0; + while (key_queue_len == 0 && rc != ETIMEDOUT) { + rc = pthread_cond_timedwait(&key_queue_cond, &key_queue_mutex, &timeout); + } - // Time out after UI_WAIT_KEY_TIMEOUT_SEC, unless a USB cable is - // plugged in. - do { - struct timeval now; - struct timespec timeout; - gettimeofday(&now, nullptr); - timeout.tv_sec = now.tv_sec; - timeout.tv_nsec = now.tv_usec * 1000; - timeout.tv_sec += UI_WAIT_KEY_TIMEOUT_SEC; - - int rc = 0; - while (key_queue_len == 0 && rc != ETIMEDOUT) { - rc = pthread_cond_timedwait(&key_queue_cond, &key_queue_mutex, &timeout); + if (screensaver_state_ != ScreensaverState::DISABLED) { + if (rc == ETIMEDOUT) { + // Lower the brightness level: NORMAL -> DIMMED; DIMMED -> OFF. + if (screensaver_state_ == ScreensaverState::NORMAL) { + if (android::base::WriteStringToFile(std::to_string(brightness_dimmed_value_), + BRIGHTNESS_FILE)) { + LOG(INFO) << "Brightness: " << brightness_dimmed_value_ << " (" << brightness_dimmed_ + << "%)"; + screensaver_state_ = ScreensaverState::DIMMED; + } + } else if (screensaver_state_ == ScreensaverState::DIMMED) { + if (android::base::WriteStringToFile("0", BRIGHTNESS_FILE)) { + LOG(INFO) << "Brightness: 0 (off)"; + screensaver_state_ = ScreensaverState::OFF; + } + } + } else if (screensaver_state_ != ScreensaverState::NORMAL) { + // Drop the first key if it's changing from OFF to NORMAL. + if (screensaver_state_ == ScreensaverState::OFF) { + if (key_queue_len > 0) { + memcpy(&key_queue[0], &key_queue[1], sizeof(int) * --key_queue_len); + } } - } while (IsUsbConnected() && key_queue_len == 0); - int key = -1; - if (key_queue_len > 0) { - key = key_queue[0]; - memcpy(&key_queue[0], &key_queue[1], sizeof(int) * --key_queue_len); + // Reset the brightness to normal. + if (android::base::WriteStringToFile(std::to_string(brightness_normal_value_), + BRIGHTNESS_FILE)) { + screensaver_state_ = ScreensaverState::NORMAL; + LOG(INFO) << "Brightness: " << brightness_normal_value_ << " (" << brightness_normal_ + << "%)"; + } + } } - pthread_mutex_unlock(&key_queue_mutex); - return key; + } while (IsUsbConnected() && key_queue_len == 0); + + int key = -1; + if (key_queue_len > 0) { + key = key_queue[0]; + memcpy(&key_queue[0], &key_queue[1], sizeof(int) * --key_queue_len); + } + pthread_mutex_unlock(&key_queue_mutex); + return key; } bool RecoveryUI::IsUsbConnected() { @@ -330,7 +411,7 @@ RecoveryUI::KeyAction RecoveryUI::CheckKey(int key, bool is_long_press) { } last_key = key; - return IsTextVisible() ? ENQUEUE : IGNORE; + return (IsTextVisible() || screensaver_state_ == ScreensaverState::OFF) ? ENQUEUE : IGNORE; } void RecoveryUI::KeyLongPress(int) { @@ -130,6 +130,13 @@ class RecoveryUI { std::string locale_; bool rtl_locale_; + // The normal and dimmed brightness percentages (default: 50 and 25, which means 50% and 25% + // of the max_brightness). Because the absolute values may vary across devices. These two + // values can be configured via subclassing. Setting brightness_normal_ to 0 to disable + // screensaver. + unsigned int brightness_normal_; + unsigned int brightness_dimmed_; + private: // Key event input queue pthread_mutex_t key_queue_mutex; @@ -167,6 +174,14 @@ class RecoveryUI { void time_key(int key_code, int count); void SetLocale(const std::string&); + + enum class ScreensaverState { DISABLED, NORMAL, DIMMED, OFF }; + ScreensaverState screensaver_state_; + // The following two contain the absolute values computed from brightness_normal_ and + // brightness_dimmed_ respectively. + unsigned int brightness_normal_value_; + unsigned int brightness_dimmed_value_; + bool InitScreensaver(); }; #endif // RECOVERY_UI_H diff --git a/update_verifier/update_verifier.cpp b/update_verifier/update_verifier.cpp index 1c9be2d58..a4799cc31 100644 --- a/update_verifier/update_verifier.cpp +++ b/update_verifier/update_verifier.cpp @@ -30,6 +30,7 @@ * verifier reaches the end after the verification. */ +#include <dirent.h> #include <errno.h> #include <fcntl.h> #include <stdio.h> @@ -52,14 +53,71 @@ using android::hardware::boot::V1_0::BoolResult; using android::hardware::boot::V1_0::CommandResult; constexpr auto CARE_MAP_FILE = "/data/ota_package/care_map.txt"; +constexpr auto DM_PATH_PREFIX = "/sys/block/"; +constexpr auto DM_PATH_SUFFIX = "/dm/name"; +constexpr auto DEV_PATH = "/dev/block/"; constexpr int BLOCKSIZE = 4096; -static bool read_blocks(const std::string& blk_device_prefix, const std::string& range_str) { - std::string slot_suffix = android::base::GetProperty("ro.boot.slot_suffix", ""); - std::string blk_device = blk_device_prefix + slot_suffix; - android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(blk_device.c_str(), O_RDONLY))); +// Find directories in format of "/sys/block/dm-X". +static int dm_name_filter(const dirent* de) { + if (android::base::StartsWith(de->d_name, "dm-")) { + return 1; + } + return 0; +} + +static bool read_blocks(const std::string& blk_device, const std::string& range_str) { + // Parse the partition in the end of the block_device string. + // Here is one example: "/dev/block/bootdevice/by-name/system" + std::string partition; + if (android::base::EndsWith(blk_device, "system")) { + partition = "system"; + } else if (android::base::EndsWith(blk_device, "vendor")) { + partition = "vendor"; + } else { + LOG(ERROR) << "Failed to parse partition string in " << blk_device; + return false; + } + + // Iterate the content of "/sys/block/dm-X/dm/name". If it matches "system" + // (or "vendor"), then dm-X is a dm-wrapped system/vendor partition. + // Afterwards, update_verifier will read every block on the care_map_file of + // "/dev/block/dm-X" to ensure the partition's integrity. + dirent** namelist; + int n = scandir(DM_PATH_PREFIX, &namelist, dm_name_filter, alphasort); + if (n == -1) { + PLOG(ERROR) << "Failed to scan dir " << DM_PATH_PREFIX; + return false; + } + if (n == 0) { + LOG(ERROR) << "dm block device not found for " << partition; + return false; + } + + std::string dm_block_device; + while (n--) { + std::string path = DM_PATH_PREFIX + std::string(namelist[n]->d_name) + DM_PATH_SUFFIX; + std::string content; + if (!android::base::ReadFileToString(path, &content)) { + PLOG(WARNING) << "Failed to read " << path; + } else if (android::base::Trim(content) == partition) { + dm_block_device = DEV_PATH + std::string(namelist[n]->d_name); + while (n--) { + free(namelist[n]); + } + break; + } + free(namelist[n]); + } + free(namelist); + + if (dm_block_device.empty()) { + LOG(ERROR) << "Failed to find dm block device for " << partition; + return false; + } + android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(dm_block_device.c_str(), O_RDONLY))); if (fd.get() == -1) { - PLOG(ERROR) << "Error reading partition " << blk_device; + PLOG(ERROR) << "Error reading " << dm_block_device << " for partition " << partition; return false; } @@ -100,7 +158,7 @@ static bool read_blocks(const std::string& blk_device_prefix, const std::string& blk_count += (range_end - range_start); } - LOG(INFO) << "Finished reading " << blk_count << " blocks on " << blk_device; + LOG(INFO) << "Finished reading " << blk_count << " blocks on " << dm_block_device; return true; } |