summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--applypatch/imgdiff.cpp1
-rw-r--r--minui/graphics.cpp63
-rw-r--r--ui.cpp129
-rw-r--r--ui.h15
-rw-r--r--update_verifier/update_verifier.cpp70
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);
}
diff --git a/ui.cpp b/ui.cpp
index a0f741e57..3ecd6d125 100644
--- a/ui.cpp
+++ b/ui.cpp
@@ -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) {
diff --git a/ui.h b/ui.h
index 53ce0602f..823eb6574 100644
--- a/ui.h
+++ b/ui.h
@@ -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;
}