Merge "Fix IWYU errors." am: 51dcd0d
am: 405db92
* commit '405db92b6e6384f0f22ba6be338c08e8f1aad345':
Fix IWYU errors.
Change-Id: Iedb6480e232c560ff9095f5593f13ad412616e4d
diff --git a/Android.mk b/Android.mk
index 95e806f..355f4d8 100644
--- a/Android.mk
+++ b/Android.mk
@@ -43,6 +43,7 @@
ui.cpp \
verifier.cpp \
wear_ui.cpp \
+ wear_touch.cpp \
LOCAL_MODULE := recovery
diff --git a/device.cpp b/device.cpp
index fd1a987..2465b07 100644
--- a/device.cpp
+++ b/device.cpp
@@ -25,6 +25,7 @@
"Wipe cache partition",
"Mount /system",
"View recovery logs",
+ "Run graphics test",
"Power off",
NULL
};
@@ -43,7 +44,8 @@
case 5: return WIPE_CACHE;
case 6: return MOUNT_SYSTEM;
case 7: return VIEW_RECOVERY_LOGS;
- case 8: return SHUTDOWN;
+ case 8: return RUN_GRAPHICS_TEST;
+ case 9: return SHUTDOWN;
default: return NO_ACTION;
}
}
diff --git a/device.h b/device.h
index f74b6b0..5017782 100644
--- a/device.h
+++ b/device.h
@@ -68,6 +68,7 @@
SHUTDOWN = 8,
VIEW_RECOVERY_LOGS = 9,
MOUNT_SYSTEM = 10,
+ RUN_GRAPHICS_TEST = 11,
};
// Return the list of menu items (an array of strings,
diff --git a/install.cpp b/install.cpp
index a7b59c3..7113fa2 100644
--- a/install.cpp
+++ b/install.cpp
@@ -23,6 +23,7 @@
#include <sys/wait.h>
#include <unistd.h>
+#include <chrono>
#include <vector>
#include "common.h"
@@ -228,6 +229,7 @@
return INSTALL_CORRUPT;
}
+ // Load keys.
std::vector<Certificate> loadedKeys;
if (!load_keys(PUBLIC_KEYS_FILE, loadedKeys)) {
LOGE("Failed to load keys\n");
@@ -235,18 +237,19 @@
}
LOGI("%zu key(s) loaded from %s\n", loadedKeys.size(), PUBLIC_KEYS_FILE);
+ // Verify package.
ui->Print("Verifying update package...\n");
-
+ auto t0 = std::chrono::system_clock::now();
int err = verify_file(map.addr, map.length, loadedKeys);
- LOGI("verify_file returned %d\n", err);
+ std::chrono::duration<double> duration = std::chrono::system_clock::now() - t0;
+ ui->Print("Update package verification took %.1f s (result %d).\n", duration.count(), err);
if (err != VERIFY_SUCCESS) {
LOGE("signature verification failed\n");
sysReleaseMap(&map);
return INSTALL_CORRUPT;
}
- /* Try to open the package.
- */
+ // Try to open the package.
ZipArchive zip;
err = mzOpenZipArchive(map.addr, map.length, &zip);
if (err != 0) {
@@ -255,8 +258,7 @@
return INSTALL_CORRUPT;
}
- /* Verify and install the contents of the package.
- */
+ // Verify and install the contents of the package.
ui->Print("Installing update...\n");
ui->SetEnableReboot(false);
int result = try_update_binary(path, &zip, wipe_cache);
diff --git a/minui/resources.cpp b/minui/resources.cpp
index 8489d60..cf738a7 100644
--- a/minui/resources.cpp
+++ b/minui/resources.cpp
@@ -33,8 +33,6 @@
#include "minui.h"
-extern char* locale;
-
#define SURFACE_DATA_ALIGNMENT 8
static GRSurface* malloc_surface(size_t data_size) {
diff --git a/minzip/SysUtil.c b/minzip/SysUtil.c
index 09ec876..e7dd17b 100644
--- a/minzip/SysUtil.c
+++ b/minzip/SysUtil.c
@@ -39,6 +39,11 @@
pMap->length = sb.st_size;
pMap->range_count = 1;
pMap->ranges = malloc(sizeof(MappedRange));
+ if (pMap->ranges == NULL) {
+ LOGE("malloc failed: %s\n", strerror(errno));
+ munmap(memPtr, sb.st_size);
+ return false;
+ }
pMap->ranges[0].addr = memPtr;
pMap->ranges[0].length = sb.st_size;
@@ -50,7 +55,7 @@
char block_dev[PATH_MAX+1];
size_t size;
unsigned int blksize;
- unsigned int blocks;
+ size_t blocks;
unsigned int range_count;
unsigned int i;
@@ -69,49 +74,80 @@
LOGE("failed to parse block map header\n");
return -1;
}
-
- blocks = ((size-1) / blksize) + 1;
+ if (blksize != 0) {
+ blocks = ((size-1) / blksize) + 1;
+ }
+ if (size == 0 || blksize == 0 || blocks > SIZE_MAX / blksize || range_count == 0) {
+ LOGE("invalid data in block map file: size %zu, blksize %u, range_count %u\n",
+ size, blksize, range_count);
+ return -1;
+ }
pMap->range_count = range_count;
- pMap->ranges = malloc(range_count * sizeof(MappedRange));
- memset(pMap->ranges, 0, range_count * sizeof(MappedRange));
+ pMap->ranges = calloc(range_count, sizeof(MappedRange));
+ if (pMap->ranges == NULL) {
+ LOGE("calloc(%u, %zu) failed: %s\n", range_count, sizeof(MappedRange), strerror(errno));
+ return -1;
+ }
// Reserve enough contiguous address space for the whole file.
unsigned char* reserve;
reserve = mmap64(NULL, blocks * blksize, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0);
if (reserve == MAP_FAILED) {
LOGE("failed to reserve address space: %s\n", strerror(errno));
+ free(pMap->ranges);
return -1;
}
- pMap->ranges[range_count-1].addr = reserve;
- pMap->ranges[range_count-1].length = blocks * blksize;
-
int fd = open(block_dev, O_RDONLY);
if (fd < 0) {
LOGE("failed to open block device %s: %s\n", block_dev, strerror(errno));
+ munmap(reserve, blocks * blksize);
+ free(pMap->ranges);
return -1;
}
unsigned char* next = reserve;
+ size_t remaining_size = blocks * blksize;
+ bool success = true;
for (i = 0; i < range_count; ++i) {
- int start, end;
- if (fscanf(mapf, "%d %d\n", &start, &end) != 2) {
+ size_t start, end;
+ if (fscanf(mapf, "%zu %zu\n", &start, &end) != 2) {
LOGE("failed to parse range %d in block map\n", i);
- return -1;
+ success = false;
+ break;
+ }
+ size_t length = (end - start) * blksize;
+ if (end <= start || (end - start) > SIZE_MAX / blksize || length > remaining_size) {
+ LOGE("unexpected range in block map: %zu %zu\n", start, end);
+ success = false;
+ break;
}
- void* addr = mmap64(next, (end-start)*blksize, PROT_READ, MAP_PRIVATE | MAP_FIXED, fd, ((off64_t)start)*blksize);
+ void* addr = mmap64(next, length, PROT_READ, MAP_PRIVATE | MAP_FIXED, fd, ((off64_t)start)*blksize);
if (addr == MAP_FAILED) {
LOGE("failed to map block %d: %s\n", i, strerror(errno));
- return -1;
+ success = false;
+ break;
}
pMap->ranges[i].addr = addr;
- pMap->ranges[i].length = (end-start)*blksize;
+ pMap->ranges[i].length = length;
- next += pMap->ranges[i].length;
+ next += length;
+ remaining_size -= length;
+ }
+ if (success && remaining_size != 0) {
+ LOGE("ranges in block map are invalid: remaining_size = %zu\n", remaining_size);
+ success = false;
+ }
+ if (!success) {
+ close(fd);
+ munmap(reserve, blocks * blksize);
+ free(pMap->ranges);
+ return -1;
}
+ close(fd);
pMap->addr = reserve;
pMap->length = size;
@@ -134,6 +170,7 @@
if (sysMapBlockFile(mapf, pMap) != 0) {
LOGE("Map of '%s' failed\n", fn);
+ fclose(mapf);
return -1;
}
diff --git a/otafault/Android.mk b/otafault/Android.mk
index 50e385e..d0b1174 100644
--- a/otafault/Android.mk
+++ b/otafault/Android.mk
@@ -14,8 +14,6 @@
LOCAL_PATH := $(call my-dir)
-# otafault (static library)
-# ===============================
include $(CLEAR_VARS)
otafault_static_libs := \
@@ -25,11 +23,12 @@
libselinux
LOCAL_SRC_FILES := config.cpp ota_io.cpp
+LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := libotafault
LOCAL_CLANG := true
LOCAL_C_INCLUDES := bootable/recovery
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
-LOCAL_STATIC_LIBRARIES := $(otafault_static_libs)
+LOCAL_WHOLE_STATIC_LIBRARIES := $(otafault_static_libs)
include $(BUILD_STATIC_LIBRARY)
@@ -40,9 +39,7 @@
LOCAL_SRC_FILES := config.cpp ota_io.cpp test.cpp
LOCAL_MODULE_TAGS := tests
LOCAL_MODULE := otafault_test
-LOCAL_STATIC_LIBRARIES := \
- libotafault \
- $(otafault_static_libs)
+LOCAL_STATIC_LIBRARIES := $(otafault_static_libs)
LOCAL_C_INCLUDES := bootable/recovery
LOCAL_FORCE_STATIC_EXECUTABLE := true
diff --git a/otafault/ota_io.cpp b/otafault/ota_io.cpp
index dd805e5..94be815 100644
--- a/otafault/ota_io.cpp
+++ b/otafault/ota_io.cpp
@@ -29,7 +29,6 @@
static std::string read_fault_file_name = "";
static std::string write_fault_file_name = "";
static std::string fsync_fault_file_name = "";
-bool have_eio_error = false;
static bool get_hit_file(const char* cached_path, std::string ffn) {
return should_hit_cache()
@@ -49,6 +48,8 @@
}
}
+bool have_eio_error = false;
+
int ota_open(const char* path, int oflags) {
// Let the caller handle errors; we do not care if open succeeds or fails
int fd = open(path, oflags);
diff --git a/recovery.cpp b/recovery.cpp
index 169413a..756e1c5 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -83,7 +83,10 @@
static const char *LOG_FILE = "/cache/recovery/log";
static const char *LAST_INSTALL_FILE = "/cache/recovery/last_install";
static const char *LOCALE_FILE = "/cache/recovery/last_locale";
+static const char *CONVERT_FBE_DIR = "/tmp/convert_fbe";
+static const char *CONVERT_FBE_FILE = "/tmp/convert_fbe/convert_fbe";
static const char *CACHE_ROOT = "/cache";
+static const char *DATA_ROOT = "/data";
static const char *SDCARD_ROOT = "/sdcard";
static const char *TEMPORARY_LOG_FILE = "/tmp/recovery.log";
static const char *TEMPORARY_INSTALL_FILE = "/tmp/last_install";
@@ -99,7 +102,7 @@
static const int BATTERY_WITH_CHARGER_OK_PERCENTAGE = 15;
RecoveryUI* ui = NULL;
-char* locale = NULL;
+static const char* locale = "en_US";
char* stage = NULL;
char* reason = NULL;
bool modified_flash = false;
@@ -530,6 +533,7 @@
static bool erase_volume(const char* volume) {
bool is_cache = (strcmp(volume, CACHE_ROOT) == 0);
+ bool is_data = (strcmp(volume, DATA_ROOT) == 0);
ui->SetBackground(RecoveryUI::ERASING);
ui->SetProgressType(RecoveryUI::INDETERMINATE);
@@ -584,7 +588,28 @@
ui->Print("Formatting %s...\n", volume);
ensure_path_unmounted(volume);
- int result = format_volume(volume);
+
+ int result;
+
+ if (is_data && reason && strcmp(reason, "convert_fbe") == 0) {
+ // Create convert_fbe breadcrumb file to signal to init
+ // to convert to file based encryption, not full disk encryption
+ if (mkdir(CONVERT_FBE_DIR, 0700) != 0) {
+ ui->Print("Failed to make convert_fbe dir %s\n", strerror(errno));
+ return true;
+ }
+ FILE* f = fopen(CONVERT_FBE_FILE, "wb");
+ if (!f) {
+ ui->Print("Failed to convert to file encryption %s\n", strerror(errno));
+ return true;
+ }
+ fclose(f);
+ result = format_volume(volume, CONVERT_FBE_DIR);
+ remove(CONVERT_FBE_FILE);
+ rmdir(CONVERT_FBE_DIR);
+ } else {
+ result = format_volume(volume);
+ }
if (is_cache) {
while (head) {
@@ -870,6 +895,37 @@
}
}
+static void run_graphics_test(Device* device) {
+ // Switch to graphics screen.
+ ui->ShowText(false);
+
+ ui->SetProgressType(RecoveryUI::INDETERMINATE);
+ ui->SetBackground(RecoveryUI::INSTALLING_UPDATE);
+ sleep(1);
+
+ ui->SetBackground(RecoveryUI::ERROR);
+ sleep(1);
+
+ ui->SetBackground(RecoveryUI::NO_COMMAND);
+ sleep(1);
+
+ ui->SetBackground(RecoveryUI::ERASING);
+ sleep(1);
+
+ ui->SetBackground(RecoveryUI::INSTALLING_UPDATE);
+
+ ui->SetProgressType(RecoveryUI::DETERMINATE);
+ ui->ShowProgress(1.0, 10.0);
+ float fraction = 0.0;
+ for (size_t i = 0; i < 100; ++i) {
+ fraction += .01;
+ ui->SetProgress(fraction);
+ usleep(100000);
+ }
+
+ ui->ShowText(true);
+}
+
// How long (in seconds) we wait for the fuse-provided package file to
// appear, before timing out.
#define SDCARD_INSTALL_TIMEOUT 10
@@ -1028,6 +1084,10 @@
choose_recovery_file(device);
break;
+ case Device::RUN_GRAPHICS_TEST:
+ run_graphics_test(device);
+ break;
+
case Device::MOUNT_SYSTEM:
char system_root_image[PROPERTY_VALUE_MAX];
property_get("ro.build.system_root_image", system_root_image, "");
diff --git a/res-hdpi/images/icon_installing.png b/res-hdpi/images/icon_installing.png
deleted file mode 100644
index 0fcfbc2..0000000
--- a/res-hdpi/images/icon_installing.png
+++ /dev/null
Binary files differ
diff --git a/res-hdpi/images/loop00.png b/res-hdpi/images/loop00.png
new file mode 100644
index 0000000..c7f8084
--- /dev/null
+++ b/res-hdpi/images/loop00.png
Binary files differ
diff --git a/res-hdpi/images/loop01.png b/res-hdpi/images/loop01.png
new file mode 100644
index 0000000..31ed667
--- /dev/null
+++ b/res-hdpi/images/loop01.png
Binary files differ
diff --git a/res-hdpi/images/loop02.png b/res-hdpi/images/loop02.png
new file mode 100644
index 0000000..1143407
--- /dev/null
+++ b/res-hdpi/images/loop02.png
Binary files differ
diff --git a/res-hdpi/images/loop03.png b/res-hdpi/images/loop03.png
new file mode 100644
index 0000000..040eeb2
--- /dev/null
+++ b/res-hdpi/images/loop03.png
Binary files differ
diff --git a/res-hdpi/images/loop04.png b/res-hdpi/images/loop04.png
new file mode 100644
index 0000000..58e139d
--- /dev/null
+++ b/res-hdpi/images/loop04.png
Binary files differ
diff --git a/res-hdpi/images/loop05.png b/res-hdpi/images/loop05.png
new file mode 100644
index 0000000..f0c2500
--- /dev/null
+++ b/res-hdpi/images/loop05.png
Binary files differ
diff --git a/res-hdpi/images/loop06.png b/res-hdpi/images/loop06.png
new file mode 100644
index 0000000..e8c5b21
--- /dev/null
+++ b/res-hdpi/images/loop06.png
Binary files differ
diff --git a/res-hdpi/images/loop07.png b/res-hdpi/images/loop07.png
new file mode 100644
index 0000000..ee0523f
--- /dev/null
+++ b/res-hdpi/images/loop07.png
Binary files differ
diff --git a/res-hdpi/images/loop08.png b/res-hdpi/images/loop08.png
new file mode 100644
index 0000000..f568a1c
--- /dev/null
+++ b/res-hdpi/images/loop08.png
Binary files differ
diff --git a/res-hdpi/images/loop09.png b/res-hdpi/images/loop09.png
new file mode 100644
index 0000000..9fed668
--- /dev/null
+++ b/res-hdpi/images/loop09.png
Binary files differ
diff --git a/res-hdpi/images/loop10.png b/res-hdpi/images/loop10.png
new file mode 100644
index 0000000..93edfcc
--- /dev/null
+++ b/res-hdpi/images/loop10.png
Binary files differ
diff --git a/res-hdpi/images/loop11.png b/res-hdpi/images/loop11.png
new file mode 100644
index 0000000..827fce8
--- /dev/null
+++ b/res-hdpi/images/loop11.png
Binary files differ
diff --git a/res-hdpi/images/loop12.png b/res-hdpi/images/loop12.png
new file mode 100644
index 0000000..927f04e
--- /dev/null
+++ b/res-hdpi/images/loop12.png
Binary files differ
diff --git a/res-hdpi/images/loop13.png b/res-hdpi/images/loop13.png
new file mode 100644
index 0000000..2856f31
--- /dev/null
+++ b/res-hdpi/images/loop13.png
Binary files differ
diff --git a/res-hdpi/images/loop14.png b/res-hdpi/images/loop14.png
new file mode 100644
index 0000000..3a2c14d
--- /dev/null
+++ b/res-hdpi/images/loop14.png
Binary files differ
diff --git a/res-hdpi/images/loop15.png b/res-hdpi/images/loop15.png
new file mode 100644
index 0000000..dcde383
--- /dev/null
+++ b/res-hdpi/images/loop15.png
Binary files differ
diff --git a/res-hdpi/images/loop16.png b/res-hdpi/images/loop16.png
new file mode 100644
index 0000000..7ba01f3
--- /dev/null
+++ b/res-hdpi/images/loop16.png
Binary files differ
diff --git a/res-hdpi/images/loop17.png b/res-hdpi/images/loop17.png
new file mode 100644
index 0000000..82a875f
--- /dev/null
+++ b/res-hdpi/images/loop17.png
Binary files differ
diff --git a/res-hdpi/images/loop18.png b/res-hdpi/images/loop18.png
new file mode 100644
index 0000000..00537e7
--- /dev/null
+++ b/res-hdpi/images/loop18.png
Binary files differ
diff --git a/res-hdpi/images/loop19.png b/res-hdpi/images/loop19.png
new file mode 100644
index 0000000..add8942
--- /dev/null
+++ b/res-hdpi/images/loop19.png
Binary files differ
diff --git a/res-hdpi/images/loop20.png b/res-hdpi/images/loop20.png
new file mode 100644
index 0000000..3c6f744
--- /dev/null
+++ b/res-hdpi/images/loop20.png
Binary files differ
diff --git a/res-hdpi/images/loop21.png b/res-hdpi/images/loop21.png
new file mode 100644
index 0000000..e1d1adb
--- /dev/null
+++ b/res-hdpi/images/loop21.png
Binary files differ
diff --git a/res-hdpi/images/loop22.png b/res-hdpi/images/loop22.png
new file mode 100644
index 0000000..bdee1ac
--- /dev/null
+++ b/res-hdpi/images/loop22.png
Binary files differ
diff --git a/res-hdpi/images/loop23.png b/res-hdpi/images/loop23.png
new file mode 100644
index 0000000..631c62d
--- /dev/null
+++ b/res-hdpi/images/loop23.png
Binary files differ
diff --git a/res-hdpi/images/loop24.png b/res-hdpi/images/loop24.png
new file mode 100644
index 0000000..081ba89
--- /dev/null
+++ b/res-hdpi/images/loop24.png
Binary files differ
diff --git a/res-hdpi/images/loop25.png b/res-hdpi/images/loop25.png
new file mode 100644
index 0000000..7511fc0
--- /dev/null
+++ b/res-hdpi/images/loop25.png
Binary files differ
diff --git a/res-hdpi/images/loop26.png b/res-hdpi/images/loop26.png
new file mode 100644
index 0000000..d9ae7d3
--- /dev/null
+++ b/res-hdpi/images/loop26.png
Binary files differ
diff --git a/res-hdpi/images/loop27.png b/res-hdpi/images/loop27.png
new file mode 100644
index 0000000..ca1d45e
--- /dev/null
+++ b/res-hdpi/images/loop27.png
Binary files differ
diff --git a/res-hdpi/images/loop28.png b/res-hdpi/images/loop28.png
new file mode 100644
index 0000000..4042974
--- /dev/null
+++ b/res-hdpi/images/loop28.png
Binary files differ
diff --git a/res-hdpi/images/loop29.png b/res-hdpi/images/loop29.png
new file mode 100644
index 0000000..506e9e4
--- /dev/null
+++ b/res-hdpi/images/loop29.png
Binary files differ
diff --git a/res-hdpi/images/loop30.png b/res-hdpi/images/loop30.png
new file mode 100644
index 0000000..4f98505
--- /dev/null
+++ b/res-hdpi/images/loop30.png
Binary files differ
diff --git a/res-hdpi/images/loop31.png b/res-hdpi/images/loop31.png
new file mode 100644
index 0000000..b259b47
--- /dev/null
+++ b/res-hdpi/images/loop31.png
Binary files differ
diff --git a/res-hdpi/images/loop32.png b/res-hdpi/images/loop32.png
new file mode 100644
index 0000000..3ddfab8
--- /dev/null
+++ b/res-hdpi/images/loop32.png
Binary files differ
diff --git a/res-hdpi/images/loop33.png b/res-hdpi/images/loop33.png
new file mode 100644
index 0000000..b61b64b
--- /dev/null
+++ b/res-hdpi/images/loop33.png
Binary files differ
diff --git a/res-hdpi/images/loop34.png b/res-hdpi/images/loop34.png
new file mode 100644
index 0000000..96e8392
--- /dev/null
+++ b/res-hdpi/images/loop34.png
Binary files differ
diff --git a/res-hdpi/images/loop35.png b/res-hdpi/images/loop35.png
new file mode 100644
index 0000000..a8bb7fc
--- /dev/null
+++ b/res-hdpi/images/loop35.png
Binary files differ
diff --git a/res-hdpi/images/loop36.png b/res-hdpi/images/loop36.png
new file mode 100644
index 0000000..5171a3b
--- /dev/null
+++ b/res-hdpi/images/loop36.png
Binary files differ
diff --git a/res-hdpi/images/loop37.png b/res-hdpi/images/loop37.png
new file mode 100644
index 0000000..b4ba0a6
--- /dev/null
+++ b/res-hdpi/images/loop37.png
Binary files differ
diff --git a/res-hdpi/images/loop38.png b/res-hdpi/images/loop38.png
new file mode 100644
index 0000000..bd248d8
--- /dev/null
+++ b/res-hdpi/images/loop38.png
Binary files differ
diff --git a/res-hdpi/images/loop39.png b/res-hdpi/images/loop39.png
new file mode 100644
index 0000000..40e2eee
--- /dev/null
+++ b/res-hdpi/images/loop39.png
Binary files differ
diff --git a/res-hdpi/images/loop40.png b/res-hdpi/images/loop40.png
new file mode 100644
index 0000000..4ffadc6
--- /dev/null
+++ b/res-hdpi/images/loop40.png
Binary files differ
diff --git a/res-hdpi/images/loop41.png b/res-hdpi/images/loop41.png
new file mode 100644
index 0000000..e0f107b
--- /dev/null
+++ b/res-hdpi/images/loop41.png
Binary files differ
diff --git a/res-hdpi/images/loop42.png b/res-hdpi/images/loop42.png
new file mode 100644
index 0000000..04b618a
--- /dev/null
+++ b/res-hdpi/images/loop42.png
Binary files differ
diff --git a/res-hdpi/images/loop43.png b/res-hdpi/images/loop43.png
new file mode 100644
index 0000000..e344cb9
--- /dev/null
+++ b/res-hdpi/images/loop43.png
Binary files differ
diff --git a/res-hdpi/images/loop44.png b/res-hdpi/images/loop44.png
new file mode 100644
index 0000000..85acfa0
--- /dev/null
+++ b/res-hdpi/images/loop44.png
Binary files differ
diff --git a/res-hdpi/images/loop45.png b/res-hdpi/images/loop45.png
new file mode 100644
index 0000000..d1f90b3
--- /dev/null
+++ b/res-hdpi/images/loop45.png
Binary files differ
diff --git a/res-hdpi/images/loop46.png b/res-hdpi/images/loop46.png
new file mode 100644
index 0000000..386a682
--- /dev/null
+++ b/res-hdpi/images/loop46.png
Binary files differ
diff --git a/res-hdpi/images/loop47.png b/res-hdpi/images/loop47.png
new file mode 100644
index 0000000..fa87591
--- /dev/null
+++ b/res-hdpi/images/loop47.png
Binary files differ
diff --git a/res-hdpi/images/loop48.png b/res-hdpi/images/loop48.png
new file mode 100644
index 0000000..fec1c9d
--- /dev/null
+++ b/res-hdpi/images/loop48.png
Binary files differ
diff --git a/res-hdpi/images/loop49.png b/res-hdpi/images/loop49.png
new file mode 100644
index 0000000..fbe504d
--- /dev/null
+++ b/res-hdpi/images/loop49.png
Binary files differ
diff --git a/res-hdpi/images/loop50.png b/res-hdpi/images/loop50.png
new file mode 100644
index 0000000..62ea720
--- /dev/null
+++ b/res-hdpi/images/loop50.png
Binary files differ
diff --git a/res-hdpi/images/loop51.png b/res-hdpi/images/loop51.png
new file mode 100644
index 0000000..6b1b5c1
--- /dev/null
+++ b/res-hdpi/images/loop51.png
Binary files differ
diff --git a/res-hdpi/images/loop52.png b/res-hdpi/images/loop52.png
new file mode 100644
index 0000000..48c2137
--- /dev/null
+++ b/res-hdpi/images/loop52.png
Binary files differ
diff --git a/res-hdpi/images/loop53.png b/res-hdpi/images/loop53.png
new file mode 100644
index 0000000..6809458
--- /dev/null
+++ b/res-hdpi/images/loop53.png
Binary files differ
diff --git a/res-hdpi/images/loop54.png b/res-hdpi/images/loop54.png
new file mode 100644
index 0000000..fb94ad8
--- /dev/null
+++ b/res-hdpi/images/loop54.png
Binary files differ
diff --git a/res-hdpi/images/loop55.png b/res-hdpi/images/loop55.png
new file mode 100644
index 0000000..c7f2092
--- /dev/null
+++ b/res-hdpi/images/loop55.png
Binary files differ
diff --git a/res-hdpi/images/loop56.png b/res-hdpi/images/loop56.png
new file mode 100644
index 0000000..aa376cc
--- /dev/null
+++ b/res-hdpi/images/loop56.png
Binary files differ
diff --git a/res-hdpi/images/loop57.png b/res-hdpi/images/loop57.png
new file mode 100644
index 0000000..b2bf5d8
--- /dev/null
+++ b/res-hdpi/images/loop57.png
Binary files differ
diff --git a/res-hdpi/images/loop58.png b/res-hdpi/images/loop58.png
new file mode 100644
index 0000000..acef933
--- /dev/null
+++ b/res-hdpi/images/loop58.png
Binary files differ
diff --git a/res-hdpi/images/loop59.png b/res-hdpi/images/loop59.png
new file mode 100644
index 0000000..f0d191e
--- /dev/null
+++ b/res-hdpi/images/loop59.png
Binary files differ
diff --git a/res-hdpi/images/loop60.png b/res-hdpi/images/loop60.png
new file mode 100644
index 0000000..d58edc6
--- /dev/null
+++ b/res-hdpi/images/loop60.png
Binary files differ
diff --git a/res-hdpi/images/loop61.png b/res-hdpi/images/loop61.png
new file mode 100644
index 0000000..d355a18
--- /dev/null
+++ b/res-hdpi/images/loop61.png
Binary files differ
diff --git a/res-hdpi/images/loop62.png b/res-hdpi/images/loop62.png
new file mode 100644
index 0000000..95fd66f
--- /dev/null
+++ b/res-hdpi/images/loop62.png
Binary files differ
diff --git a/res-hdpi/images/loop63.png b/res-hdpi/images/loop63.png
new file mode 100644
index 0000000..619bbf4
--- /dev/null
+++ b/res-hdpi/images/loop63.png
Binary files differ
diff --git a/res-hdpi/images/loop64.png b/res-hdpi/images/loop64.png
new file mode 100644
index 0000000..1867c8e
--- /dev/null
+++ b/res-hdpi/images/loop64.png
Binary files differ
diff --git a/res-hdpi/images/loop65.png b/res-hdpi/images/loop65.png
new file mode 100644
index 0000000..a0eee31
--- /dev/null
+++ b/res-hdpi/images/loop65.png
Binary files differ
diff --git a/res-hdpi/images/loop66.png b/res-hdpi/images/loop66.png
new file mode 100644
index 0000000..b6befd6
--- /dev/null
+++ b/res-hdpi/images/loop66.png
Binary files differ
diff --git a/res-hdpi/images/loop67.png b/res-hdpi/images/loop67.png
new file mode 100644
index 0000000..2576294
--- /dev/null
+++ b/res-hdpi/images/loop67.png
Binary files differ
diff --git a/res-hdpi/images/loop68.png b/res-hdpi/images/loop68.png
new file mode 100644
index 0000000..0bc718f
--- /dev/null
+++ b/res-hdpi/images/loop68.png
Binary files differ
diff --git a/res-hdpi/images/loop69.png b/res-hdpi/images/loop69.png
new file mode 100644
index 0000000..3678cea
--- /dev/null
+++ b/res-hdpi/images/loop69.png
Binary files differ
diff --git a/res-hdpi/images/loop70.png b/res-hdpi/images/loop70.png
new file mode 100644
index 0000000..03e69c4
--- /dev/null
+++ b/res-hdpi/images/loop70.png
Binary files differ
diff --git a/res-hdpi/images/loop71.png b/res-hdpi/images/loop71.png
new file mode 100644
index 0000000..62ba17e
--- /dev/null
+++ b/res-hdpi/images/loop71.png
Binary files differ
diff --git a/res-hdpi/images/loop72.png b/res-hdpi/images/loop72.png
new file mode 100644
index 0000000..c6e8fee
--- /dev/null
+++ b/res-hdpi/images/loop72.png
Binary files differ
diff --git a/res-hdpi/images/loop73.png b/res-hdpi/images/loop73.png
new file mode 100644
index 0000000..c12fb7d
--- /dev/null
+++ b/res-hdpi/images/loop73.png
Binary files differ
diff --git a/res-hdpi/images/loop74.png b/res-hdpi/images/loop74.png
new file mode 100644
index 0000000..30b8ff9
--- /dev/null
+++ b/res-hdpi/images/loop74.png
Binary files differ
diff --git a/res-hdpi/images/loop75.png b/res-hdpi/images/loop75.png
new file mode 100644
index 0000000..c9b4940
--- /dev/null
+++ b/res-hdpi/images/loop75.png
Binary files differ
diff --git a/res-hdpi/images/loop76.png b/res-hdpi/images/loop76.png
new file mode 100644
index 0000000..9e789a5
--- /dev/null
+++ b/res-hdpi/images/loop76.png
Binary files differ
diff --git a/res-hdpi/images/loop77.png b/res-hdpi/images/loop77.png
new file mode 100644
index 0000000..c235f53
--- /dev/null
+++ b/res-hdpi/images/loop77.png
Binary files differ
diff --git a/res-hdpi/images/loop78.png b/res-hdpi/images/loop78.png
new file mode 100644
index 0000000..11aaf36
--- /dev/null
+++ b/res-hdpi/images/loop78.png
Binary files differ
diff --git a/res-hdpi/images/loop79.png b/res-hdpi/images/loop79.png
new file mode 100644
index 0000000..cce9d8a
--- /dev/null
+++ b/res-hdpi/images/loop79.png
Binary files differ
diff --git a/res-hdpi/images/loop80.png b/res-hdpi/images/loop80.png
new file mode 100644
index 0000000..e92ba62
--- /dev/null
+++ b/res-hdpi/images/loop80.png
Binary files differ
diff --git a/res-hdpi/images/loop81.png b/res-hdpi/images/loop81.png
new file mode 100644
index 0000000..ae44a1c
--- /dev/null
+++ b/res-hdpi/images/loop81.png
Binary files differ
diff --git a/res-hdpi/images/loop82.png b/res-hdpi/images/loop82.png
new file mode 100644
index 0000000..646b5e7
--- /dev/null
+++ b/res-hdpi/images/loop82.png
Binary files differ
diff --git a/res-hdpi/images/loop83.png b/res-hdpi/images/loop83.png
new file mode 100644
index 0000000..37357b5
--- /dev/null
+++ b/res-hdpi/images/loop83.png
Binary files differ
diff --git a/res-hdpi/images/loop84.png b/res-hdpi/images/loop84.png
new file mode 100644
index 0000000..e52d037
--- /dev/null
+++ b/res-hdpi/images/loop84.png
Binary files differ
diff --git a/res-hdpi/images/loop85.png b/res-hdpi/images/loop85.png
new file mode 100644
index 0000000..73ecb61
--- /dev/null
+++ b/res-hdpi/images/loop85.png
Binary files differ
diff --git a/res-hdpi/images/loop86.png b/res-hdpi/images/loop86.png
new file mode 100644
index 0000000..9474ed5
--- /dev/null
+++ b/res-hdpi/images/loop86.png
Binary files differ
diff --git a/res-hdpi/images/loop87.png b/res-hdpi/images/loop87.png
new file mode 100644
index 0000000..af86252
--- /dev/null
+++ b/res-hdpi/images/loop87.png
Binary files differ
diff --git a/res-hdpi/images/loop88.png b/res-hdpi/images/loop88.png
new file mode 100644
index 0000000..0b6955b
--- /dev/null
+++ b/res-hdpi/images/loop88.png
Binary files differ
diff --git a/res-hdpi/images/loop89.png b/res-hdpi/images/loop89.png
new file mode 100644
index 0000000..e52e38d
--- /dev/null
+++ b/res-hdpi/images/loop89.png
Binary files differ
diff --git a/res-hdpi/images/loop90.png b/res-hdpi/images/loop90.png
new file mode 100644
index 0000000..c7f8084
--- /dev/null
+++ b/res-hdpi/images/loop90.png
Binary files differ
diff --git a/res-mdpi/images/icon_installing.png b/res-mdpi/images/icon_installing.png
deleted file mode 100644
index 0fcfbc2..0000000
--- a/res-mdpi/images/icon_installing.png
+++ /dev/null
Binary files differ
diff --git a/res-mdpi/images/loop00.png b/res-mdpi/images/loop00.png
new file mode 100644
index 0000000..20bebb0
--- /dev/null
+++ b/res-mdpi/images/loop00.png
Binary files differ
diff --git a/res-mdpi/images/loop01.png b/res-mdpi/images/loop01.png
new file mode 100644
index 0000000..f5eabdd
--- /dev/null
+++ b/res-mdpi/images/loop01.png
Binary files differ
diff --git a/res-mdpi/images/loop02.png b/res-mdpi/images/loop02.png
new file mode 100644
index 0000000..ae93a51
--- /dev/null
+++ b/res-mdpi/images/loop02.png
Binary files differ
diff --git a/res-mdpi/images/loop03.png b/res-mdpi/images/loop03.png
new file mode 100644
index 0000000..bda711b
--- /dev/null
+++ b/res-mdpi/images/loop03.png
Binary files differ
diff --git a/res-mdpi/images/loop04.png b/res-mdpi/images/loop04.png
new file mode 100644
index 0000000..8e55e96
--- /dev/null
+++ b/res-mdpi/images/loop04.png
Binary files differ
diff --git a/res-mdpi/images/loop05.png b/res-mdpi/images/loop05.png
new file mode 100644
index 0000000..69d2172
--- /dev/null
+++ b/res-mdpi/images/loop05.png
Binary files differ
diff --git a/res-mdpi/images/loop06.png b/res-mdpi/images/loop06.png
new file mode 100644
index 0000000..f876787
--- /dev/null
+++ b/res-mdpi/images/loop06.png
Binary files differ
diff --git a/res-mdpi/images/loop07.png b/res-mdpi/images/loop07.png
new file mode 100644
index 0000000..ee34a81
--- /dev/null
+++ b/res-mdpi/images/loop07.png
Binary files differ
diff --git a/res-mdpi/images/loop08.png b/res-mdpi/images/loop08.png
new file mode 100644
index 0000000..2d5c3eb
--- /dev/null
+++ b/res-mdpi/images/loop08.png
Binary files differ
diff --git a/res-mdpi/images/loop09.png b/res-mdpi/images/loop09.png
new file mode 100644
index 0000000..c83a736
--- /dev/null
+++ b/res-mdpi/images/loop09.png
Binary files differ
diff --git a/res-mdpi/images/loop10.png b/res-mdpi/images/loop10.png
new file mode 100644
index 0000000..6cd8d8c
--- /dev/null
+++ b/res-mdpi/images/loop10.png
Binary files differ
diff --git a/res-mdpi/images/loop11.png b/res-mdpi/images/loop11.png
new file mode 100644
index 0000000..c33dcb2
--- /dev/null
+++ b/res-mdpi/images/loop11.png
Binary files differ
diff --git a/res-mdpi/images/loop12.png b/res-mdpi/images/loop12.png
new file mode 100644
index 0000000..1f2b2f4
--- /dev/null
+++ b/res-mdpi/images/loop12.png
Binary files differ
diff --git a/res-mdpi/images/loop13.png b/res-mdpi/images/loop13.png
new file mode 100644
index 0000000..8a15029
--- /dev/null
+++ b/res-mdpi/images/loop13.png
Binary files differ
diff --git a/res-mdpi/images/loop14.png b/res-mdpi/images/loop14.png
new file mode 100644
index 0000000..3ab2fee
--- /dev/null
+++ b/res-mdpi/images/loop14.png
Binary files differ
diff --git a/res-mdpi/images/loop15.png b/res-mdpi/images/loop15.png
new file mode 100644
index 0000000..6af606f
--- /dev/null
+++ b/res-mdpi/images/loop15.png
Binary files differ
diff --git a/res-mdpi/images/loop16.png b/res-mdpi/images/loop16.png
new file mode 100644
index 0000000..5cb302e
--- /dev/null
+++ b/res-mdpi/images/loop16.png
Binary files differ
diff --git a/res-mdpi/images/loop17.png b/res-mdpi/images/loop17.png
new file mode 100644
index 0000000..cdceb06
--- /dev/null
+++ b/res-mdpi/images/loop17.png
Binary files differ
diff --git a/res-mdpi/images/loop18.png b/res-mdpi/images/loop18.png
new file mode 100644
index 0000000..27c37a8
--- /dev/null
+++ b/res-mdpi/images/loop18.png
Binary files differ
diff --git a/res-mdpi/images/loop19.png b/res-mdpi/images/loop19.png
new file mode 100644
index 0000000..92e6696
--- /dev/null
+++ b/res-mdpi/images/loop19.png
Binary files differ
diff --git a/res-mdpi/images/loop20.png b/res-mdpi/images/loop20.png
new file mode 100644
index 0000000..634a011
--- /dev/null
+++ b/res-mdpi/images/loop20.png
Binary files differ
diff --git a/res-mdpi/images/loop21.png b/res-mdpi/images/loop21.png
new file mode 100644
index 0000000..6dc6dcc
--- /dev/null
+++ b/res-mdpi/images/loop21.png
Binary files differ
diff --git a/res-mdpi/images/loop22.png b/res-mdpi/images/loop22.png
new file mode 100644
index 0000000..19b10a5
--- /dev/null
+++ b/res-mdpi/images/loop22.png
Binary files differ
diff --git a/res-mdpi/images/loop23.png b/res-mdpi/images/loop23.png
new file mode 100644
index 0000000..ab68fcd
--- /dev/null
+++ b/res-mdpi/images/loop23.png
Binary files differ
diff --git a/res-mdpi/images/loop24.png b/res-mdpi/images/loop24.png
new file mode 100644
index 0000000..74541f4
--- /dev/null
+++ b/res-mdpi/images/loop24.png
Binary files differ
diff --git a/res-mdpi/images/loop25.png b/res-mdpi/images/loop25.png
new file mode 100644
index 0000000..af54a7b
--- /dev/null
+++ b/res-mdpi/images/loop25.png
Binary files differ
diff --git a/res-mdpi/images/loop26.png b/res-mdpi/images/loop26.png
new file mode 100644
index 0000000..eaa826e
--- /dev/null
+++ b/res-mdpi/images/loop26.png
Binary files differ
diff --git a/res-mdpi/images/loop27.png b/res-mdpi/images/loop27.png
new file mode 100644
index 0000000..d5fd471
--- /dev/null
+++ b/res-mdpi/images/loop27.png
Binary files differ
diff --git a/res-mdpi/images/loop28.png b/res-mdpi/images/loop28.png
new file mode 100644
index 0000000..aeb9324
--- /dev/null
+++ b/res-mdpi/images/loop28.png
Binary files differ
diff --git a/res-mdpi/images/loop29.png b/res-mdpi/images/loop29.png
new file mode 100644
index 0000000..06886bc
--- /dev/null
+++ b/res-mdpi/images/loop29.png
Binary files differ
diff --git a/res-mdpi/images/loop30.png b/res-mdpi/images/loop30.png
new file mode 100644
index 0000000..c0f15ef
--- /dev/null
+++ b/res-mdpi/images/loop30.png
Binary files differ
diff --git a/res-mdpi/images/loop31.png b/res-mdpi/images/loop31.png
new file mode 100644
index 0000000..b166a27
--- /dev/null
+++ b/res-mdpi/images/loop31.png
Binary files differ
diff --git a/res-mdpi/images/loop32.png b/res-mdpi/images/loop32.png
new file mode 100644
index 0000000..ab5d116
--- /dev/null
+++ b/res-mdpi/images/loop32.png
Binary files differ
diff --git a/res-mdpi/images/loop33.png b/res-mdpi/images/loop33.png
new file mode 100644
index 0000000..df4f77f
--- /dev/null
+++ b/res-mdpi/images/loop33.png
Binary files differ
diff --git a/res-mdpi/images/loop34.png b/res-mdpi/images/loop34.png
new file mode 100644
index 0000000..c5663d0
--- /dev/null
+++ b/res-mdpi/images/loop34.png
Binary files differ
diff --git a/res-mdpi/images/loop35.png b/res-mdpi/images/loop35.png
new file mode 100644
index 0000000..7aed6c5
--- /dev/null
+++ b/res-mdpi/images/loop35.png
Binary files differ
diff --git a/res-mdpi/images/loop36.png b/res-mdpi/images/loop36.png
new file mode 100644
index 0000000..e42a59f
--- /dev/null
+++ b/res-mdpi/images/loop36.png
Binary files differ
diff --git a/res-mdpi/images/loop37.png b/res-mdpi/images/loop37.png
new file mode 100644
index 0000000..fb21da4
--- /dev/null
+++ b/res-mdpi/images/loop37.png
Binary files differ
diff --git a/res-mdpi/images/loop38.png b/res-mdpi/images/loop38.png
new file mode 100644
index 0000000..314e3f7
--- /dev/null
+++ b/res-mdpi/images/loop38.png
Binary files differ
diff --git a/res-mdpi/images/loop39.png b/res-mdpi/images/loop39.png
new file mode 100644
index 0000000..77f4362
--- /dev/null
+++ b/res-mdpi/images/loop39.png
Binary files differ
diff --git a/res-mdpi/images/loop40.png b/res-mdpi/images/loop40.png
new file mode 100644
index 0000000..c3bc8b1
--- /dev/null
+++ b/res-mdpi/images/loop40.png
Binary files differ
diff --git a/res-mdpi/images/loop41.png b/res-mdpi/images/loop41.png
new file mode 100644
index 0000000..33dcfe1
--- /dev/null
+++ b/res-mdpi/images/loop41.png
Binary files differ
diff --git a/res-mdpi/images/loop42.png b/res-mdpi/images/loop42.png
new file mode 100644
index 0000000..7cd3c10
--- /dev/null
+++ b/res-mdpi/images/loop42.png
Binary files differ
diff --git a/res-mdpi/images/loop43.png b/res-mdpi/images/loop43.png
new file mode 100644
index 0000000..15b1526
--- /dev/null
+++ b/res-mdpi/images/loop43.png
Binary files differ
diff --git a/res-mdpi/images/loop44.png b/res-mdpi/images/loop44.png
new file mode 100644
index 0000000..3c3825d
--- /dev/null
+++ b/res-mdpi/images/loop44.png
Binary files differ
diff --git a/res-mdpi/images/loop45.png b/res-mdpi/images/loop45.png
new file mode 100644
index 0000000..6d52f3c
--- /dev/null
+++ b/res-mdpi/images/loop45.png
Binary files differ
diff --git a/res-mdpi/images/loop46.png b/res-mdpi/images/loop46.png
new file mode 100644
index 0000000..8c7fe50
--- /dev/null
+++ b/res-mdpi/images/loop46.png
Binary files differ
diff --git a/res-mdpi/images/loop47.png b/res-mdpi/images/loop47.png
new file mode 100644
index 0000000..8ca16a4
--- /dev/null
+++ b/res-mdpi/images/loop47.png
Binary files differ
diff --git a/res-mdpi/images/loop48.png b/res-mdpi/images/loop48.png
new file mode 100644
index 0000000..62acae0
--- /dev/null
+++ b/res-mdpi/images/loop48.png
Binary files differ
diff --git a/res-mdpi/images/loop49.png b/res-mdpi/images/loop49.png
new file mode 100644
index 0000000..3c7a355
--- /dev/null
+++ b/res-mdpi/images/loop49.png
Binary files differ
diff --git a/res-mdpi/images/loop50.png b/res-mdpi/images/loop50.png
new file mode 100644
index 0000000..72add04
--- /dev/null
+++ b/res-mdpi/images/loop50.png
Binary files differ
diff --git a/res-mdpi/images/loop51.png b/res-mdpi/images/loop51.png
new file mode 100644
index 0000000..74108f1
--- /dev/null
+++ b/res-mdpi/images/loop51.png
Binary files differ
diff --git a/res-mdpi/images/loop52.png b/res-mdpi/images/loop52.png
new file mode 100644
index 0000000..bd12968
--- /dev/null
+++ b/res-mdpi/images/loop52.png
Binary files differ
diff --git a/res-mdpi/images/loop53.png b/res-mdpi/images/loop53.png
new file mode 100644
index 0000000..6af0c17
--- /dev/null
+++ b/res-mdpi/images/loop53.png
Binary files differ
diff --git a/res-mdpi/images/loop54.png b/res-mdpi/images/loop54.png
new file mode 100644
index 0000000..23f776c
--- /dev/null
+++ b/res-mdpi/images/loop54.png
Binary files differ
diff --git a/res-mdpi/images/loop55.png b/res-mdpi/images/loop55.png
new file mode 100644
index 0000000..d2d03c8
--- /dev/null
+++ b/res-mdpi/images/loop55.png
Binary files differ
diff --git a/res-mdpi/images/loop56.png b/res-mdpi/images/loop56.png
new file mode 100644
index 0000000..13e73ed
--- /dev/null
+++ b/res-mdpi/images/loop56.png
Binary files differ
diff --git a/res-mdpi/images/loop57.png b/res-mdpi/images/loop57.png
new file mode 100644
index 0000000..c2b81b6
--- /dev/null
+++ b/res-mdpi/images/loop57.png
Binary files differ
diff --git a/res-mdpi/images/loop58.png b/res-mdpi/images/loop58.png
new file mode 100644
index 0000000..d99cd74
--- /dev/null
+++ b/res-mdpi/images/loop58.png
Binary files differ
diff --git a/res-mdpi/images/loop59.png b/res-mdpi/images/loop59.png
new file mode 100644
index 0000000..8a36210
--- /dev/null
+++ b/res-mdpi/images/loop59.png
Binary files differ
diff --git a/res-mdpi/images/loop60.png b/res-mdpi/images/loop60.png
new file mode 100644
index 0000000..dc957fb
--- /dev/null
+++ b/res-mdpi/images/loop60.png
Binary files differ
diff --git a/res-mdpi/images/loop61.png b/res-mdpi/images/loop61.png
new file mode 100644
index 0000000..ea29c29
--- /dev/null
+++ b/res-mdpi/images/loop61.png
Binary files differ
diff --git a/res-mdpi/images/loop62.png b/res-mdpi/images/loop62.png
new file mode 100644
index 0000000..608a868
--- /dev/null
+++ b/res-mdpi/images/loop62.png
Binary files differ
diff --git a/res-mdpi/images/loop63.png b/res-mdpi/images/loop63.png
new file mode 100644
index 0000000..f65a3b7
--- /dev/null
+++ b/res-mdpi/images/loop63.png
Binary files differ
diff --git a/res-mdpi/images/loop64.png b/res-mdpi/images/loop64.png
new file mode 100644
index 0000000..5b27105
--- /dev/null
+++ b/res-mdpi/images/loop64.png
Binary files differ
diff --git a/res-mdpi/images/loop65.png b/res-mdpi/images/loop65.png
new file mode 100644
index 0000000..4ec41bf
--- /dev/null
+++ b/res-mdpi/images/loop65.png
Binary files differ
diff --git a/res-mdpi/images/loop66.png b/res-mdpi/images/loop66.png
new file mode 100644
index 0000000..b0845b5
--- /dev/null
+++ b/res-mdpi/images/loop66.png
Binary files differ
diff --git a/res-mdpi/images/loop67.png b/res-mdpi/images/loop67.png
new file mode 100644
index 0000000..30fae6e
--- /dev/null
+++ b/res-mdpi/images/loop67.png
Binary files differ
diff --git a/res-mdpi/images/loop68.png b/res-mdpi/images/loop68.png
new file mode 100644
index 0000000..fc90fca
--- /dev/null
+++ b/res-mdpi/images/loop68.png
Binary files differ
diff --git a/res-mdpi/images/loop69.png b/res-mdpi/images/loop69.png
new file mode 100644
index 0000000..da35643
--- /dev/null
+++ b/res-mdpi/images/loop69.png
Binary files differ
diff --git a/res-mdpi/images/loop70.png b/res-mdpi/images/loop70.png
new file mode 100644
index 0000000..baf5153
--- /dev/null
+++ b/res-mdpi/images/loop70.png
Binary files differ
diff --git a/res-mdpi/images/loop71.png b/res-mdpi/images/loop71.png
new file mode 100644
index 0000000..3b013c7
--- /dev/null
+++ b/res-mdpi/images/loop71.png
Binary files differ
diff --git a/res-mdpi/images/loop72.png b/res-mdpi/images/loop72.png
new file mode 100644
index 0000000..7f55992
--- /dev/null
+++ b/res-mdpi/images/loop72.png
Binary files differ
diff --git a/res-mdpi/images/loop73.png b/res-mdpi/images/loop73.png
new file mode 100644
index 0000000..85a4194
--- /dev/null
+++ b/res-mdpi/images/loop73.png
Binary files differ
diff --git a/res-mdpi/images/loop74.png b/res-mdpi/images/loop74.png
new file mode 100644
index 0000000..740f37e
--- /dev/null
+++ b/res-mdpi/images/loop74.png
Binary files differ
diff --git a/res-mdpi/images/loop75.png b/res-mdpi/images/loop75.png
new file mode 100644
index 0000000..cfb3d6f
--- /dev/null
+++ b/res-mdpi/images/loop75.png
Binary files differ
diff --git a/res-mdpi/images/loop76.png b/res-mdpi/images/loop76.png
new file mode 100644
index 0000000..15c841d
--- /dev/null
+++ b/res-mdpi/images/loop76.png
Binary files differ
diff --git a/res-mdpi/images/loop77.png b/res-mdpi/images/loop77.png
new file mode 100644
index 0000000..b277725
--- /dev/null
+++ b/res-mdpi/images/loop77.png
Binary files differ
diff --git a/res-mdpi/images/loop78.png b/res-mdpi/images/loop78.png
new file mode 100644
index 0000000..2744a9a
--- /dev/null
+++ b/res-mdpi/images/loop78.png
Binary files differ
diff --git a/res-mdpi/images/loop79.png b/res-mdpi/images/loop79.png
new file mode 100644
index 0000000..40f4908
--- /dev/null
+++ b/res-mdpi/images/loop79.png
Binary files differ
diff --git a/res-mdpi/images/loop80.png b/res-mdpi/images/loop80.png
new file mode 100644
index 0000000..cd969ec
--- /dev/null
+++ b/res-mdpi/images/loop80.png
Binary files differ
diff --git a/res-mdpi/images/loop81.png b/res-mdpi/images/loop81.png
new file mode 100644
index 0000000..e388ac0
--- /dev/null
+++ b/res-mdpi/images/loop81.png
Binary files differ
diff --git a/res-mdpi/images/loop82.png b/res-mdpi/images/loop82.png
new file mode 100644
index 0000000..134bebb
--- /dev/null
+++ b/res-mdpi/images/loop82.png
Binary files differ
diff --git a/res-mdpi/images/loop83.png b/res-mdpi/images/loop83.png
new file mode 100644
index 0000000..bdc71dd
--- /dev/null
+++ b/res-mdpi/images/loop83.png
Binary files differ
diff --git a/res-mdpi/images/loop84.png b/res-mdpi/images/loop84.png
new file mode 100644
index 0000000..e630af3
--- /dev/null
+++ b/res-mdpi/images/loop84.png
Binary files differ
diff --git a/res-mdpi/images/loop85.png b/res-mdpi/images/loop85.png
new file mode 100644
index 0000000..a936c98
--- /dev/null
+++ b/res-mdpi/images/loop85.png
Binary files differ
diff --git a/res-mdpi/images/loop86.png b/res-mdpi/images/loop86.png
new file mode 100644
index 0000000..53b3e51
--- /dev/null
+++ b/res-mdpi/images/loop86.png
Binary files differ
diff --git a/res-mdpi/images/loop87.png b/res-mdpi/images/loop87.png
new file mode 100644
index 0000000..9826193
--- /dev/null
+++ b/res-mdpi/images/loop87.png
Binary files differ
diff --git a/res-mdpi/images/loop88.png b/res-mdpi/images/loop88.png
new file mode 100644
index 0000000..00f682b
--- /dev/null
+++ b/res-mdpi/images/loop88.png
Binary files differ
diff --git a/res-mdpi/images/loop89.png b/res-mdpi/images/loop89.png
new file mode 100644
index 0000000..293b507
--- /dev/null
+++ b/res-mdpi/images/loop89.png
Binary files differ
diff --git a/res-mdpi/images/loop90.png b/res-mdpi/images/loop90.png
new file mode 100644
index 0000000..20bebb0
--- /dev/null
+++ b/res-mdpi/images/loop90.png
Binary files differ
diff --git a/res-xhdpi/images/icon_installing.png b/res-xhdpi/images/icon_installing.png
deleted file mode 100644
index 0fcfbc2..0000000
--- a/res-xhdpi/images/icon_installing.png
+++ /dev/null
Binary files differ
diff --git a/res-xhdpi/images/loop00.png b/res-xhdpi/images/loop00.png
new file mode 100644
index 0000000..45393ea
--- /dev/null
+++ b/res-xhdpi/images/loop00.png
Binary files differ
diff --git a/res-xhdpi/images/loop01.png b/res-xhdpi/images/loop01.png
new file mode 100644
index 0000000..d410fc0
--- /dev/null
+++ b/res-xhdpi/images/loop01.png
Binary files differ
diff --git a/res-xhdpi/images/loop02.png b/res-xhdpi/images/loop02.png
new file mode 100644
index 0000000..49c98a3
--- /dev/null
+++ b/res-xhdpi/images/loop02.png
Binary files differ
diff --git a/res-xhdpi/images/loop03.png b/res-xhdpi/images/loop03.png
new file mode 100644
index 0000000..b9ce0f5
--- /dev/null
+++ b/res-xhdpi/images/loop03.png
Binary files differ
diff --git a/res-xhdpi/images/loop04.png b/res-xhdpi/images/loop04.png
new file mode 100644
index 0000000..8391f60
--- /dev/null
+++ b/res-xhdpi/images/loop04.png
Binary files differ
diff --git a/res-xhdpi/images/loop05.png b/res-xhdpi/images/loop05.png
new file mode 100644
index 0000000..f76ad1b
--- /dev/null
+++ b/res-xhdpi/images/loop05.png
Binary files differ
diff --git a/res-xhdpi/images/loop06.png b/res-xhdpi/images/loop06.png
new file mode 100644
index 0000000..a53c567
--- /dev/null
+++ b/res-xhdpi/images/loop06.png
Binary files differ
diff --git a/res-xhdpi/images/loop07.png b/res-xhdpi/images/loop07.png
new file mode 100644
index 0000000..40b48db
--- /dev/null
+++ b/res-xhdpi/images/loop07.png
Binary files differ
diff --git a/res-xhdpi/images/loop08.png b/res-xhdpi/images/loop08.png
new file mode 100644
index 0000000..ea33f0c
--- /dev/null
+++ b/res-xhdpi/images/loop08.png
Binary files differ
diff --git a/res-xhdpi/images/loop09.png b/res-xhdpi/images/loop09.png
new file mode 100644
index 0000000..1c93a9c
--- /dev/null
+++ b/res-xhdpi/images/loop09.png
Binary files differ
diff --git a/res-xhdpi/images/loop10.png b/res-xhdpi/images/loop10.png
new file mode 100644
index 0000000..88309a4
--- /dev/null
+++ b/res-xhdpi/images/loop10.png
Binary files differ
diff --git a/res-xhdpi/images/loop11.png b/res-xhdpi/images/loop11.png
new file mode 100644
index 0000000..ae34ccf
--- /dev/null
+++ b/res-xhdpi/images/loop11.png
Binary files differ
diff --git a/res-xhdpi/images/loop12.png b/res-xhdpi/images/loop12.png
new file mode 100644
index 0000000..ee07cbc
--- /dev/null
+++ b/res-xhdpi/images/loop12.png
Binary files differ
diff --git a/res-xhdpi/images/loop13.png b/res-xhdpi/images/loop13.png
new file mode 100644
index 0000000..c1b7a78
--- /dev/null
+++ b/res-xhdpi/images/loop13.png
Binary files differ
diff --git a/res-xhdpi/images/loop14.png b/res-xhdpi/images/loop14.png
new file mode 100644
index 0000000..26ced74
--- /dev/null
+++ b/res-xhdpi/images/loop14.png
Binary files differ
diff --git a/res-xhdpi/images/loop15.png b/res-xhdpi/images/loop15.png
new file mode 100644
index 0000000..3cd3f3c
--- /dev/null
+++ b/res-xhdpi/images/loop15.png
Binary files differ
diff --git a/res-xhdpi/images/loop16.png b/res-xhdpi/images/loop16.png
new file mode 100644
index 0000000..67f6dd3
--- /dev/null
+++ b/res-xhdpi/images/loop16.png
Binary files differ
diff --git a/res-xhdpi/images/loop17.png b/res-xhdpi/images/loop17.png
new file mode 100644
index 0000000..c2ddbd0
--- /dev/null
+++ b/res-xhdpi/images/loop17.png
Binary files differ
diff --git a/res-xhdpi/images/loop18.png b/res-xhdpi/images/loop18.png
new file mode 100644
index 0000000..14590aa
--- /dev/null
+++ b/res-xhdpi/images/loop18.png
Binary files differ
diff --git a/res-xhdpi/images/loop19.png b/res-xhdpi/images/loop19.png
new file mode 100644
index 0000000..0c6c828
--- /dev/null
+++ b/res-xhdpi/images/loop19.png
Binary files differ
diff --git a/res-xhdpi/images/loop20.png b/res-xhdpi/images/loop20.png
new file mode 100644
index 0000000..ab0572c
--- /dev/null
+++ b/res-xhdpi/images/loop20.png
Binary files differ
diff --git a/res-xhdpi/images/loop21.png b/res-xhdpi/images/loop21.png
new file mode 100644
index 0000000..1ed54e5
--- /dev/null
+++ b/res-xhdpi/images/loop21.png
Binary files differ
diff --git a/res-xhdpi/images/loop22.png b/res-xhdpi/images/loop22.png
new file mode 100644
index 0000000..9e894c7
--- /dev/null
+++ b/res-xhdpi/images/loop22.png
Binary files differ
diff --git a/res-xhdpi/images/loop23.png b/res-xhdpi/images/loop23.png
new file mode 100644
index 0000000..87c44c5
--- /dev/null
+++ b/res-xhdpi/images/loop23.png
Binary files differ
diff --git a/res-xhdpi/images/loop24.png b/res-xhdpi/images/loop24.png
new file mode 100644
index 0000000..9dcebd9
--- /dev/null
+++ b/res-xhdpi/images/loop24.png
Binary files differ
diff --git a/res-xhdpi/images/loop25.png b/res-xhdpi/images/loop25.png
new file mode 100644
index 0000000..600c1e9
--- /dev/null
+++ b/res-xhdpi/images/loop25.png
Binary files differ
diff --git a/res-xhdpi/images/loop26.png b/res-xhdpi/images/loop26.png
new file mode 100644
index 0000000..575e808
--- /dev/null
+++ b/res-xhdpi/images/loop26.png
Binary files differ
diff --git a/res-xhdpi/images/loop27.png b/res-xhdpi/images/loop27.png
new file mode 100644
index 0000000..3c7908d
--- /dev/null
+++ b/res-xhdpi/images/loop27.png
Binary files differ
diff --git a/res-xhdpi/images/loop28.png b/res-xhdpi/images/loop28.png
new file mode 100644
index 0000000..31bc008
--- /dev/null
+++ b/res-xhdpi/images/loop28.png
Binary files differ
diff --git a/res-xhdpi/images/loop29.png b/res-xhdpi/images/loop29.png
new file mode 100644
index 0000000..7797b39
--- /dev/null
+++ b/res-xhdpi/images/loop29.png
Binary files differ
diff --git a/res-xhdpi/images/loop30.png b/res-xhdpi/images/loop30.png
new file mode 100644
index 0000000..234970c
--- /dev/null
+++ b/res-xhdpi/images/loop30.png
Binary files differ
diff --git a/res-xhdpi/images/loop31.png b/res-xhdpi/images/loop31.png
new file mode 100644
index 0000000..cd87e1b
--- /dev/null
+++ b/res-xhdpi/images/loop31.png
Binary files differ
diff --git a/res-xhdpi/images/loop32.png b/res-xhdpi/images/loop32.png
new file mode 100644
index 0000000..263dd0d
--- /dev/null
+++ b/res-xhdpi/images/loop32.png
Binary files differ
diff --git a/res-xhdpi/images/loop33.png b/res-xhdpi/images/loop33.png
new file mode 100644
index 0000000..62cbd5c
--- /dev/null
+++ b/res-xhdpi/images/loop33.png
Binary files differ
diff --git a/res-xhdpi/images/loop34.png b/res-xhdpi/images/loop34.png
new file mode 100644
index 0000000..7ab5856
--- /dev/null
+++ b/res-xhdpi/images/loop34.png
Binary files differ
diff --git a/res-xhdpi/images/loop35.png b/res-xhdpi/images/loop35.png
new file mode 100644
index 0000000..2b124e9
--- /dev/null
+++ b/res-xhdpi/images/loop35.png
Binary files differ
diff --git a/res-xhdpi/images/loop36.png b/res-xhdpi/images/loop36.png
new file mode 100644
index 0000000..b5b74be
--- /dev/null
+++ b/res-xhdpi/images/loop36.png
Binary files differ
diff --git a/res-xhdpi/images/loop37.png b/res-xhdpi/images/loop37.png
new file mode 100644
index 0000000..cad4c42
--- /dev/null
+++ b/res-xhdpi/images/loop37.png
Binary files differ
diff --git a/res-xhdpi/images/loop38.png b/res-xhdpi/images/loop38.png
new file mode 100644
index 0000000..4a83e18
--- /dev/null
+++ b/res-xhdpi/images/loop38.png
Binary files differ
diff --git a/res-xhdpi/images/loop39.png b/res-xhdpi/images/loop39.png
new file mode 100644
index 0000000..454a03e
--- /dev/null
+++ b/res-xhdpi/images/loop39.png
Binary files differ
diff --git a/res-xhdpi/images/loop40.png b/res-xhdpi/images/loop40.png
new file mode 100644
index 0000000..093f44b
--- /dev/null
+++ b/res-xhdpi/images/loop40.png
Binary files differ
diff --git a/res-xhdpi/images/loop41.png b/res-xhdpi/images/loop41.png
new file mode 100644
index 0000000..c173032
--- /dev/null
+++ b/res-xhdpi/images/loop41.png
Binary files differ
diff --git a/res-xhdpi/images/loop42.png b/res-xhdpi/images/loop42.png
new file mode 100644
index 0000000..4b4072a
--- /dev/null
+++ b/res-xhdpi/images/loop42.png
Binary files differ
diff --git a/res-xhdpi/images/loop43.png b/res-xhdpi/images/loop43.png
new file mode 100644
index 0000000..33a03d2
--- /dev/null
+++ b/res-xhdpi/images/loop43.png
Binary files differ
diff --git a/res-xhdpi/images/loop44.png b/res-xhdpi/images/loop44.png
new file mode 100644
index 0000000..1965294
--- /dev/null
+++ b/res-xhdpi/images/loop44.png
Binary files differ
diff --git a/res-xhdpi/images/loop45.png b/res-xhdpi/images/loop45.png
new file mode 100644
index 0000000..0bf16da
--- /dev/null
+++ b/res-xhdpi/images/loop45.png
Binary files differ
diff --git a/res-xhdpi/images/loop46.png b/res-xhdpi/images/loop46.png
new file mode 100644
index 0000000..81255bc
--- /dev/null
+++ b/res-xhdpi/images/loop46.png
Binary files differ
diff --git a/res-xhdpi/images/loop47.png b/res-xhdpi/images/loop47.png
new file mode 100644
index 0000000..e1e1710
--- /dev/null
+++ b/res-xhdpi/images/loop47.png
Binary files differ
diff --git a/res-xhdpi/images/loop48.png b/res-xhdpi/images/loop48.png
new file mode 100644
index 0000000..9d515ca
--- /dev/null
+++ b/res-xhdpi/images/loop48.png
Binary files differ
diff --git a/res-xhdpi/images/loop49.png b/res-xhdpi/images/loop49.png
new file mode 100644
index 0000000..6cb515c
--- /dev/null
+++ b/res-xhdpi/images/loop49.png
Binary files differ
diff --git a/res-xhdpi/images/loop50.png b/res-xhdpi/images/loop50.png
new file mode 100644
index 0000000..310ba72
--- /dev/null
+++ b/res-xhdpi/images/loop50.png
Binary files differ
diff --git a/res-xhdpi/images/loop51.png b/res-xhdpi/images/loop51.png
new file mode 100644
index 0000000..283f7eb
--- /dev/null
+++ b/res-xhdpi/images/loop51.png
Binary files differ
diff --git a/res-xhdpi/images/loop52.png b/res-xhdpi/images/loop52.png
new file mode 100644
index 0000000..141004f
--- /dev/null
+++ b/res-xhdpi/images/loop52.png
Binary files differ
diff --git a/res-xhdpi/images/loop53.png b/res-xhdpi/images/loop53.png
new file mode 100644
index 0000000..1b4649c
--- /dev/null
+++ b/res-xhdpi/images/loop53.png
Binary files differ
diff --git a/res-xhdpi/images/loop54.png b/res-xhdpi/images/loop54.png
new file mode 100644
index 0000000..3210b4a
--- /dev/null
+++ b/res-xhdpi/images/loop54.png
Binary files differ
diff --git a/res-xhdpi/images/loop55.png b/res-xhdpi/images/loop55.png
new file mode 100644
index 0000000..b1d9ea0
--- /dev/null
+++ b/res-xhdpi/images/loop55.png
Binary files differ
diff --git a/res-xhdpi/images/loop56.png b/res-xhdpi/images/loop56.png
new file mode 100644
index 0000000..1ae6126
--- /dev/null
+++ b/res-xhdpi/images/loop56.png
Binary files differ
diff --git a/res-xhdpi/images/loop57.png b/res-xhdpi/images/loop57.png
new file mode 100644
index 0000000..6317e88
--- /dev/null
+++ b/res-xhdpi/images/loop57.png
Binary files differ
diff --git a/res-xhdpi/images/loop58.png b/res-xhdpi/images/loop58.png
new file mode 100644
index 0000000..b275a31
--- /dev/null
+++ b/res-xhdpi/images/loop58.png
Binary files differ
diff --git a/res-xhdpi/images/loop59.png b/res-xhdpi/images/loop59.png
new file mode 100644
index 0000000..9bc3ba0
--- /dev/null
+++ b/res-xhdpi/images/loop59.png
Binary files differ
diff --git a/res-xhdpi/images/loop60.png b/res-xhdpi/images/loop60.png
new file mode 100644
index 0000000..b6a9e64
--- /dev/null
+++ b/res-xhdpi/images/loop60.png
Binary files differ
diff --git a/res-xhdpi/images/loop61.png b/res-xhdpi/images/loop61.png
new file mode 100644
index 0000000..fee9bee
--- /dev/null
+++ b/res-xhdpi/images/loop61.png
Binary files differ
diff --git a/res-xhdpi/images/loop62.png b/res-xhdpi/images/loop62.png
new file mode 100644
index 0000000..e153319
--- /dev/null
+++ b/res-xhdpi/images/loop62.png
Binary files differ
diff --git a/res-xhdpi/images/loop63.png b/res-xhdpi/images/loop63.png
new file mode 100644
index 0000000..a2d9efd
--- /dev/null
+++ b/res-xhdpi/images/loop63.png
Binary files differ
diff --git a/res-xhdpi/images/loop64.png b/res-xhdpi/images/loop64.png
new file mode 100644
index 0000000..6cfdc5a
--- /dev/null
+++ b/res-xhdpi/images/loop64.png
Binary files differ
diff --git a/res-xhdpi/images/loop65.png b/res-xhdpi/images/loop65.png
new file mode 100644
index 0000000..2806b1c
--- /dev/null
+++ b/res-xhdpi/images/loop65.png
Binary files differ
diff --git a/res-xhdpi/images/loop66.png b/res-xhdpi/images/loop66.png
new file mode 100644
index 0000000..fc51ee9
--- /dev/null
+++ b/res-xhdpi/images/loop66.png
Binary files differ
diff --git a/res-xhdpi/images/loop67.png b/res-xhdpi/images/loop67.png
new file mode 100644
index 0000000..d85ebf3
--- /dev/null
+++ b/res-xhdpi/images/loop67.png
Binary files differ
diff --git a/res-xhdpi/images/loop68.png b/res-xhdpi/images/loop68.png
new file mode 100644
index 0000000..8f5437a
--- /dev/null
+++ b/res-xhdpi/images/loop68.png
Binary files differ
diff --git a/res-xhdpi/images/loop69.png b/res-xhdpi/images/loop69.png
new file mode 100644
index 0000000..b426c53
--- /dev/null
+++ b/res-xhdpi/images/loop69.png
Binary files differ
diff --git a/res-xhdpi/images/loop70.png b/res-xhdpi/images/loop70.png
new file mode 100644
index 0000000..8541890
--- /dev/null
+++ b/res-xhdpi/images/loop70.png
Binary files differ
diff --git a/res-xhdpi/images/loop71.png b/res-xhdpi/images/loop71.png
new file mode 100644
index 0000000..2aa0fbf
--- /dev/null
+++ b/res-xhdpi/images/loop71.png
Binary files differ
diff --git a/res-xhdpi/images/loop72.png b/res-xhdpi/images/loop72.png
new file mode 100644
index 0000000..dfe61c9
--- /dev/null
+++ b/res-xhdpi/images/loop72.png
Binary files differ
diff --git a/res-xhdpi/images/loop73.png b/res-xhdpi/images/loop73.png
new file mode 100644
index 0000000..4b235b5
--- /dev/null
+++ b/res-xhdpi/images/loop73.png
Binary files differ
diff --git a/res-xhdpi/images/loop74.png b/res-xhdpi/images/loop74.png
new file mode 100644
index 0000000..31e4c0e
--- /dev/null
+++ b/res-xhdpi/images/loop74.png
Binary files differ
diff --git a/res-xhdpi/images/loop75.png b/res-xhdpi/images/loop75.png
new file mode 100644
index 0000000..68197f5
--- /dev/null
+++ b/res-xhdpi/images/loop75.png
Binary files differ
diff --git a/res-xhdpi/images/loop76.png b/res-xhdpi/images/loop76.png
new file mode 100644
index 0000000..cff8f4a
--- /dev/null
+++ b/res-xhdpi/images/loop76.png
Binary files differ
diff --git a/res-xhdpi/images/loop77.png b/res-xhdpi/images/loop77.png
new file mode 100644
index 0000000..3b38a39
--- /dev/null
+++ b/res-xhdpi/images/loop77.png
Binary files differ
diff --git a/res-xhdpi/images/loop78.png b/res-xhdpi/images/loop78.png
new file mode 100644
index 0000000..8d35624
--- /dev/null
+++ b/res-xhdpi/images/loop78.png
Binary files differ
diff --git a/res-xhdpi/images/loop79.png b/res-xhdpi/images/loop79.png
new file mode 100644
index 0000000..e8cdbe0
--- /dev/null
+++ b/res-xhdpi/images/loop79.png
Binary files differ
diff --git a/res-xhdpi/images/loop80.png b/res-xhdpi/images/loop80.png
new file mode 100644
index 0000000..5b26b48
--- /dev/null
+++ b/res-xhdpi/images/loop80.png
Binary files differ
diff --git a/res-xhdpi/images/loop81.png b/res-xhdpi/images/loop81.png
new file mode 100644
index 0000000..135b61e
--- /dev/null
+++ b/res-xhdpi/images/loop81.png
Binary files differ
diff --git a/res-xhdpi/images/loop82.png b/res-xhdpi/images/loop82.png
new file mode 100644
index 0000000..51da110
--- /dev/null
+++ b/res-xhdpi/images/loop82.png
Binary files differ
diff --git a/res-xhdpi/images/loop83.png b/res-xhdpi/images/loop83.png
new file mode 100644
index 0000000..84888a9
--- /dev/null
+++ b/res-xhdpi/images/loop83.png
Binary files differ
diff --git a/res-xhdpi/images/loop84.png b/res-xhdpi/images/loop84.png
new file mode 100644
index 0000000..0143344
--- /dev/null
+++ b/res-xhdpi/images/loop84.png
Binary files differ
diff --git a/res-xhdpi/images/loop85.png b/res-xhdpi/images/loop85.png
new file mode 100644
index 0000000..5836778
--- /dev/null
+++ b/res-xhdpi/images/loop85.png
Binary files differ
diff --git a/res-xhdpi/images/loop86.png b/res-xhdpi/images/loop86.png
new file mode 100644
index 0000000..00166a9
--- /dev/null
+++ b/res-xhdpi/images/loop86.png
Binary files differ
diff --git a/res-xhdpi/images/loop87.png b/res-xhdpi/images/loop87.png
new file mode 100644
index 0000000..b6f0089
--- /dev/null
+++ b/res-xhdpi/images/loop87.png
Binary files differ
diff --git a/res-xhdpi/images/loop88.png b/res-xhdpi/images/loop88.png
new file mode 100644
index 0000000..77b5b42
--- /dev/null
+++ b/res-xhdpi/images/loop88.png
Binary files differ
diff --git a/res-xhdpi/images/loop89.png b/res-xhdpi/images/loop89.png
new file mode 100644
index 0000000..4beb1f0
--- /dev/null
+++ b/res-xhdpi/images/loop89.png
Binary files differ
diff --git a/res-xhdpi/images/loop90.png b/res-xhdpi/images/loop90.png
new file mode 100644
index 0000000..45393ea
--- /dev/null
+++ b/res-xhdpi/images/loop90.png
Binary files differ
diff --git a/res-xxhdpi/images/icon_installing.png b/res-xxhdpi/images/icon_installing.png
deleted file mode 100644
index 0fcfbc2..0000000
--- a/res-xxhdpi/images/icon_installing.png
+++ /dev/null
Binary files differ
diff --git a/res-xxhdpi/images/loop00.png b/res-xxhdpi/images/loop00.png
new file mode 100644
index 0000000..9d61544
--- /dev/null
+++ b/res-xxhdpi/images/loop00.png
Binary files differ
diff --git a/res-xxhdpi/images/loop01.png b/res-xxhdpi/images/loop01.png
new file mode 100644
index 0000000..024bf6c
--- /dev/null
+++ b/res-xxhdpi/images/loop01.png
Binary files differ
diff --git a/res-xxhdpi/images/loop02.png b/res-xxhdpi/images/loop02.png
new file mode 100644
index 0000000..4f6cbf2
--- /dev/null
+++ b/res-xxhdpi/images/loop02.png
Binary files differ
diff --git a/res-xxhdpi/images/loop03.png b/res-xxhdpi/images/loop03.png
new file mode 100644
index 0000000..2f3287d
--- /dev/null
+++ b/res-xxhdpi/images/loop03.png
Binary files differ
diff --git a/res-xxhdpi/images/loop04.png b/res-xxhdpi/images/loop04.png
new file mode 100644
index 0000000..bc979cc
--- /dev/null
+++ b/res-xxhdpi/images/loop04.png
Binary files differ
diff --git a/res-xxhdpi/images/loop05.png b/res-xxhdpi/images/loop05.png
new file mode 100644
index 0000000..b1733db
--- /dev/null
+++ b/res-xxhdpi/images/loop05.png
Binary files differ
diff --git a/res-xxhdpi/images/loop06.png b/res-xxhdpi/images/loop06.png
new file mode 100644
index 0000000..46f6291
--- /dev/null
+++ b/res-xxhdpi/images/loop06.png
Binary files differ
diff --git a/res-xxhdpi/images/loop07.png b/res-xxhdpi/images/loop07.png
new file mode 100644
index 0000000..ead912a
--- /dev/null
+++ b/res-xxhdpi/images/loop07.png
Binary files differ
diff --git a/res-xxhdpi/images/loop08.png b/res-xxhdpi/images/loop08.png
new file mode 100644
index 0000000..d693b5b
--- /dev/null
+++ b/res-xxhdpi/images/loop08.png
Binary files differ
diff --git a/res-xxhdpi/images/loop09.png b/res-xxhdpi/images/loop09.png
new file mode 100644
index 0000000..06c7034
--- /dev/null
+++ b/res-xxhdpi/images/loop09.png
Binary files differ
diff --git a/res-xxhdpi/images/loop10.png b/res-xxhdpi/images/loop10.png
new file mode 100644
index 0000000..0875b91
--- /dev/null
+++ b/res-xxhdpi/images/loop10.png
Binary files differ
diff --git a/res-xxhdpi/images/loop11.png b/res-xxhdpi/images/loop11.png
new file mode 100644
index 0000000..1b0f18e
--- /dev/null
+++ b/res-xxhdpi/images/loop11.png
Binary files differ
diff --git a/res-xxhdpi/images/loop12.png b/res-xxhdpi/images/loop12.png
new file mode 100644
index 0000000..540d292
--- /dev/null
+++ b/res-xxhdpi/images/loop12.png
Binary files differ
diff --git a/res-xxhdpi/images/loop13.png b/res-xxhdpi/images/loop13.png
new file mode 100644
index 0000000..5a85eff
--- /dev/null
+++ b/res-xxhdpi/images/loop13.png
Binary files differ
diff --git a/res-xxhdpi/images/loop14.png b/res-xxhdpi/images/loop14.png
new file mode 100644
index 0000000..e94ea24
--- /dev/null
+++ b/res-xxhdpi/images/loop14.png
Binary files differ
diff --git a/res-xxhdpi/images/loop15.png b/res-xxhdpi/images/loop15.png
new file mode 100644
index 0000000..c1a78f5
--- /dev/null
+++ b/res-xxhdpi/images/loop15.png
Binary files differ
diff --git a/res-xxhdpi/images/loop16.png b/res-xxhdpi/images/loop16.png
new file mode 100644
index 0000000..7cb3e9a
--- /dev/null
+++ b/res-xxhdpi/images/loop16.png
Binary files differ
diff --git a/res-xxhdpi/images/loop17.png b/res-xxhdpi/images/loop17.png
new file mode 100644
index 0000000..1ad8497
--- /dev/null
+++ b/res-xxhdpi/images/loop17.png
Binary files differ
diff --git a/res-xxhdpi/images/loop18.png b/res-xxhdpi/images/loop18.png
new file mode 100644
index 0000000..fb82ebe
--- /dev/null
+++ b/res-xxhdpi/images/loop18.png
Binary files differ
diff --git a/res-xxhdpi/images/loop19.png b/res-xxhdpi/images/loop19.png
new file mode 100644
index 0000000..217d34b
--- /dev/null
+++ b/res-xxhdpi/images/loop19.png
Binary files differ
diff --git a/res-xxhdpi/images/loop20.png b/res-xxhdpi/images/loop20.png
new file mode 100644
index 0000000..f1cfe78
--- /dev/null
+++ b/res-xxhdpi/images/loop20.png
Binary files differ
diff --git a/res-xxhdpi/images/loop21.png b/res-xxhdpi/images/loop21.png
new file mode 100644
index 0000000..184c86b
--- /dev/null
+++ b/res-xxhdpi/images/loop21.png
Binary files differ
diff --git a/res-xxhdpi/images/loop22.png b/res-xxhdpi/images/loop22.png
new file mode 100644
index 0000000..68e3b2a
--- /dev/null
+++ b/res-xxhdpi/images/loop22.png
Binary files differ
diff --git a/res-xxhdpi/images/loop23.png b/res-xxhdpi/images/loop23.png
new file mode 100644
index 0000000..af18831
--- /dev/null
+++ b/res-xxhdpi/images/loop23.png
Binary files differ
diff --git a/res-xxhdpi/images/loop24.png b/res-xxhdpi/images/loop24.png
new file mode 100644
index 0000000..dd7c4a5
--- /dev/null
+++ b/res-xxhdpi/images/loop24.png
Binary files differ
diff --git a/res-xxhdpi/images/loop25.png b/res-xxhdpi/images/loop25.png
new file mode 100644
index 0000000..c58c08d
--- /dev/null
+++ b/res-xxhdpi/images/loop25.png
Binary files differ
diff --git a/res-xxhdpi/images/loop26.png b/res-xxhdpi/images/loop26.png
new file mode 100644
index 0000000..4409e55
--- /dev/null
+++ b/res-xxhdpi/images/loop26.png
Binary files differ
diff --git a/res-xxhdpi/images/loop27.png b/res-xxhdpi/images/loop27.png
new file mode 100644
index 0000000..e96e1fd
--- /dev/null
+++ b/res-xxhdpi/images/loop27.png
Binary files differ
diff --git a/res-xxhdpi/images/loop28.png b/res-xxhdpi/images/loop28.png
new file mode 100644
index 0000000..d36ffa9
--- /dev/null
+++ b/res-xxhdpi/images/loop28.png
Binary files differ
diff --git a/res-xxhdpi/images/loop29.png b/res-xxhdpi/images/loop29.png
new file mode 100644
index 0000000..936a570
--- /dev/null
+++ b/res-xxhdpi/images/loop29.png
Binary files differ
diff --git a/res-xxhdpi/images/loop30.png b/res-xxhdpi/images/loop30.png
new file mode 100644
index 0000000..b5c5e04
--- /dev/null
+++ b/res-xxhdpi/images/loop30.png
Binary files differ
diff --git a/res-xxhdpi/images/loop31.png b/res-xxhdpi/images/loop31.png
new file mode 100644
index 0000000..1e2aa8b
--- /dev/null
+++ b/res-xxhdpi/images/loop31.png
Binary files differ
diff --git a/res-xxhdpi/images/loop32.png b/res-xxhdpi/images/loop32.png
new file mode 100644
index 0000000..638ec8b
--- /dev/null
+++ b/res-xxhdpi/images/loop32.png
Binary files differ
diff --git a/res-xxhdpi/images/loop33.png b/res-xxhdpi/images/loop33.png
new file mode 100644
index 0000000..cb62a36
--- /dev/null
+++ b/res-xxhdpi/images/loop33.png
Binary files differ
diff --git a/res-xxhdpi/images/loop34.png b/res-xxhdpi/images/loop34.png
new file mode 100644
index 0000000..ac877b8
--- /dev/null
+++ b/res-xxhdpi/images/loop34.png
Binary files differ
diff --git a/res-xxhdpi/images/loop35.png b/res-xxhdpi/images/loop35.png
new file mode 100644
index 0000000..567cbf1
--- /dev/null
+++ b/res-xxhdpi/images/loop35.png
Binary files differ
diff --git a/res-xxhdpi/images/loop36.png b/res-xxhdpi/images/loop36.png
new file mode 100644
index 0000000..b1c6220
--- /dev/null
+++ b/res-xxhdpi/images/loop36.png
Binary files differ
diff --git a/res-xxhdpi/images/loop37.png b/res-xxhdpi/images/loop37.png
new file mode 100644
index 0000000..ad40b75
--- /dev/null
+++ b/res-xxhdpi/images/loop37.png
Binary files differ
diff --git a/res-xxhdpi/images/loop38.png b/res-xxhdpi/images/loop38.png
new file mode 100644
index 0000000..87be4ef
--- /dev/null
+++ b/res-xxhdpi/images/loop38.png
Binary files differ
diff --git a/res-xxhdpi/images/loop39.png b/res-xxhdpi/images/loop39.png
new file mode 100644
index 0000000..fecaa1f
--- /dev/null
+++ b/res-xxhdpi/images/loop39.png
Binary files differ
diff --git a/res-xxhdpi/images/loop40.png b/res-xxhdpi/images/loop40.png
new file mode 100644
index 0000000..849caaa
--- /dev/null
+++ b/res-xxhdpi/images/loop40.png
Binary files differ
diff --git a/res-xxhdpi/images/loop41.png b/res-xxhdpi/images/loop41.png
new file mode 100644
index 0000000..9c0b81f
--- /dev/null
+++ b/res-xxhdpi/images/loop41.png
Binary files differ
diff --git a/res-xxhdpi/images/loop42.png b/res-xxhdpi/images/loop42.png
new file mode 100644
index 0000000..9c86573
--- /dev/null
+++ b/res-xxhdpi/images/loop42.png
Binary files differ
diff --git a/res-xxhdpi/images/loop43.png b/res-xxhdpi/images/loop43.png
new file mode 100644
index 0000000..1a5f888
--- /dev/null
+++ b/res-xxhdpi/images/loop43.png
Binary files differ
diff --git a/res-xxhdpi/images/loop44.png b/res-xxhdpi/images/loop44.png
new file mode 100644
index 0000000..2b4a449
--- /dev/null
+++ b/res-xxhdpi/images/loop44.png
Binary files differ
diff --git a/res-xxhdpi/images/loop45.png b/res-xxhdpi/images/loop45.png
new file mode 100644
index 0000000..11cc31c
--- /dev/null
+++ b/res-xxhdpi/images/loop45.png
Binary files differ
diff --git a/res-xxhdpi/images/loop46.png b/res-xxhdpi/images/loop46.png
new file mode 100644
index 0000000..95f3f99
--- /dev/null
+++ b/res-xxhdpi/images/loop46.png
Binary files differ
diff --git a/res-xxhdpi/images/loop47.png b/res-xxhdpi/images/loop47.png
new file mode 100644
index 0000000..ed99115
--- /dev/null
+++ b/res-xxhdpi/images/loop47.png
Binary files differ
diff --git a/res-xxhdpi/images/loop48.png b/res-xxhdpi/images/loop48.png
new file mode 100644
index 0000000..e39761c
--- /dev/null
+++ b/res-xxhdpi/images/loop48.png
Binary files differ
diff --git a/res-xxhdpi/images/loop49.png b/res-xxhdpi/images/loop49.png
new file mode 100644
index 0000000..65ec560
--- /dev/null
+++ b/res-xxhdpi/images/loop49.png
Binary files differ
diff --git a/res-xxhdpi/images/loop50.png b/res-xxhdpi/images/loop50.png
new file mode 100644
index 0000000..82631d9
--- /dev/null
+++ b/res-xxhdpi/images/loop50.png
Binary files differ
diff --git a/res-xxhdpi/images/loop51.png b/res-xxhdpi/images/loop51.png
new file mode 100644
index 0000000..eb3910c
--- /dev/null
+++ b/res-xxhdpi/images/loop51.png
Binary files differ
diff --git a/res-xxhdpi/images/loop52.png b/res-xxhdpi/images/loop52.png
new file mode 100644
index 0000000..64ec1ad
--- /dev/null
+++ b/res-xxhdpi/images/loop52.png
Binary files differ
diff --git a/res-xxhdpi/images/loop53.png b/res-xxhdpi/images/loop53.png
new file mode 100644
index 0000000..e71c971
--- /dev/null
+++ b/res-xxhdpi/images/loop53.png
Binary files differ
diff --git a/res-xxhdpi/images/loop54.png b/res-xxhdpi/images/loop54.png
new file mode 100644
index 0000000..877e152
--- /dev/null
+++ b/res-xxhdpi/images/loop54.png
Binary files differ
diff --git a/res-xxhdpi/images/loop55.png b/res-xxhdpi/images/loop55.png
new file mode 100644
index 0000000..0a8f8f0
--- /dev/null
+++ b/res-xxhdpi/images/loop55.png
Binary files differ
diff --git a/res-xxhdpi/images/loop56.png b/res-xxhdpi/images/loop56.png
new file mode 100644
index 0000000..ed9eff9
--- /dev/null
+++ b/res-xxhdpi/images/loop56.png
Binary files differ
diff --git a/res-xxhdpi/images/loop57.png b/res-xxhdpi/images/loop57.png
new file mode 100644
index 0000000..9afb745
--- /dev/null
+++ b/res-xxhdpi/images/loop57.png
Binary files differ
diff --git a/res-xxhdpi/images/loop58.png b/res-xxhdpi/images/loop58.png
new file mode 100644
index 0000000..775514e
--- /dev/null
+++ b/res-xxhdpi/images/loop58.png
Binary files differ
diff --git a/res-xxhdpi/images/loop59.png b/res-xxhdpi/images/loop59.png
new file mode 100644
index 0000000..b22a3a7
--- /dev/null
+++ b/res-xxhdpi/images/loop59.png
Binary files differ
diff --git a/res-xxhdpi/images/loop60.png b/res-xxhdpi/images/loop60.png
new file mode 100644
index 0000000..94905ca
--- /dev/null
+++ b/res-xxhdpi/images/loop60.png
Binary files differ
diff --git a/res-xxhdpi/images/loop61.png b/res-xxhdpi/images/loop61.png
new file mode 100644
index 0000000..bb9670c
--- /dev/null
+++ b/res-xxhdpi/images/loop61.png
Binary files differ
diff --git a/res-xxhdpi/images/loop62.png b/res-xxhdpi/images/loop62.png
new file mode 100644
index 0000000..1acf5ac
--- /dev/null
+++ b/res-xxhdpi/images/loop62.png
Binary files differ
diff --git a/res-xxhdpi/images/loop63.png b/res-xxhdpi/images/loop63.png
new file mode 100644
index 0000000..03f5620
--- /dev/null
+++ b/res-xxhdpi/images/loop63.png
Binary files differ
diff --git a/res-xxhdpi/images/loop64.png b/res-xxhdpi/images/loop64.png
new file mode 100644
index 0000000..7a5ce18
--- /dev/null
+++ b/res-xxhdpi/images/loop64.png
Binary files differ
diff --git a/res-xxhdpi/images/loop65.png b/res-xxhdpi/images/loop65.png
new file mode 100644
index 0000000..022b646
--- /dev/null
+++ b/res-xxhdpi/images/loop65.png
Binary files differ
diff --git a/res-xxhdpi/images/loop66.png b/res-xxhdpi/images/loop66.png
new file mode 100644
index 0000000..9fd3264
--- /dev/null
+++ b/res-xxhdpi/images/loop66.png
Binary files differ
diff --git a/res-xxhdpi/images/loop67.png b/res-xxhdpi/images/loop67.png
new file mode 100644
index 0000000..b05e20e
--- /dev/null
+++ b/res-xxhdpi/images/loop67.png
Binary files differ
diff --git a/res-xxhdpi/images/loop68.png b/res-xxhdpi/images/loop68.png
new file mode 100644
index 0000000..66556f9
--- /dev/null
+++ b/res-xxhdpi/images/loop68.png
Binary files differ
diff --git a/res-xxhdpi/images/loop69.png b/res-xxhdpi/images/loop69.png
new file mode 100644
index 0000000..34150c3
--- /dev/null
+++ b/res-xxhdpi/images/loop69.png
Binary files differ
diff --git a/res-xxhdpi/images/loop70.png b/res-xxhdpi/images/loop70.png
new file mode 100644
index 0000000..007f595
--- /dev/null
+++ b/res-xxhdpi/images/loop70.png
Binary files differ
diff --git a/res-xxhdpi/images/loop71.png b/res-xxhdpi/images/loop71.png
new file mode 100644
index 0000000..6db5c64
--- /dev/null
+++ b/res-xxhdpi/images/loop71.png
Binary files differ
diff --git a/res-xxhdpi/images/loop72.png b/res-xxhdpi/images/loop72.png
new file mode 100644
index 0000000..6e9d8e8
--- /dev/null
+++ b/res-xxhdpi/images/loop72.png
Binary files differ
diff --git a/res-xxhdpi/images/loop73.png b/res-xxhdpi/images/loop73.png
new file mode 100644
index 0000000..90c87d3
--- /dev/null
+++ b/res-xxhdpi/images/loop73.png
Binary files differ
diff --git a/res-xxhdpi/images/loop74.png b/res-xxhdpi/images/loop74.png
new file mode 100644
index 0000000..c0fe8dd
--- /dev/null
+++ b/res-xxhdpi/images/loop74.png
Binary files differ
diff --git a/res-xxhdpi/images/loop75.png b/res-xxhdpi/images/loop75.png
new file mode 100644
index 0000000..1853558
--- /dev/null
+++ b/res-xxhdpi/images/loop75.png
Binary files differ
diff --git a/res-xxhdpi/images/loop76.png b/res-xxhdpi/images/loop76.png
new file mode 100644
index 0000000..911ffea
--- /dev/null
+++ b/res-xxhdpi/images/loop76.png
Binary files differ
diff --git a/res-xxhdpi/images/loop77.png b/res-xxhdpi/images/loop77.png
new file mode 100644
index 0000000..87861a2
--- /dev/null
+++ b/res-xxhdpi/images/loop77.png
Binary files differ
diff --git a/res-xxhdpi/images/loop78.png b/res-xxhdpi/images/loop78.png
new file mode 100644
index 0000000..4b61b52
--- /dev/null
+++ b/res-xxhdpi/images/loop78.png
Binary files differ
diff --git a/res-xxhdpi/images/loop79.png b/res-xxhdpi/images/loop79.png
new file mode 100644
index 0000000..dea4bcf
--- /dev/null
+++ b/res-xxhdpi/images/loop79.png
Binary files differ
diff --git a/res-xxhdpi/images/loop80.png b/res-xxhdpi/images/loop80.png
new file mode 100644
index 0000000..dab06f3
--- /dev/null
+++ b/res-xxhdpi/images/loop80.png
Binary files differ
diff --git a/res-xxhdpi/images/loop81.png b/res-xxhdpi/images/loop81.png
new file mode 100644
index 0000000..4d74671
--- /dev/null
+++ b/res-xxhdpi/images/loop81.png
Binary files differ
diff --git a/res-xxhdpi/images/loop82.png b/res-xxhdpi/images/loop82.png
new file mode 100644
index 0000000..7124c88
--- /dev/null
+++ b/res-xxhdpi/images/loop82.png
Binary files differ
diff --git a/res-xxhdpi/images/loop83.png b/res-xxhdpi/images/loop83.png
new file mode 100644
index 0000000..c8cc938
--- /dev/null
+++ b/res-xxhdpi/images/loop83.png
Binary files differ
diff --git a/res-xxhdpi/images/loop84.png b/res-xxhdpi/images/loop84.png
new file mode 100644
index 0000000..dbfdaeb
--- /dev/null
+++ b/res-xxhdpi/images/loop84.png
Binary files differ
diff --git a/res-xxhdpi/images/loop85.png b/res-xxhdpi/images/loop85.png
new file mode 100644
index 0000000..2110980
--- /dev/null
+++ b/res-xxhdpi/images/loop85.png
Binary files differ
diff --git a/res-xxhdpi/images/loop86.png b/res-xxhdpi/images/loop86.png
new file mode 100644
index 0000000..c402cec
--- /dev/null
+++ b/res-xxhdpi/images/loop86.png
Binary files differ
diff --git a/res-xxhdpi/images/loop87.png b/res-xxhdpi/images/loop87.png
new file mode 100644
index 0000000..0d7ff31
--- /dev/null
+++ b/res-xxhdpi/images/loop87.png
Binary files differ
diff --git a/res-xxhdpi/images/loop88.png b/res-xxhdpi/images/loop88.png
new file mode 100644
index 0000000..754537d
--- /dev/null
+++ b/res-xxhdpi/images/loop88.png
Binary files differ
diff --git a/res-xxhdpi/images/loop89.png b/res-xxhdpi/images/loop89.png
new file mode 100644
index 0000000..68d4d60
--- /dev/null
+++ b/res-xxhdpi/images/loop89.png
Binary files differ
diff --git a/res-xxhdpi/images/loop90.png b/res-xxhdpi/images/loop90.png
new file mode 100644
index 0000000..9d61544
--- /dev/null
+++ b/res-xxhdpi/images/loop90.png
Binary files differ
diff --git a/res-xxxhdpi/images/icon_installing.png b/res-xxxhdpi/images/icon_installing.png
deleted file mode 100644
index 0fcfbc2..0000000
--- a/res-xxxhdpi/images/icon_installing.png
+++ /dev/null
Binary files differ
diff --git a/res-xxxhdpi/images/loop00.png b/res-xxxhdpi/images/loop00.png
new file mode 100644
index 0000000..76351c5
--- /dev/null
+++ b/res-xxxhdpi/images/loop00.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop01.png b/res-xxxhdpi/images/loop01.png
new file mode 100644
index 0000000..acdefc0
--- /dev/null
+++ b/res-xxxhdpi/images/loop01.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop02.png b/res-xxxhdpi/images/loop02.png
new file mode 100644
index 0000000..3fcb5e5
--- /dev/null
+++ b/res-xxxhdpi/images/loop02.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop03.png b/res-xxxhdpi/images/loop03.png
new file mode 100644
index 0000000..47497a4
--- /dev/null
+++ b/res-xxxhdpi/images/loop03.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop04.png b/res-xxxhdpi/images/loop04.png
new file mode 100644
index 0000000..1867381
--- /dev/null
+++ b/res-xxxhdpi/images/loop04.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop05.png b/res-xxxhdpi/images/loop05.png
new file mode 100644
index 0000000..8b7574c
--- /dev/null
+++ b/res-xxxhdpi/images/loop05.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop06.png b/res-xxxhdpi/images/loop06.png
new file mode 100644
index 0000000..e3c0a7d
--- /dev/null
+++ b/res-xxxhdpi/images/loop06.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop07.png b/res-xxxhdpi/images/loop07.png
new file mode 100644
index 0000000..d783ca7
--- /dev/null
+++ b/res-xxxhdpi/images/loop07.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop08.png b/res-xxxhdpi/images/loop08.png
new file mode 100644
index 0000000..eefcb3f
--- /dev/null
+++ b/res-xxxhdpi/images/loop08.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop09.png b/res-xxxhdpi/images/loop09.png
new file mode 100644
index 0000000..0f82c26
--- /dev/null
+++ b/res-xxxhdpi/images/loop09.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop10.png b/res-xxxhdpi/images/loop10.png
new file mode 100644
index 0000000..bc86246
--- /dev/null
+++ b/res-xxxhdpi/images/loop10.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop11.png b/res-xxxhdpi/images/loop11.png
new file mode 100644
index 0000000..7bd1087
--- /dev/null
+++ b/res-xxxhdpi/images/loop11.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop12.png b/res-xxxhdpi/images/loop12.png
new file mode 100644
index 0000000..b9dd44e
--- /dev/null
+++ b/res-xxxhdpi/images/loop12.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop13.png b/res-xxxhdpi/images/loop13.png
new file mode 100644
index 0000000..76c0d46
--- /dev/null
+++ b/res-xxxhdpi/images/loop13.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop14.png b/res-xxxhdpi/images/loop14.png
new file mode 100644
index 0000000..03ff4bd
--- /dev/null
+++ b/res-xxxhdpi/images/loop14.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop15.png b/res-xxxhdpi/images/loop15.png
new file mode 100644
index 0000000..b33cc28
--- /dev/null
+++ b/res-xxxhdpi/images/loop15.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop16.png b/res-xxxhdpi/images/loop16.png
new file mode 100644
index 0000000..cef8302
--- /dev/null
+++ b/res-xxxhdpi/images/loop16.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop17.png b/res-xxxhdpi/images/loop17.png
new file mode 100644
index 0000000..b1d6010
--- /dev/null
+++ b/res-xxxhdpi/images/loop17.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop18.png b/res-xxxhdpi/images/loop18.png
new file mode 100644
index 0000000..2df58f0
--- /dev/null
+++ b/res-xxxhdpi/images/loop18.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop19.png b/res-xxxhdpi/images/loop19.png
new file mode 100644
index 0000000..0249bff
--- /dev/null
+++ b/res-xxxhdpi/images/loop19.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop20.png b/res-xxxhdpi/images/loop20.png
new file mode 100644
index 0000000..5968bbb
--- /dev/null
+++ b/res-xxxhdpi/images/loop20.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop21.png b/res-xxxhdpi/images/loop21.png
new file mode 100644
index 0000000..76758e3
--- /dev/null
+++ b/res-xxxhdpi/images/loop21.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop22.png b/res-xxxhdpi/images/loop22.png
new file mode 100644
index 0000000..7ab40f9
--- /dev/null
+++ b/res-xxxhdpi/images/loop22.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop23.png b/res-xxxhdpi/images/loop23.png
new file mode 100644
index 0000000..830569f
--- /dev/null
+++ b/res-xxxhdpi/images/loop23.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop24.png b/res-xxxhdpi/images/loop24.png
new file mode 100644
index 0000000..4b8f77f
--- /dev/null
+++ b/res-xxxhdpi/images/loop24.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop25.png b/res-xxxhdpi/images/loop25.png
new file mode 100644
index 0000000..83df09e
--- /dev/null
+++ b/res-xxxhdpi/images/loop25.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop26.png b/res-xxxhdpi/images/loop26.png
new file mode 100644
index 0000000..4df09dc
--- /dev/null
+++ b/res-xxxhdpi/images/loop26.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop27.png b/res-xxxhdpi/images/loop27.png
new file mode 100644
index 0000000..0b211fe
--- /dev/null
+++ b/res-xxxhdpi/images/loop27.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop28.png b/res-xxxhdpi/images/loop28.png
new file mode 100644
index 0000000..b40985b
--- /dev/null
+++ b/res-xxxhdpi/images/loop28.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop29.png b/res-xxxhdpi/images/loop29.png
new file mode 100644
index 0000000..be5899d
--- /dev/null
+++ b/res-xxxhdpi/images/loop29.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop30.png b/res-xxxhdpi/images/loop30.png
new file mode 100644
index 0000000..a7f95ed
--- /dev/null
+++ b/res-xxxhdpi/images/loop30.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop31.png b/res-xxxhdpi/images/loop31.png
new file mode 100644
index 0000000..1fe0bf3
--- /dev/null
+++ b/res-xxxhdpi/images/loop31.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop32.png b/res-xxxhdpi/images/loop32.png
new file mode 100644
index 0000000..4bd34b4
--- /dev/null
+++ b/res-xxxhdpi/images/loop32.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop33.png b/res-xxxhdpi/images/loop33.png
new file mode 100644
index 0000000..c800b02
--- /dev/null
+++ b/res-xxxhdpi/images/loop33.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop34.png b/res-xxxhdpi/images/loop34.png
new file mode 100644
index 0000000..926b010
--- /dev/null
+++ b/res-xxxhdpi/images/loop34.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop35.png b/res-xxxhdpi/images/loop35.png
new file mode 100644
index 0000000..20f4cc1
--- /dev/null
+++ b/res-xxxhdpi/images/loop35.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop36.png b/res-xxxhdpi/images/loop36.png
new file mode 100644
index 0000000..36e4abe
--- /dev/null
+++ b/res-xxxhdpi/images/loop36.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop37.png b/res-xxxhdpi/images/loop37.png
new file mode 100644
index 0000000..424bb09
--- /dev/null
+++ b/res-xxxhdpi/images/loop37.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop38.png b/res-xxxhdpi/images/loop38.png
new file mode 100644
index 0000000..9e83b0f
--- /dev/null
+++ b/res-xxxhdpi/images/loop38.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop39.png b/res-xxxhdpi/images/loop39.png
new file mode 100644
index 0000000..37c65be
--- /dev/null
+++ b/res-xxxhdpi/images/loop39.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop40.png b/res-xxxhdpi/images/loop40.png
new file mode 100644
index 0000000..961342a
--- /dev/null
+++ b/res-xxxhdpi/images/loop40.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop41.png b/res-xxxhdpi/images/loop41.png
new file mode 100644
index 0000000..28c4aac
--- /dev/null
+++ b/res-xxxhdpi/images/loop41.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop42.png b/res-xxxhdpi/images/loop42.png
new file mode 100644
index 0000000..75adbba
--- /dev/null
+++ b/res-xxxhdpi/images/loop42.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop43.png b/res-xxxhdpi/images/loop43.png
new file mode 100644
index 0000000..4ea659b
--- /dev/null
+++ b/res-xxxhdpi/images/loop43.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop44.png b/res-xxxhdpi/images/loop44.png
new file mode 100644
index 0000000..a36e066
--- /dev/null
+++ b/res-xxxhdpi/images/loop44.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop45.png b/res-xxxhdpi/images/loop45.png
new file mode 100644
index 0000000..f986268
--- /dev/null
+++ b/res-xxxhdpi/images/loop45.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop46.png b/res-xxxhdpi/images/loop46.png
new file mode 100644
index 0000000..6b6d52e
--- /dev/null
+++ b/res-xxxhdpi/images/loop46.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop47.png b/res-xxxhdpi/images/loop47.png
new file mode 100644
index 0000000..30c47f5
--- /dev/null
+++ b/res-xxxhdpi/images/loop47.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop48.png b/res-xxxhdpi/images/loop48.png
new file mode 100644
index 0000000..35c5801
--- /dev/null
+++ b/res-xxxhdpi/images/loop48.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop49.png b/res-xxxhdpi/images/loop49.png
new file mode 100644
index 0000000..849a8e8
--- /dev/null
+++ b/res-xxxhdpi/images/loop49.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop50.png b/res-xxxhdpi/images/loop50.png
new file mode 100644
index 0000000..fd48c65
--- /dev/null
+++ b/res-xxxhdpi/images/loop50.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop51.png b/res-xxxhdpi/images/loop51.png
new file mode 100644
index 0000000..9326afb
--- /dev/null
+++ b/res-xxxhdpi/images/loop51.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop52.png b/res-xxxhdpi/images/loop52.png
new file mode 100644
index 0000000..7a16865
--- /dev/null
+++ b/res-xxxhdpi/images/loop52.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop53.png b/res-xxxhdpi/images/loop53.png
new file mode 100644
index 0000000..5d4db5b
--- /dev/null
+++ b/res-xxxhdpi/images/loop53.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop54.png b/res-xxxhdpi/images/loop54.png
new file mode 100644
index 0000000..ac12a5c
--- /dev/null
+++ b/res-xxxhdpi/images/loop54.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop55.png b/res-xxxhdpi/images/loop55.png
new file mode 100644
index 0000000..6a2cbc1
--- /dev/null
+++ b/res-xxxhdpi/images/loop55.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop56.png b/res-xxxhdpi/images/loop56.png
new file mode 100644
index 0000000..5947d18
--- /dev/null
+++ b/res-xxxhdpi/images/loop56.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop57.png b/res-xxxhdpi/images/loop57.png
new file mode 100644
index 0000000..dddc757
--- /dev/null
+++ b/res-xxxhdpi/images/loop57.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop58.png b/res-xxxhdpi/images/loop58.png
new file mode 100644
index 0000000..5a7d248
--- /dev/null
+++ b/res-xxxhdpi/images/loop58.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop59.png b/res-xxxhdpi/images/loop59.png
new file mode 100644
index 0000000..34f68e8
--- /dev/null
+++ b/res-xxxhdpi/images/loop59.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop60.png b/res-xxxhdpi/images/loop60.png
new file mode 100644
index 0000000..7c2b918
--- /dev/null
+++ b/res-xxxhdpi/images/loop60.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop61.png b/res-xxxhdpi/images/loop61.png
new file mode 100644
index 0000000..b27c4af
--- /dev/null
+++ b/res-xxxhdpi/images/loop61.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop62.png b/res-xxxhdpi/images/loop62.png
new file mode 100644
index 0000000..36e1644
--- /dev/null
+++ b/res-xxxhdpi/images/loop62.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop63.png b/res-xxxhdpi/images/loop63.png
new file mode 100644
index 0000000..a812627
--- /dev/null
+++ b/res-xxxhdpi/images/loop63.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop64.png b/res-xxxhdpi/images/loop64.png
new file mode 100644
index 0000000..97ff930
--- /dev/null
+++ b/res-xxxhdpi/images/loop64.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop65.png b/res-xxxhdpi/images/loop65.png
new file mode 100644
index 0000000..9d69ba7
--- /dev/null
+++ b/res-xxxhdpi/images/loop65.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop66.png b/res-xxxhdpi/images/loop66.png
new file mode 100644
index 0000000..42d1a31
--- /dev/null
+++ b/res-xxxhdpi/images/loop66.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop67.png b/res-xxxhdpi/images/loop67.png
new file mode 100644
index 0000000..bff98b3
--- /dev/null
+++ b/res-xxxhdpi/images/loop67.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop68.png b/res-xxxhdpi/images/loop68.png
new file mode 100644
index 0000000..5bfc75b
--- /dev/null
+++ b/res-xxxhdpi/images/loop68.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop69.png b/res-xxxhdpi/images/loop69.png
new file mode 100644
index 0000000..488a245
--- /dev/null
+++ b/res-xxxhdpi/images/loop69.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop70.png b/res-xxxhdpi/images/loop70.png
new file mode 100644
index 0000000..4a92b7b
--- /dev/null
+++ b/res-xxxhdpi/images/loop70.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop71.png b/res-xxxhdpi/images/loop71.png
new file mode 100644
index 0000000..b220638
--- /dev/null
+++ b/res-xxxhdpi/images/loop71.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop72.png b/res-xxxhdpi/images/loop72.png
new file mode 100644
index 0000000..91c9d44
--- /dev/null
+++ b/res-xxxhdpi/images/loop72.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop73.png b/res-xxxhdpi/images/loop73.png
new file mode 100644
index 0000000..6cf9486
--- /dev/null
+++ b/res-xxxhdpi/images/loop73.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop74.png b/res-xxxhdpi/images/loop74.png
new file mode 100644
index 0000000..d949bc0
--- /dev/null
+++ b/res-xxxhdpi/images/loop74.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop75.png b/res-xxxhdpi/images/loop75.png
new file mode 100644
index 0000000..1b22bc9
--- /dev/null
+++ b/res-xxxhdpi/images/loop75.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop76.png b/res-xxxhdpi/images/loop76.png
new file mode 100644
index 0000000..09c8b8e
--- /dev/null
+++ b/res-xxxhdpi/images/loop76.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop77.png b/res-xxxhdpi/images/loop77.png
new file mode 100644
index 0000000..72fa8c8
--- /dev/null
+++ b/res-xxxhdpi/images/loop77.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop78.png b/res-xxxhdpi/images/loop78.png
new file mode 100644
index 0000000..d5cc7b2
--- /dev/null
+++ b/res-xxxhdpi/images/loop78.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop79.png b/res-xxxhdpi/images/loop79.png
new file mode 100644
index 0000000..207c75a
--- /dev/null
+++ b/res-xxxhdpi/images/loop79.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop80.png b/res-xxxhdpi/images/loop80.png
new file mode 100644
index 0000000..d0b38d7
--- /dev/null
+++ b/res-xxxhdpi/images/loop80.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop81.png b/res-xxxhdpi/images/loop81.png
new file mode 100644
index 0000000..c8655ea
--- /dev/null
+++ b/res-xxxhdpi/images/loop81.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop82.png b/res-xxxhdpi/images/loop82.png
new file mode 100644
index 0000000..fca1ad5
--- /dev/null
+++ b/res-xxxhdpi/images/loop82.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop83.png b/res-xxxhdpi/images/loop83.png
new file mode 100644
index 0000000..ba1b1bf
--- /dev/null
+++ b/res-xxxhdpi/images/loop83.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop84.png b/res-xxxhdpi/images/loop84.png
new file mode 100644
index 0000000..9bcf1dd
--- /dev/null
+++ b/res-xxxhdpi/images/loop84.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop85.png b/res-xxxhdpi/images/loop85.png
new file mode 100644
index 0000000..fb1e08b
--- /dev/null
+++ b/res-xxxhdpi/images/loop85.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop86.png b/res-xxxhdpi/images/loop86.png
new file mode 100644
index 0000000..9e2311e
--- /dev/null
+++ b/res-xxxhdpi/images/loop86.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop87.png b/res-xxxhdpi/images/loop87.png
new file mode 100644
index 0000000..4c6aee1
--- /dev/null
+++ b/res-xxxhdpi/images/loop87.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop88.png b/res-xxxhdpi/images/loop88.png
new file mode 100644
index 0000000..a40c515
--- /dev/null
+++ b/res-xxxhdpi/images/loop88.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop89.png b/res-xxxhdpi/images/loop89.png
new file mode 100644
index 0000000..c16adfb
--- /dev/null
+++ b/res-xxxhdpi/images/loop89.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop90.png b/res-xxxhdpi/images/loop90.png
new file mode 100644
index 0000000..76351c5
--- /dev/null
+++ b/res-xxxhdpi/images/loop90.png
Binary files differ
diff --git a/roots.cpp b/roots.cpp
index 12c6b5e..f361cb8 100644
--- a/roots.cpp
+++ b/roots.cpp
@@ -175,7 +175,7 @@
return WEXITSTATUS(status);
}
-int format_volume(const char* volume) {
+int format_volume(const char* volume, const char* directory) {
Volume* v = volume_for_path(volume);
if (v == NULL) {
LOGE("unknown volume \"%s\"\n", volume);
@@ -241,7 +241,7 @@
}
int result;
if (strcmp(v->fs_type, "ext4") == 0) {
- result = make_ext4fs(v->blk_device, length, volume, sehandle);
+ result = make_ext4fs_directory(v->blk_device, length, volume, sehandle, directory);
} else { /* Has to be f2fs because we checked earlier. */
if (v->key_loc != NULL && strcmp(v->key_loc, "footer") == 0 && length < 0) {
LOGE("format_volume: crypt footer + negative length (%zd) not supported on %s\n", length, v->fs_type);
@@ -273,6 +273,10 @@
return -1;
}
+int format_volume(const char* volume) {
+ return format_volume(volume, NULL);
+}
+
int setup_install_mounts() {
if (fstab == NULL) {
LOGE("can't set up install mounts: no fstab loaded\n");
diff --git a/roots.h b/roots.h
index 6e3b243..a14b7d9 100644
--- a/roots.h
+++ b/roots.h
@@ -41,6 +41,12 @@
// it is mounted.
int format_volume(const char* volume);
+// Reformat the given volume (must be the mount point only, eg
+// "/cache"), no paths permitted. Attempts to unmount the volume if
+// it is mounted.
+// Copies 'directory' to root of the newly formatted volume
+int format_volume(const char* volume, const char* directory);
+
// Ensure that all and only the volumes that packages expect to find
// mounted (/tmp and /cache) are mounted. Returns 0 on success.
int setup_install_mounts();
diff --git a/screen_ui.cpp b/screen_ui.cpp
index 522aa6b..b32df36 100644
--- a/screen_ui.cpp
+++ b/screen_ui.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <linux/input.h>
@@ -40,8 +41,7 @@
#include "screen_ui.h"
#include "ui.h"
-static int char_width;
-static int char_height;
+#define TEXT_INDENT 4
// Return the current time as a double (including fractions of a second).
static double now() {
@@ -52,9 +52,9 @@
ScreenRecoveryUI::ScreenRecoveryUI() :
currentIcon(NONE),
- installingFrame(0),
locale(nullptr),
- rtl_locale(false),
+ intro_done(false),
+ current_frame(0),
progressBarType(EMPTY),
progressScopeStart(0),
progressScopeSize(0),
@@ -73,30 +73,43 @@
menu_items(0),
menu_sel(0),
file_viewer_text_(nullptr),
- animation_fps(-1),
- installing_frames(-1),
+ intro_frames(0),
+ loop_frames(0),
+ animation_fps(30), // TODO: there's currently no way to infer this.
stage(-1),
- max_stage(-1) {
+ max_stage(-1),
+ rtl_locale(false) {
- for (int i = 0; i < 5; i++) {
- backgroundIcon[i] = nullptr;
- }
pthread_mutex_init(&updateMutex, nullptr);
}
+GRSurface* ScreenRecoveryUI::GetCurrentFrame() {
+ if (currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) {
+ return intro_done ? loopFrames[current_frame] : introFrames[current_frame];
+ }
+ return error_icon;
+}
+
+GRSurface* ScreenRecoveryUI::GetCurrentText() {
+ switch (currentIcon) {
+ case ERASING: return erasing_text;
+ case ERROR: return error_text;
+ case INSTALLING_UPDATE: return installing_text;
+ case NO_COMMAND: return no_command_text;
+ case NONE: abort();
+ }
+}
+
// Clear the screen and draw the currently selected background icon (if any).
// Should only be called with updateMutex locked.
-void ScreenRecoveryUI::draw_background_locked(Icon icon) {
+void ScreenRecoveryUI::draw_background_locked() {
pagesIdentical = false;
gr_color(0, 0, 0, 255);
gr_clear();
- if (icon) {
- GRSurface* surface = backgroundIcon[icon];
- if (icon == INSTALLING_UPDATE || icon == ERASING) {
- surface = installation[installingFrame];
- }
- GRSurface* text_surface = backgroundText[icon];
+ if (currentIcon != NONE) {
+ GRSurface* surface = GetCurrentFrame();
+ GRSurface* text_surface = GetCurrentText();
int iconWidth = gr_get_width(surface);
int iconHeight = gr_get_height(surface);
@@ -133,14 +146,15 @@
// Should only be called with updateMutex locked.
void ScreenRecoveryUI::draw_progress_locked() {
if (currentIcon == ERROR) return;
+ if (progressBarType != DETERMINATE) return;
if (currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) {
- GRSurface* icon = installation[installingFrame];
- gr_blit(icon, 0, 0, gr_get_width(icon), gr_get_height(icon), iconX, iconY);
+ GRSurface* frame = GetCurrentFrame();
+ gr_blit(frame, 0, 0, gr_get_width(frame), gr_get_height(frame), iconX, iconY);
}
if (progressBarType != EMPTY) {
- int iconHeight = gr_get_height(backgroundIcon[INSTALLING_UPDATE]);
+ int iconHeight = gr_get_height(loopFrames[0]);
int width = gr_get_width(progressBarEmpty);
int height = gr_get_height(progressBarEmpty);
@@ -213,14 +227,14 @@
*y += 4;
}
-void ScreenRecoveryUI::DrawTextLine(int* y, const char* line, bool bold) {
- gr_text(4, *y, line, bold);
- *y += char_height + 4;
+void ScreenRecoveryUI::DrawTextLine(int x, int* y, const char* line, bool bold) {
+ gr_text(x, *y, line, bold);
+ *y += char_height_ + 4;
}
-void ScreenRecoveryUI::DrawTextLines(int* y, const char* const* lines) {
+void ScreenRecoveryUI::DrawTextLines(int x, int* y, const char* const* lines) {
for (size_t i = 0; lines != nullptr && lines[i] != nullptr; ++i) {
- DrawTextLine(y, lines[i], false);
+ DrawTextLine(x, y, lines[i], false);
}
}
@@ -239,7 +253,7 @@
// Should only be called with updateMutex locked.
void ScreenRecoveryUI::draw_screen_locked() {
if (!show_text) {
- draw_background_locked(currentIcon);
+ draw_background_locked();
draw_progress_locked();
} else {
gr_color(0, 0, 0, 255);
@@ -251,14 +265,14 @@
property_get("ro.bootimage.build.fingerprint", recovery_fingerprint, "");
SetColor(INFO);
- DrawTextLine(&y, "Android Recovery", true);
+ DrawTextLine(TEXT_INDENT, &y, "Android Recovery", true);
for (auto& chunk : android::base::Split(recovery_fingerprint, ":")) {
- DrawTextLine(&y, chunk.c_str(), false);
+ DrawTextLine(TEXT_INDENT, &y, chunk.c_str(), false);
}
- DrawTextLines(&y, HasThreeButtons() ? REGULAR_HELP : LONG_PRESS_HELP);
+ DrawTextLines(TEXT_INDENT, &y, HasThreeButtons() ? REGULAR_HELP : LONG_PRESS_HELP);
SetColor(HEADER);
- DrawTextLines(&y, menu_headers_);
+ DrawTextLines(TEXT_INDENT, &y, menu_headers_);
SetColor(MENU);
DrawHorizontalRule(&y);
@@ -267,7 +281,7 @@
if (i == menu_sel) {
// Draw the highlight bar.
SetColor(IsLongPress() ? MENU_SEL_BG_ACTIVE : MENU_SEL_BG);
- gr_fill(0, y - 2, gr_fb_width(), y + char_height + 2);
+ 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);
@@ -275,7 +289,7 @@
} else {
gr_text(4, y, menu_[i], false);
}
- y += char_height + 4;
+ y += char_height_ + 4;
}
DrawHorizontalRule(&y);
}
@@ -286,9 +300,9 @@
SetColor(LOG);
int row = (text_top_ + text_rows_ - 1) % text_rows_;
size_t count = 0;
- for (int ty = gr_fb_height() - char_height;
+ for (int ty = gr_fb_height() - char_height_;
ty >= y && count < text_rows_;
- ty -= char_height, ++count) {
+ ty -= char_height_, ++count) {
gr_text(0, ty, text_[row], false);
--row;
if (row < 0) row = text_rows_ - 1;
@@ -327,14 +341,23 @@
double start = now();
pthread_mutex_lock(&updateMutex);
- int redraw = 0;
+ bool redraw = false;
// update the installation animation, if active
// skip this if we have a text overlay (too expensive to update)
- if ((currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) &&
- installing_frames > 0 && !show_text) {
- installingFrame = (installingFrame + 1) % installing_frames;
- redraw = 1;
+ 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 = true;
}
// move the progress bar forward on timed intervals, if configured
@@ -345,7 +368,7 @@
if (p > 1.0) p = 1.0;
if (p > progress) {
progress = p;
- redraw = 1;
+ redraw = true;
}
}
@@ -363,22 +386,14 @@
void ScreenRecoveryUI::LoadBitmap(const char* filename, GRSurface** surface) {
int result = res_create_display_surface(filename, surface);
if (result < 0) {
- LOGE("missing bitmap %s\n(Code %d)\n", filename, result);
- }
-}
-
-void ScreenRecoveryUI::LoadBitmapArray(const char* filename, int* frames, int* fps,
- GRSurface*** surface) {
- int result = res_create_multi_display_surface(filename, frames, fps, surface);
- if (result < 0) {
- LOGE("missing bitmap %s\n(Code %d)\n", filename, result);
+ LOGE("missing bitmap %s (error %d)\n", filename, result);
}
}
void ScreenRecoveryUI::LoadLocalizedBitmap(const char* filename, GRSurface** surface) {
int result = res_create_localized_alpha_surface(filename, locale, surface);
if (result < 0) {
- LOGE("missing bitmap %s\n(Code %d)\n", filename, result);
+ LOGE("missing bitmap %s (error %d)\n", filename, result);
}
}
@@ -394,9 +409,9 @@
void ScreenRecoveryUI::Init() {
gr_init();
- gr_font_size(&char_width, &char_height);
- text_rows_ = gr_fb_height() / char_height;
- text_cols_ = gr_fb_width() / char_width;
+ 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);
@@ -405,31 +420,60 @@
text_col_ = text_row_ = 0;
text_top_ = 1;
- backgroundIcon[NONE] = nullptr;
- LoadBitmapArray("icon_installing", &installing_frames, &animation_fps, &installation);
- backgroundIcon[INSTALLING_UPDATE] = installing_frames ? installation[0] : nullptr;
- backgroundIcon[ERASING] = backgroundIcon[INSTALLING_UPDATE];
- LoadBitmap("icon_error", &backgroundIcon[ERROR]);
- backgroundIcon[NO_COMMAND] = backgroundIcon[ERROR];
+ LoadBitmap("icon_error", &error_icon);
LoadBitmap("progress_empty", &progressBarEmpty);
LoadBitmap("progress_fill", &progressBarFill);
+
LoadBitmap("stage_empty", &stageMarkerEmpty);
LoadBitmap("stage_fill", &stageMarkerFill);
- LoadLocalizedBitmap("installing_text", &backgroundText[INSTALLING_UPDATE]);
- LoadLocalizedBitmap("erasing_text", &backgroundText[ERASING]);
- LoadLocalizedBitmap("no_command_text", &backgroundText[NO_COMMAND]);
- LoadLocalizedBitmap("error_text", &backgroundText[ERROR]);
+ LoadLocalizedBitmap("installing_text", &installing_text);
+ LoadLocalizedBitmap("erasing_text", &erasing_text);
+ LoadLocalizedBitmap("no_command_text", &no_command_text);
+ LoadLocalizedBitmap("error_text", &error_text);
+
+ 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;
+ 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;
+ }
+ }
+
+ // 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();
+
+ introFrames = new GRSurface*[intro_frames];
+ for (int i = 0; i < intro_frames; ++i) {
+ LoadBitmap(android::base::StringPrintf("intro%02d", i).c_str(), &introFrames[i]);
+ }
+
+ loopFrames = new GRSurface*[loop_frames];
+ for (int i = 0; i < loop_frames; ++i) {
+ LoadBitmap(android::base::StringPrintf("loop%02d", i).c_str(), &loopFrames[i]);
+ }
+}
+
void ScreenRecoveryUI::SetLocale(const char* new_locale) {
- if (new_locale) {
- this->locale = new_locale;
+ this->locale = new_locale;
+ this->rtl_locale = false;
+
+ if (locale) {
char* lang = strdup(locale);
for (char* p = lang; *p; ++p) {
if (*p == '_') {
@@ -438,8 +482,7 @@
}
}
- // A bit cheesy: keep an explicit list of supported languages
- // that are RTL.
+ // A bit cheesy: keep an explicit list of supported RTL languages.
if (strcmp(lang, "ar") == 0 || // Arabic
strcmp(lang, "fa") == 0 || // Persian (Farsi)
strcmp(lang, "he") == 0 || // Hebrew (new language code)
@@ -448,8 +491,6 @@
rtl_locale = true;
}
free(lang);
- } else {
- new_locale = nullptr;
}
}
diff --git a/screen_ui.h b/screen_ui.h
index 08a5f44..233ff55 100644
--- a/screen_ui.h
+++ b/screen_ui.h
@@ -67,16 +67,23 @@
};
void SetColor(UIElement e);
- private:
+ protected:
Icon currentIcon;
- int installingFrame;
- const char* locale;
- bool rtl_locale;
- pthread_mutex_t updateMutex;
- GRSurface* backgroundIcon[5];
- GRSurface* backgroundText[5];
- GRSurface** installation;
+ const char* locale;
+ bool intro_done;
+ int current_frame;
+
+ GRSurface* error_icon;
+
+ GRSurface* erasing_text;
+ GRSurface* error_text;
+ GRSurface* installing_text;
+ GRSurface* no_command_text;
+
+ GRSurface** introFrames;
+ GRSurface** loopFrames;
+
GRSurface* progressBarEmpty;
GRSurface* progressBarFill;
GRSurface* stageMarkerEmpty;
@@ -109,21 +116,31 @@
pthread_t progress_thread_;
- // The following two are parsed from the image file
- // (e.g. '/res/images/icon_installing.png').
+ // Number of intro frames and loop frames in the animation.
+ int intro_frames;
+ int loop_frames;
+
+ // Number of frames per sec (default: 30) for both parts of the animation.
int animation_fps;
- int installing_frames;
int iconX, iconY;
int stage, max_stage;
- void draw_background_locked(Icon icon);
+ int char_width_;
+ int char_height_;
+ pthread_mutex_t updateMutex;
+ bool rtl_locale;
+
+ void draw_background_locked();
void draw_progress_locked();
void draw_screen_locked();
void update_screen_locked();
void update_progress_locked();
+ GRSurface* GetCurrentFrame();
+ GRSurface* GetCurrentText();
+
static void* ProgressThreadStartRoutine(void* data);
void ProgressThreadLoop();
@@ -132,13 +149,13 @@
void PutChar(char);
void ClearText();
- void DrawHorizontalRule(int* y);
- void DrawTextLine(int* y, const char* line, bool bold);
- void DrawTextLines(int* y, const char* const* lines);
-
+ void LoadAnimation();
void LoadBitmap(const char* filename, GRSurface** surface);
- void LoadBitmapArray(const char* filename, int* frames, int* fps, GRSurface*** surface);
void LoadLocalizedBitmap(const char* filename, GRSurface** surface);
+
+ void DrawHorizontalRule(int* y);
+ void DrawTextLine(int x, int* y, const char* line, bool bold);
+ void DrawTextLines(int x, int* y, const char* const* lines);
};
#endif // RECOVERY_UI_H
diff --git a/tests/Android.mk b/tests/Android.mk
index 7b004b2..81435be 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -31,12 +31,18 @@
# Component tests
include $(CLEAR_VARS)
LOCAL_CLANG := true
+LOCAL_CFLAGS += -Wno-unused-parameter
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
LOCAL_MODULE := recovery_component_test
LOCAL_C_INCLUDES := bootable/recovery
-LOCAL_SRC_FILES := component/verifier_test.cpp
+LOCAL_SRC_FILES := \
+ component/verifier_test.cpp \
+ component/applypatch_test.cpp
LOCAL_FORCE_STATIC_EXECUTABLE := true
LOCAL_STATIC_LIBRARIES := \
+ libapplypatch \
+ libotafault \
+ libmtdutils \
libbase \
libverifier \
libcrypto_utils_static \
@@ -44,6 +50,8 @@
libminui \
libminzip \
libcutils \
+ libbz \
+ libz \
libc
testdata_out_path := $(TARGET_OUT_DATA_NATIVE_TESTS)/recovery
diff --git a/tests/common/test_constants.h b/tests/common/test_constants.h
new file mode 100644
index 0000000..3490f68
--- /dev/null
+++ b/tests/common/test_constants.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agree to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _OTA_TEST_CONSTANTS_H
+#define _OTA_TEST_CONSTANTS_H
+
+#if defined(__LP64__)
+#define NATIVE_TEST_PATH "/nativetest64"
+#else
+#define NATIVE_TEST_PATH "/nativetest"
+#endif
+
+#endif
diff --git a/tests/component/applypatch_test.cpp b/tests/component/applypatch_test.cpp
new file mode 100644
index 0000000..b44ddd1
--- /dev/null
+++ b/tests/component/applypatch_test.cpp
@@ -0,0 +1,392 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agree to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fcntl.h>
+#include <gtest/gtest.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/statvfs.h>
+#include <sys/types.h>
+#include <time.h>
+
+#include <string>
+
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
+#include <android-base/test_utils.h>
+
+#include "applypatch/applypatch.h"
+#include "common/test_constants.h"
+#include "openssl/sha.h"
+#include "print_sha1.h"
+
+static const std::string DATA_PATH = getenv("ANDROID_DATA");
+static const std::string TESTDATA_PATH = "/recovery/testdata";
+static const std::string WORK_FS = "/data";
+
+static std::string sha1sum(const std::string& fname) {
+ uint8_t digest[SHA_DIGEST_LENGTH];
+ std::string data;
+ android::base::ReadFileToString(fname, &data);
+
+ SHA1((const uint8_t*)data.c_str(), data.size(), digest);
+ return print_sha1(digest);
+}
+
+static void mangle_file(const std::string& fname) {
+ FILE* fh = fopen(&fname[0], "w");
+ int r;
+ for (int i=0; i < 1024; i++) {
+ r = rand();
+ fwrite(&r, sizeof(short), 1, fh);
+ }
+ fclose(fh);
+}
+
+static bool file_cmp(std::string& f1, std::string& f2) {
+ std::string c1;
+ std::string c2;
+ android::base::ReadFileToString(f1, &c1);
+ android::base::ReadFileToString(f2, &c2);
+ return c1 == c2;
+}
+
+static std::string from_testdata_base(const std::string fname) {
+ return android::base::StringPrintf("%s%s%s/%s",
+ &DATA_PATH[0],
+ &NATIVE_TEST_PATH[0],
+ &TESTDATA_PATH[0],
+ &fname[0]);
+}
+
+class ApplyPatchTest : public ::testing::Test {
+ public:
+ static void SetUpTestCase() {
+ // set up files
+ old_file = from_testdata_base("old.file");
+ new_file = from_testdata_base("new.file");
+ patch_file = from_testdata_base("patch.bsdiff");
+ rand_file = "/cache/applypatch_test_rand.file";
+ cache_file = "/cache/saved.file";
+
+ // write stuff to rand_file
+ android::base::WriteStringToFile("hello", rand_file);
+
+ // set up SHA constants
+ old_sha1 = sha1sum(old_file);
+ new_sha1 = sha1sum(new_file);
+ srand(time(NULL));
+ bad_sha1_a = android::base::StringPrintf("%040x", rand());
+ bad_sha1_b = android::base::StringPrintf("%040x", rand());
+
+ struct stat st;
+ stat(&new_file[0], &st);
+ new_size = st.st_size;
+ }
+
+ static std::string old_file;
+ static std::string new_file;
+ static std::string rand_file;
+ static std::string cache_file;
+ static std::string patch_file;
+
+ static std::string old_sha1;
+ static std::string new_sha1;
+ static std::string bad_sha1_a;
+ static std::string bad_sha1_b;
+
+ static size_t new_size;
+};
+
+std::string ApplyPatchTest::old_file;
+std::string ApplyPatchTest::new_file;
+
+static void cp(std::string src, std::string tgt) {
+ std::string cmd = android::base::StringPrintf("cp %s %s",
+ &src[0],
+ &tgt[0]);
+ system(&cmd[0]);
+}
+
+static void backup_old() {
+ cp(ApplyPatchTest::old_file, ApplyPatchTest::cache_file);
+}
+
+static void restore_old() {
+ cp(ApplyPatchTest::cache_file, ApplyPatchTest::old_file);
+}
+
+class ApplyPatchCacheTest : public ApplyPatchTest {
+ public:
+ virtual void SetUp() {
+ backup_old();
+ }
+
+ virtual void TearDown() {
+ restore_old();
+ }
+};
+
+class ApplyPatchFullTest : public ApplyPatchCacheTest {
+ public:
+ static void SetUpTestCase() {
+ ApplyPatchTest::SetUpTestCase();
+ unsigned long free_kb = FreeSpaceForFile(&WORK_FS[0]);
+ ASSERT_GE(free_kb * 1024, new_size * 3 / 2);
+ output_f = new TemporaryFile();
+ output_loc = std::string(output_f->path);
+
+ struct FileContents fc;
+
+ ASSERT_EQ(0, LoadFileContents(&rand_file[0], &fc));
+ Value* patch1 = new Value();
+ patch1->type = VAL_BLOB;
+ patch1->size = fc.data.size();
+ patch1->data = static_cast<char*>(malloc(fc.data.size()));
+ memcpy(patch1->data, fc.data.data(), fc.data.size());
+ patches.push_back(patch1);
+
+ ASSERT_EQ(0, LoadFileContents(&patch_file[0], &fc));
+ Value* patch2 = new Value();
+ patch2->type = VAL_BLOB;
+ patch2->size = fc.st.st_size;
+ patch2->data = static_cast<char*>(malloc(fc.data.size()));
+ memcpy(patch2->data, fc.data.data(), fc.data.size());
+ patches.push_back(patch2);
+ }
+ static void TearDownTestCase() {
+ delete output_f;
+ for (auto it = patches.begin(); it != patches.end(); ++it) {
+ free((*it)->data);
+ delete *it;
+ }
+ patches.clear();
+ }
+
+ static std::vector<Value*> patches;
+ static TemporaryFile* output_f;
+ static std::string output_loc;
+};
+
+class ApplyPatchDoubleCacheTest : public ApplyPatchFullTest {
+ public:
+ virtual void SetUp() {
+ ApplyPatchCacheTest::SetUp();
+ cp(cache_file, "/cache/reallysaved.file");
+ }
+
+ virtual void TearDown() {
+ cp("/cache/reallysaved.file", cache_file);
+ ApplyPatchCacheTest::TearDown();
+ }
+};
+
+std::string ApplyPatchTest::rand_file;
+std::string ApplyPatchTest::patch_file;
+std::string ApplyPatchTest::cache_file;
+std::string ApplyPatchTest::old_sha1;
+std::string ApplyPatchTest::new_sha1;
+std::string ApplyPatchTest::bad_sha1_a;
+std::string ApplyPatchTest::bad_sha1_b;
+
+size_t ApplyPatchTest::new_size;
+
+std::vector<Value*> ApplyPatchFullTest::patches;
+TemporaryFile* ApplyPatchFullTest::output_f;
+std::string ApplyPatchFullTest::output_loc;
+
+TEST_F(ApplyPatchTest, CheckModeSingle) {
+ char* s = &old_sha1[0];
+ ASSERT_EQ(0, applypatch_check(&old_file[0], 1, &s));
+}
+
+TEST_F(ApplyPatchTest, CheckModeMultiple) {
+ char* argv[3] = {
+ &bad_sha1_a[0],
+ &old_sha1[0],
+ &bad_sha1_b[0]
+ };
+ ASSERT_EQ(0, applypatch_check(&old_file[0], 3, argv));
+}
+
+TEST_F(ApplyPatchTest, CheckModeFailure) {
+ char* argv[2] = {
+ &bad_sha1_a[0],
+ &bad_sha1_b[0]
+ };
+ ASSERT_NE(0, applypatch_check(&old_file[0], 2, argv));
+}
+
+TEST_F(ApplyPatchCacheTest, CheckCacheCorruptedSingle) {
+ mangle_file(old_file);
+ char* s = &old_sha1[0];
+ ASSERT_EQ(0, applypatch_check(&old_file[0], 1, &s));
+}
+
+TEST_F(ApplyPatchCacheTest, CheckCacheCorruptedMultiple) {
+ mangle_file(old_file);
+ char* argv[3] = {
+ &bad_sha1_a[0],
+ &old_sha1[0],
+ &bad_sha1_b[0]
+ };
+ ASSERT_EQ(0, applypatch_check(&old_file[0], 3, argv));
+}
+
+TEST_F(ApplyPatchCacheTest, CheckCacheCorruptedFailure) {
+ mangle_file(old_file);
+ char* argv[2] = {
+ &bad_sha1_a[0],
+ &bad_sha1_b[0]
+ };
+ ASSERT_NE(0, applypatch_check(&old_file[0], 2, argv));
+}
+
+TEST_F(ApplyPatchCacheTest, CheckCacheMissingSingle) {
+ unlink(&old_file[0]);
+ char* s = &old_sha1[0];
+ ASSERT_EQ(0, applypatch_check(&old_file[0], 1, &s));
+}
+
+TEST_F(ApplyPatchCacheTest, CheckCacheMissingMultiple) {
+ unlink(&old_file[0]);
+ char* argv[3] = {
+ &bad_sha1_a[0],
+ &old_sha1[0],
+ &bad_sha1_b[0]
+ };
+ ASSERT_EQ(0, applypatch_check(&old_file[0], 3, argv));
+}
+
+TEST_F(ApplyPatchCacheTest, CheckCacheMissingFailure) {
+ unlink(&old_file[0]);
+ char* argv[2] = {
+ &bad_sha1_a[0],
+ &bad_sha1_b[0]
+ };
+ ASSERT_NE(0, applypatch_check(&old_file[0], 2, argv));
+}
+
+TEST_F(ApplyPatchFullTest, ApplyInPlace) {
+ std::vector<char*> sha1s;
+ sha1s.push_back(&bad_sha1_a[0]);
+ sha1s.push_back(&old_sha1[0]);
+
+ int ap_result = applypatch(&old_file[0],
+ "-",
+ &new_sha1[0],
+ new_size,
+ 2,
+ sha1s.data(),
+ patches.data(),
+ nullptr);
+ ASSERT_EQ(0, ap_result);
+ ASSERT_TRUE(file_cmp(old_file, new_file));
+ // reapply, applypatch is idempotent so it should succeed
+ ap_result = applypatch(&old_file[0],
+ "-",
+ &new_sha1[0],
+ new_size,
+ 2,
+ sha1s.data(),
+ patches.data(),
+ nullptr);
+ ASSERT_EQ(0, ap_result);
+ ASSERT_TRUE(file_cmp(old_file, new_file));
+}
+
+TEST_F(ApplyPatchFullTest, ApplyInNewLocation) {
+ std::vector<char*> sha1s;
+ sha1s.push_back(&bad_sha1_a[0]);
+ sha1s.push_back(&old_sha1[0]);
+ int ap_result = applypatch(&old_file[0],
+ &output_loc[0],
+ &new_sha1[0],
+ new_size,
+ 2,
+ sha1s.data(),
+ patches.data(),
+ nullptr);
+ ASSERT_EQ(0, ap_result);
+ ASSERT_TRUE(file_cmp(output_loc, new_file));
+ ap_result = applypatch(&old_file[0],
+ &output_loc[0],
+ &new_sha1[0],
+ new_size,
+ 2,
+ sha1s.data(),
+ patches.data(),
+ nullptr);
+ ASSERT_EQ(0, ap_result);
+ ASSERT_TRUE(file_cmp(output_loc, new_file));
+}
+
+TEST_F(ApplyPatchFullTest, ApplyCorruptedInNewLocation) {
+ mangle_file(old_file);
+ std::vector<char*> sha1s;
+ sha1s.push_back(&bad_sha1_a[0]);
+ sha1s.push_back(&old_sha1[0]);
+ int ap_result = applypatch(&old_file[0],
+ &output_loc[0],
+ &new_sha1[0],
+ new_size,
+ 2,
+ sha1s.data(),
+ patches.data(),
+ nullptr);
+ ASSERT_EQ(0, ap_result);
+ ASSERT_TRUE(file_cmp(output_loc, new_file));
+ ap_result = applypatch(&old_file[0],
+ &output_loc[0],
+ &new_sha1[0],
+ new_size,
+ 2,
+ sha1s.data(),
+ patches.data(),
+ nullptr);
+ ASSERT_EQ(0, ap_result);
+ ASSERT_TRUE(file_cmp(output_loc, new_file));
+}
+
+TEST_F(ApplyPatchDoubleCacheTest, ApplyDoubleCorruptedInNewLocation) {
+ mangle_file(old_file);
+ mangle_file(cache_file);
+
+ std::vector<char*> sha1s;
+ sha1s.push_back(&bad_sha1_a[0]);
+ sha1s.push_back(&old_sha1[0]);
+ int ap_result = applypatch(&old_file[0],
+ &output_loc[0],
+ &new_sha1[0],
+ new_size,
+ 2,
+ sha1s.data(),
+ patches.data(),
+ nullptr);
+ ASSERT_NE(0, ap_result);
+ ASSERT_FALSE(file_cmp(output_loc, new_file));
+ ap_result = applypatch(&old_file[0],
+ &output_loc[0],
+ &new_sha1[0],
+ new_size,
+ 2,
+ sha1s.data(),
+ patches.data(),
+ nullptr);
+ ASSERT_NE(0, ap_result);
+ ASSERT_FALSE(file_cmp(output_loc, new_file));
+}
diff --git a/tests/component/verifier_test.cpp b/tests/component/verifier_test.cpp
index b5d7032..6a5e369 100644
--- a/tests/component/verifier_test.cpp
+++ b/tests/component/verifier_test.cpp
@@ -31,16 +31,11 @@
#include <android-base/stringprintf.h>
#include "common.h"
+#include "common/test_constants.h"
#include "minzip/SysUtil.h"
#include "ui.h"
#include "verifier.h"
-#if defined(__LP64__)
-#define NATIVE_TEST_PATH "/nativetest64"
-#else
-#define NATIVE_TEST_PATH "/nativetest"
-#endif
-
static const char* DATA_PATH = getenv("ANDROID_DATA");
static const char* TESTDATA_PATH = "/recovery/testdata/";
diff --git a/tests/testdata/new.file b/tests/testdata/new.file
new file mode 100644
index 0000000..cdeb8fd
--- /dev/null
+++ b/tests/testdata/new.file
Binary files differ
diff --git a/tests/testdata/old.file b/tests/testdata/old.file
new file mode 100644
index 0000000..166c873
--- /dev/null
+++ b/tests/testdata/old.file
Binary files differ
diff --git a/tests/testdata/patch.bsdiff b/tests/testdata/patch.bsdiff
new file mode 100644
index 0000000..b78d385
--- /dev/null
+++ b/tests/testdata/patch.bsdiff
Binary files differ
diff --git a/tools/recovery_l10n/res/layout/main.xml b/tools/recovery_l10n/res/layout/main.xml
index 0900b11..05a16e1 100644
--- a/tools/recovery_l10n/res/layout/main.xml
+++ b/tools/recovery_l10n/res/layout/main.xml
@@ -19,7 +19,9 @@
<TextView android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textColor="#ffffffff"
+ android:fontFamily="sans-serif-medium"
+ android:textColor="#fff5f5f5"
+ android:textSize="14sp"
android:background="#ff000000"
android:maxWidth="480px"
android:gravity="center"
diff --git a/tools/recovery_l10n/src/com/android/recovery_l10n/Main.java b/tools/recovery_l10n/src/com/android/recovery_l10n/Main.java
index 3f2bebe..817a3ad 100644
--- a/tools/recovery_l10n/src/com/android/recovery_l10n/Main.java
+++ b/tools/recovery_l10n/src/com/android/recovery_l10n/Main.java
@@ -149,12 +149,9 @@
String[] localeNames = getAssets().getLocales();
Arrays.sort(localeNames);
ArrayList<Locale> locales = new ArrayList<Locale>();
- for (String ln : localeNames) {
- int u = ln.indexOf('_');
- if (u >= 0) {
- Log.i(TAG, "locale = " + ln);
- locales.add(new Locale(ln.substring(0, u), ln.substring(u+1)));
- }
+ for (String localeName : localeNames) {
+ Log.i(TAG, "locale = " + localeName);
+ locales.add(Locale.forLanguageTag(localeName));
}
final Runnable seq = buildSequence(locales.toArray(new Locale[0]));
diff --git a/uncrypt/Android.mk b/uncrypt/Android.mk
index 6422cb2..09cfdfc 100644
--- a/uncrypt/Android.mk
+++ b/uncrypt/Android.mk
@@ -15,6 +15,15 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
+LOCAL_CLANG := true
+LOCAL_SRC_FILES := bootloader_message_writer.cpp
+LOCAL_MODULE := libbootloader_message_writer
+LOCAL_STATIC_LIBRARIES := libbase libfs_mgr
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/..
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
LOCAL_CLANG := true
@@ -24,7 +33,8 @@
LOCAL_MODULE := uncrypt
-LOCAL_STATIC_LIBRARIES := libbase liblog libfs_mgr libcutils
+LOCAL_STATIC_LIBRARIES := libbootloader_message_writer libbase \
+ liblog libfs_mgr libcutils \
LOCAL_INIT_RC := uncrypt.rc
diff --git a/uncrypt/bootloader_message_writer.cpp b/uncrypt/bootloader_message_writer.cpp
new file mode 100644
index 0000000..3bb106a
--- /dev/null
+++ b/uncrypt/bootloader_message_writer.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/system_properties.h>
+
+#include <string>
+#include <vector>
+
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
+#include <fs_mgr.h>
+
+#include "bootloader.h"
+
+static struct fstab* read_fstab(std::string* err) {
+ // The fstab path is always "/fstab.${ro.hardware}".
+ std::string fstab_path = "/fstab.";
+ char value[PROP_VALUE_MAX];
+ if (__system_property_get("ro.hardware", value) == 0) {
+ *err = "failed to get ro.hardware";
+ return nullptr;
+ }
+ fstab_path += value;
+ struct fstab* fstab = fs_mgr_read_fstab(fstab_path.c_str());
+ if (fstab == nullptr) {
+ *err = "failed to read " + fstab_path;
+ }
+ return fstab;
+}
+
+static std::string get_misc_blk_device(std::string* err) {
+ struct fstab* fstab = read_fstab(err);
+ if (fstab == nullptr) {
+ return "";
+ }
+ fstab_rec* record = fs_mgr_get_entry_for_mount_point(fstab, "/misc");
+ if (record == nullptr) {
+ *err = "failed to find /misc partition";
+ return "";
+ }
+ return record->blk_device;
+}
+
+static bool write_bootloader_message(const bootloader_message& boot, std::string* err) {
+ std::string misc_blk_device = get_misc_blk_device(err);
+ if (misc_blk_device.empty()) {
+ return false;
+ }
+ android::base::unique_fd fd(open(misc_blk_device.c_str(), O_WRONLY | O_SYNC));
+ if (fd.get() == -1) {
+ *err = android::base::StringPrintf("failed to open %s: %s", misc_blk_device.c_str(),
+ strerror(errno));
+ return false;
+ }
+ if (!android::base::WriteFully(fd.get(), &boot, sizeof(boot))) {
+ *err = android::base::StringPrintf("failed to write %s: %s", misc_blk_device.c_str(),
+ strerror(errno));
+ return false;
+ }
+ // TODO: O_SYNC and fsync duplicates each other?
+ if (fsync(fd.get()) == -1) {
+ *err = android::base::StringPrintf("failed to fsync %s: %s", misc_blk_device.c_str(),
+ strerror(errno));
+ return false;
+ }
+ return true;
+}
+
+bool clear_bootloader_message(std::string* err) {
+ bootloader_message boot = {};
+ return write_bootloader_message(boot, err);
+}
+
+bool write_bootloader_message(const std::vector<std::string>& options, std::string* err) {
+ bootloader_message boot = {};
+ strlcpy(boot.command, "boot-recovery", sizeof(boot.command));
+ strlcpy(boot.recovery, "recovery\n", sizeof(boot.recovery));
+ for (const auto& s : options) {
+ strlcat(boot.recovery, s.c_str(), sizeof(boot.recovery));
+ if (s.back() != '\n') {
+ strlcat(boot.recovery, "\n", sizeof(boot.recovery));
+ }
+ }
+ return write_bootloader_message(boot, err);
+}
+
+extern "C" bool write_bootloader_message(const char* options) {
+ std::string err;
+ return write_bootloader_message({options}, &err);
+}
diff --git a/uncrypt/include/bootloader_message_writer.h b/uncrypt/include/bootloader_message_writer.h
new file mode 100644
index 0000000..e0ca3f4
--- /dev/null
+++ b/uncrypt/include/bootloader_message_writer.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BOOTLOADER_MESSAGE_WRITER_H
+#define BOOTLOADER_MESSAGE_WRITER_H
+
+#ifdef __cplusplus
+#include <string>
+#include <vector>
+
+bool clear_bootloader_message(std::string* err);
+
+bool write_bootloader_message(const std::vector<std::string>& options, std::string* err);
+
+#else
+#include <stdbool.h>
+
+// C Interface.
+bool write_bootloader_message(const char* options);
+#endif
+
+#endif // BOOTLOADER_MESSAGE_WRITER_H
diff --git a/uncrypt/uncrypt.cpp b/uncrypt/uncrypt.cpp
index 43a2c2a..0e14da1 100644
--- a/uncrypt/uncrypt.cpp
+++ b/uncrypt/uncrypt.cpp
@@ -39,6 +39,53 @@
// Recovery can take this block map file and retrieve the underlying
// file data to use as an update package.
+/**
+ * In addition to the uncrypt work, uncrypt also takes care of setting and
+ * clearing the bootloader control block (BCB) at /misc partition.
+ *
+ * uncrypt is triggered as init services on demand. It uses socket to
+ * communicate with its caller (i.e. system_server). The socket is managed by
+ * init (i.e. created prior to the service starts, and destroyed when uncrypt
+ * exits).
+ *
+ * Below is the uncrypt protocol.
+ *
+ * a. caller b. init c. uncrypt
+ * --------------- ------------ --------------
+ * a1. ctl.start:
+ * setup-bcb /
+ * clear-bcb /
+ * uncrypt
+ *
+ * b2. create socket at
+ * /dev/socket/uncrypt
+ *
+ * c3. listen and accept
+ *
+ * a4. send a 4-byte int
+ * (message length)
+ * c5. receive message length
+ * a6. send message
+ * c7. receive message
+ * c8. <do the work; may send
+ * the progress>
+ * a9. <may handle progress>
+ * c10. <upon finishing>
+ * send "100" or "-1"
+ *
+ * a11. receive status code
+ * a12. send a 4-byte int to
+ * ack the receive of the
+ * final status code
+ * c13. receive and exit
+ *
+ * b14. destroy the socket
+ *
+ * Note that a12 and c13 are necessary to ensure a11 happens before the socket
+ * gets destroyed in b14.
+ */
+
+#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
@@ -49,6 +96,7 @@
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
+#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
@@ -62,23 +110,32 @@
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
+#include <bootloader_message_writer.h>
#include <cutils/android_reboot.h>
#include <cutils/properties.h>
+#include <cutils/sockets.h>
#include <fs_mgr.h>
#define LOG_TAG "uncrypt"
#include <log/log.h>
-#include "bootloader.h"
-
#define WINDOW_SIZE 5
+// uncrypt provides three services: SETUP_BCB, CLEAR_BCB and UNCRYPT.
+//
+// SETUP_BCB and CLEAR_BCB services use socket communication and do not rely
+// on /cache partitions. They will handle requests to reboot into recovery
+// (for applying updates for non-A/B devices, or factory resets for all
+// devices).
+//
+// UNCRYPT service still needs files on /cache partition (UNCRYPT_PATH_FILE
+// and CACHE_BLOCK_MAP). It will be working (and needed) only for non-A/B
+// devices, on which /cache partitions always exist.
static const std::string CACHE_BLOCK_MAP = "/cache/recovery/block.map";
-static const std::string COMMAND_FILE = "/cache/recovery/command";
-static const std::string STATUS_FILE = "/cache/recovery/uncrypt_status";
static const std::string UNCRYPT_PATH_FILE = "/cache/recovery/uncrypt_file";
+static const std::string UNCRYPT_SOCKET = "uncrypt";
-static struct fstab* fstab = NULL;
+static struct fstab* fstab = nullptr;
static int write_at_offset(unsigned char* buffer, size_t size, int wfd, off64_t offset) {
if (TEMP_FAILURE_RETRY(lseek64(wfd, offset, SEEK_SET)) == -1) {
@@ -152,6 +209,11 @@
return NULL;
}
+static bool write_status_to_socket(int status, int socket) {
+ int status_out = htonl(status);
+ return android::base::WriteFully(socket, &status_out, sizeof(int));
+}
+
// Parse uncrypt_file to find the update package name.
static bool find_uncrypt_package(const std::string& uncrypt_path_file, std::string* package_name) {
CHECK(package_name != nullptr);
@@ -167,7 +229,7 @@
}
static int produce_block_map(const char* path, const char* map_file, const char* blk_dev,
- bool encrypted, int status_fd) {
+ bool encrypted, int socket) {
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());
@@ -181,9 +243,9 @@
return -1;
}
- // Make sure we can write to the status_file.
- if (!android::base::WriteStringToFd("0\n", status_fd)) {
- ALOGE("failed to update \"%s\"\n", STATUS_FILE.c_str());
+ // 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;
}
@@ -235,8 +297,8 @@
// Update the status file, progress must be between [0, 99].
int progress = static_cast<int>(100 * (double(pos) / double(sb.st_size)));
if (progress > last_progress) {
- last_progress = progress;
- android::base::WriteStringToFd(std::to_string(progress) + "\n", status_fd);
+ last_progress = progress;
+ write_status_to_socket(progress, socket);
}
if ((tail+1) % WINDOW_SIZE == head) {
@@ -349,54 +411,7 @@
return 0;
}
-static std::string get_misc_blk_device() {
- struct fstab* fstab = read_fstab();
- if (fstab == nullptr) {
- return "";
- }
- for (int i = 0; i < fstab->num_entries; ++i) {
- fstab_rec* v = &fstab->recs[i];
- if (v->mount_point != nullptr && strcmp(v->mount_point, "/misc") == 0) {
- return v->blk_device;
- }
- }
- return "";
-}
-
-static int write_bootloader_message(const bootloader_message* in) {
- std::string misc_blk_device = get_misc_blk_device();
- if (misc_blk_device.empty()) {
- ALOGE("failed to find /misc partition.");
- return -1;
- }
- android::base::unique_fd fd(open(misc_blk_device.c_str(), O_WRONLY | O_SYNC));
- if (fd == -1) {
- ALOGE("failed to open %s: %s", misc_blk_device.c_str(), strerror(errno));
- return -1;
- }
- if (!android::base::WriteFully(fd, in, sizeof(*in))) {
- ALOGE("failed to write %s: %s", misc_blk_device.c_str(), strerror(errno));
- return -1;
- }
- // TODO: O_SYNC and fsync() duplicates each other?
- if (fsync(fd) == -1) {
- ALOGE("failed to fsync %s: %s", misc_blk_device.c_str(), strerror(errno));
- return -1;
- }
- return 0;
-}
-
-static void reboot_to_recovery() {
- ALOGI("rebooting to recovery");
- property_set("sys.powerctl", "reboot,recovery");
- while (true) {
- pause();
- }
- ALOGE("reboot didn't succeed?");
-}
-
-static int uncrypt(const char* input_path, const char* map_file, int status_fd) {
-
+static int uncrypt(const char* input_path, const char* map_file, const int socket) {
ALOGI("update package is \"%s\"", input_path);
// Turn the name of the file we're supposed to convert into an
@@ -407,10 +422,6 @@
return 1;
}
- if (read_fstab() == NULL) {
- return 1;
- }
-
bool encryptable;
bool encrypted;
const char* blk_dev = find_block_device(path, &encryptable, &encrypted);
@@ -434,7 +445,7 @@
// 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, status_fd) != 0) {
+ if (produce_block_map(path, map_file, blk_dev, encrypted, socket) != 0) {
return 1;
}
}
@@ -442,102 +453,141 @@
return 0;
}
-static int uncrypt_wrapper(const char* input_path, const char* map_file,
- const std::string& status_file) {
- // The pipe has been created by the system server.
- android::base::unique_fd status_fd(open(status_file.c_str(),
- O_WRONLY | O_CREAT | O_SYNC, S_IRUSR | S_IWUSR));
- if (status_fd == -1) {
- ALOGE("failed to open pipe \"%s\": %s", status_file.c_str(), strerror(errno));
- return 1;
- }
-
+static bool uncrypt_wrapper(const char* input_path, const char* map_file, const int socket) {
std::string package;
if (input_path == nullptr) {
if (!find_uncrypt_package(UNCRYPT_PATH_FILE, &package)) {
- android::base::WriteStringToFd("-1\n", status_fd);
- return 1;
+ write_status_to_socket(-1, socket);
+ return false;
}
input_path = package.c_str();
}
CHECK(map_file != nullptr);
- int status = uncrypt(input_path, map_file, status_fd);
+ int status = uncrypt(input_path, map_file, socket);
if (status != 0) {
- android::base::WriteStringToFd("-1\n", status_fd);
- return 1;
+ write_status_to_socket(-1, socket);
+ return false;
}
- android::base::WriteStringToFd("100\n", status_fd);
- return 0;
+ write_status_to_socket(100, socket);
+ return true;
}
-static int clear_bcb(const std::string& status_file) {
- android::base::unique_fd status_fd(open(status_file.c_str(),
- O_WRONLY | O_CREAT | O_SYNC, S_IRUSR | S_IWUSR));
- if (status_fd == -1) {
- ALOGE("failed to open pipe \"%s\": %s", status_file.c_str(), strerror(errno));
- return 1;
+static bool clear_bcb(const int socket) {
+ std::string err;
+ if (!clear_bootloader_message(&err)) {
+ ALOGE("failed to clear bootloader message: %s", err.c_str());
+ write_status_to_socket(-1, socket);
+ return false;
}
- bootloader_message boot = {};
- if (write_bootloader_message(&boot) != 0) {
- android::base::WriteStringToFd("-1\n", status_fd);
- return 1;
- }
- android::base::WriteStringToFd("100\n", status_fd);
- return 0;
+ write_status_to_socket(100, socket);
+ return true;
}
-static int setup_bcb(const std::string& command_file, const std::string& status_file) {
- android::base::unique_fd status_fd(open(status_file.c_str(),
- O_WRONLY | O_CREAT | O_SYNC, S_IRUSR | S_IWUSR));
- if (status_fd == -1) {
- ALOGE("failed to open pipe \"%s\": %s", status_file.c_str(), strerror(errno));
- return 1;
+static bool setup_bcb(const int socket) {
+ // c5. receive message length
+ int length;
+ if (!android::base::ReadFully(socket, &length, 4)) {
+ ALOGE("failed to read the length: %s", strerror(errno));
+ return false;
}
+ length = ntohl(length);
+
+ // c7. receive message
std::string content;
- if (!android::base::ReadFileToString(command_file, &content)) {
- ALOGE("failed to read \"%s\": %s", command_file.c_str(), strerror(errno));
- android::base::WriteStringToFd("-1\n", status_fd);
- return 1;
+ content.resize(length);
+ if (!android::base::ReadFully(socket, &content[0], length)) {
+ ALOGE("failed to read the length: %s", strerror(errno));
+ return false;
}
- bootloader_message boot = {};
- strlcpy(boot.command, "boot-recovery", sizeof(boot.command));
- strlcpy(boot.recovery, "recovery\n", sizeof(boot.recovery));
- strlcat(boot.recovery, content.c_str(), sizeof(boot.recovery));
- if (write_bootloader_message(&boot) != 0) {
- ALOGE("failed to set bootloader message");
- android::base::WriteStringToFd("-1\n", status_fd);
- return 1;
+ ALOGI(" received command: [%s] (%zu)", content.c_str(), content.size());
+
+ // c8. setup the bcb command
+ std::string err;
+ if (!write_bootloader_message({content}, &err)) {
+ ALOGE("failed to set bootloader message: %s", err.c_str());
+ write_status_to_socket(-1, socket);
+ return false;
}
- android::base::WriteStringToFd("100\n", status_fd);
- return 0;
+ // c10. send "100" status
+ write_status_to_socket(100, socket);
+ return true;
}
static void usage(const char* exename) {
fprintf(stderr, "Usage of %s:\n", exename);
fprintf(stderr, "%s [<package_path> <map_file>] Uncrypt ota package.\n", exename);
- fprintf(stderr, "%s --reboot Clear BCB data and reboot to recovery.\n", exename);
fprintf(stderr, "%s --clear-bcb Clear BCB data in misc partition.\n", exename);
fprintf(stderr, "%s --setup-bcb Setup BCB data by command file.\n", exename);
}
int main(int argc, char** argv) {
- if (argc == 2) {
- if (strcmp(argv[1], "--reboot") == 0) {
- reboot_to_recovery();
- } else if (strcmp(argv[1], "--clear-bcb") == 0) {
- return clear_bcb(STATUS_FILE);
- } else if (strcmp(argv[1], "--setup-bcb") == 0) {
- return setup_bcb(COMMAND_FILE, STATUS_FILE);
- }
- } else if (argc == 1 || argc == 3) {
- const char* input_path = nullptr;
- const char* map_file = CACHE_BLOCK_MAP.c_str();
- if (argc == 3) {
- input_path = argv[1];
- map_file = argv[2];
- }
- return uncrypt_wrapper(input_path, map_file, STATUS_FILE);
+ enum { UNCRYPT, SETUP_BCB, CLEAR_BCB } action;
+ const char* input_path = nullptr;
+ const char* map_file = CACHE_BLOCK_MAP.c_str();
+
+ if (argc == 2 && strcmp(argv[1], "--clear-bcb") == 0) {
+ action = CLEAR_BCB;
+ } else if (argc == 2 && strcmp(argv[1], "--setup-bcb") == 0) {
+ action = SETUP_BCB;
+ } else if (argc == 1) {
+ action = UNCRYPT;
+ } else if (argc == 3) {
+ input_path = argv[1];
+ map_file = argv[2];
+ action = UNCRYPT;
+ } else {
+ usage(argv[0]);
+ return 2;
}
- usage(argv[0]);
- return 2;
+
+ if ((fstab = read_fstab()) == nullptr) {
+ return 1;
+ }
+
+ // c3. The socket is created by init when starting the service. uncrypt
+ // will use the socket to communicate with its caller.
+ android::base::unique_fd service_socket(android_get_control_socket(UNCRYPT_SOCKET.c_str()));
+ if (service_socket == -1) {
+ ALOGE("failed to open socket \"%s\": %s", UNCRYPT_SOCKET.c_str(), strerror(errno));
+ return 1;
+ }
+ fcntl(service_socket, F_SETFD, FD_CLOEXEC);
+
+ if (listen(service_socket, 1) == -1) {
+ ALOGE("failed to listen on socket %d: %s", service_socket.get(), strerror(errno));
+ return 1;
+ }
+
+ android::base::unique_fd socket_fd(accept4(service_socket, nullptr, nullptr, SOCK_CLOEXEC));
+ if (socket_fd == -1) {
+ ALOGE("failed to accept on socket %d: %s", service_socket.get(), strerror(errno));
+ return 1;
+ }
+
+ bool success = false;
+ switch (action) {
+ case UNCRYPT:
+ success = uncrypt_wrapper(input_path, map_file, socket_fd);
+ break;
+ case SETUP_BCB:
+ success = setup_bcb(socket_fd);
+ break;
+ case CLEAR_BCB:
+ success = clear_bcb(socket_fd);
+ break;
+ default: // Should never happen.
+ ALOGE("Invalid uncrypt action code: %d", action);
+ return 1;
+ }
+
+ // c13. Read a 4-byte code from the client before uncrypt exits. This is to
+ // ensure the client to receive the last status code before the socket gets
+ // destroyed.
+ int code;
+ if (android::base::ReadFully(socket_fd, &code, 4)) {
+ ALOGI(" received %d, exiting now", code);
+ } else {
+ ALOGE("failed to read the code: %s", strerror(errno));
+ }
+ return success ? 0 : 1;
}
diff --git a/uncrypt/uncrypt.rc b/uncrypt/uncrypt.rc
index b07c1da..52f564e 100644
--- a/uncrypt/uncrypt.rc
+++ b/uncrypt/uncrypt.rc
@@ -1,19 +1,17 @@
service uncrypt /system/bin/uncrypt
class main
- disabled
- oneshot
-
-service pre-recovery /system/bin/uncrypt --reboot
- class main
+ socket uncrypt stream 600 system system
disabled
oneshot
service setup-bcb /system/bin/uncrypt --setup-bcb
class main
+ socket uncrypt stream 600 system system
disabled
oneshot
service clear-bcb /system/bin/uncrypt --clear-bcb
class main
+ socket uncrypt stream 600 system system
disabled
- oneshot
\ No newline at end of file
+ oneshot
diff --git a/verifier.cpp b/verifier.cpp
index 1d6cf81..a2ef946 100644
--- a/verifier.cpp
+++ b/verifier.cpp
@@ -33,6 +33,8 @@
extern RecoveryUI* ui;
+static constexpr size_t MiB = 1024 * 1024;
+
/*
* Simple version of PKCS#7 SignedData extraction. This extracts the
* signature OCTET STRING to be used for signature verification.
@@ -188,8 +190,6 @@
}
}
-#define BUFFER_SIZE 4096
-
bool need_sha1 = false;
bool need_sha256 = false;
for (const auto& key : keys) {
@@ -207,8 +207,10 @@
double frac = -1.0;
size_t so_far = 0;
while (so_far < signed_len) {
- size_t size = signed_len - so_far;
- if (size > BUFFER_SIZE) size = BUFFER_SIZE;
+ // On a Nexus 9, experiment didn't show any performance improvement with
+ // larger sizes past 1MiB, and they reduce the granularity of the progress
+ // bar. http://b/28135231.
+ size_t size = std::min(signed_len - so_far, 1 * MiB);
if (need_sha1) SHA1_Update(&sha1_ctx, addr + so_far, size);
if (need_sha256) SHA256_Update(&sha256_ctx, addr + so_far, size);
diff --git a/wear_touch.cpp b/wear_touch.cpp
new file mode 100644
index 0000000..f22d40b
--- /dev/null
+++ b/wear_touch.cpp
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common.h"
+#include "wear_touch.h"
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include <linux/input.h>
+
+#define DEVICE_PATH "/dev/input"
+
+WearSwipeDetector::WearSwipeDetector(int low, int high, OnSwipeCallback callback, void* cookie):
+ mLowThreshold(low),
+ mHighThreshold(high),
+ mCallback(callback),
+ mCookie(cookie),
+ mCurrentSlot(-1) {
+ pthread_create(&mThread, NULL, touch_thread, this);
+}
+
+WearSwipeDetector::~WearSwipeDetector() {
+}
+
+void WearSwipeDetector::detect(int dx, int dy) {
+ enum SwipeDirection direction;
+
+ if (abs(dy) < mLowThreshold && abs(dx) > mHighThreshold) {
+ direction = dx < 0 ? LEFT : RIGHT;
+ } else if (abs(dx) < mLowThreshold && abs(dy) > mHighThreshold) {
+ direction = dy < 0 ? UP : DOWN;
+ } else {
+ LOGD("Ignore %d %d\n", dx, dy);
+ return;
+ }
+
+ LOGD("Swipe direction=%d\n", direction);
+ mCallback(mCookie, direction);
+}
+
+void WearSwipeDetector::process(struct input_event *event) {
+ if (mCurrentSlot < 0) {
+ mCallback(mCookie, UP);
+ mCurrentSlot = 0;
+ }
+
+ if (event->type == EV_ABS) {
+ if (event->code == ABS_MT_SLOT)
+ mCurrentSlot = event->value;
+
+ // Ignore other fingers
+ if (mCurrentSlot > 0) {
+ return;
+ }
+
+ switch (event->code) {
+ case ABS_MT_POSITION_X:
+ mX = event->value;
+ mFingerDown = true;
+ break;
+
+ case ABS_MT_POSITION_Y:
+ mY = event->value;
+ mFingerDown = true;
+ break;
+
+ case ABS_MT_TRACKING_ID:
+ if (event->value < 0)
+ mFingerDown = false;
+ break;
+ }
+ } else if (event->type == EV_SYN) {
+ if (event->code == SYN_REPORT) {
+ if (mFingerDown && !mSwiping) {
+ mStartX = mX;
+ mStartY = mY;
+ mSwiping = true;
+ } else if (!mFingerDown && mSwiping) {
+ mSwiping = false;
+ detect(mX - mStartX, mY - mStartY);
+ }
+ }
+ }
+}
+
+void WearSwipeDetector::run() {
+ int fd = findDevice(DEVICE_PATH);
+ if (fd < 0) {
+ LOGE("no input devices found\n");
+ return;
+ }
+
+ struct input_event event;
+ while (read(fd, &event, sizeof(event)) == sizeof(event)) {
+ process(&event);
+ }
+
+ close(fd);
+}
+
+void* WearSwipeDetector::touch_thread(void* cookie) {
+ ((WearSwipeDetector*)cookie)->run();
+ return NULL;
+}
+
+#define test_bit(bit, array) (array[bit/8] & (1<<(bit%8)))
+
+int WearSwipeDetector::openDevice(const char *device) {
+ int fd = open(device, O_RDONLY);
+ if (fd < 0) {
+ LOGE("could not open %s, %s\n", device, strerror(errno));
+ return false;
+ }
+
+ char name[80];
+ name[sizeof(name) - 1] = '\0';
+ if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
+ LOGE("could not get device name for %s, %s\n", device, strerror(errno));
+ name[0] = '\0';
+ }
+
+ uint8_t bits[512];
+ memset(bits, 0, sizeof(bits));
+ int ret = ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(bits)), bits);
+ if (ret > 0) {
+ if (test_bit(ABS_MT_POSITION_X, bits) && test_bit(ABS_MT_POSITION_Y, bits)) {
+ LOGD("Found %s %s\n", device, name);
+ return fd;
+ }
+ }
+
+ close(fd);
+ return -1;
+}
+
+int WearSwipeDetector::findDevice(const char* path) {
+ DIR* dir = opendir(path);
+ if (dir == NULL) {
+ LOGE("Could not open directory %s", path);
+ return false;
+ }
+
+ struct dirent* entry;
+ int ret = -1;
+ while (ret < 0 && (entry = readdir(dir)) != NULL) {
+ if (entry->d_name[0] == '.') continue;
+
+ char device[PATH_MAX];
+ device[PATH_MAX-1] = '\0';
+ snprintf(device, PATH_MAX-1, "%s/%s", path, entry->d_name);
+
+ ret = openDevice(device);
+ }
+
+ closedir(dir);
+ return ret;
+}
+
diff --git a/wear_touch.h b/wear_touch.h
new file mode 100644
index 0000000..9a1d315
--- /dev/null
+++ b/wear_touch.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __WEAR_TOUCH_H
+#define __WEAR_TOUCH_H
+
+#include <pthread.h>
+
+class WearSwipeDetector {
+
+public:
+ enum SwipeDirection { UP, DOWN, RIGHT, LEFT };
+ typedef void (*OnSwipeCallback)(void* cookie, enum SwipeDirection direction);
+
+ WearSwipeDetector(int low, int high, OnSwipeCallback cb, void* cookie);
+ ~WearSwipeDetector();
+
+private:
+ void run();
+ void process(struct input_event *event);
+ void detect(int dx, int dy);
+
+ pthread_t mThread;
+ static void* touch_thread(void* cookie);
+
+ int findDevice(const char* path);
+ int openDevice(const char* device);
+
+ int mLowThreshold;
+ int mHighThreshold;
+
+ OnSwipeCallback mCallback;
+ void *mCookie;
+
+ int mX;
+ int mY;
+ int mStartX;
+ int mStartY;
+
+ int mCurrentSlot;
+ bool mFingerDown;
+ bool mSwiping;
+};
+
+#endif // __WEAR_TOUCH_H
diff --git a/wear_ui.cpp b/wear_ui.cpp
index 50aeb38..2502313 100644
--- a/wear_ui.cpp
+++ b/wear_ui.cpp
@@ -16,9 +16,7 @@
#include <errno.h>
#include <fcntl.h>
-#include <pthread.h>
#include <stdarg.h>
-#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
@@ -31,14 +29,10 @@
#include "common.h"
#include "device.h"
-#include "minui/minui.h"
#include "wear_ui.h"
-#include "ui.h"
#include "cutils/properties.h"
#include "android-base/strings.h"
-
-static int char_width;
-static int char_height;
+#include "android-base/stringprintf.h"
// There's only (at most) one of these objects, and global callbacks
// (for pthread_create, and the input event system) need to find it,
@@ -65,7 +59,6 @@
currentIcon(NONE),
intro_done(false),
current_frame(0),
- rtl_locale(false),
progressBarType(EMPTY),
progressScopeStart(0),
progressScopeSize(0),
@@ -84,7 +77,6 @@
for (size_t i = 0; i < 5; i++)
backgroundIcon[i] = NULL;
- pthread_mutex_init(&updateMutex, NULL);
self = this;
}
@@ -148,41 +140,6 @@
}
}
-void WearRecoveryUI::SetColor(UIElement e) {
- switch (e) {
- case HEADER:
- gr_color(247, 0, 6, 255);
- break;
- case MENU:
- case MENU_SEL_BG:
- gr_color(0, 106, 157, 255);
- break;
- case MENU_SEL_FG:
- gr_color(255, 255, 255, 255);
- break;
- case LOG:
- gr_color(249, 194, 0, 255);
- break;
- case TEXT_FILL:
- gr_color(0, 0, 0, 160);
- break;
- default:
- gr_color(255, 255, 255, 255);
- break;
- }
-}
-
-void WearRecoveryUI::DrawTextLine(int x, int* y, const char* line, bool bold) {
- gr_text(x, *y, line, bold);
- *y += char_height + 4;
-}
-
-void WearRecoveryUI::DrawTextLines(int x, int* y, const char* const* lines) {
- for (size_t i = 0; lines != nullptr && lines[i] != nullptr; ++i) {
- DrawTextLine(x, y, lines[i], false);
- }
-}
-
static const char* HEADERS[] = {
"Swipe up/down to move.",
"Swipe left/right to select.",
@@ -221,7 +178,7 @@
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);
- y += char_height+4;
+ y += char_height_+4;
}
// Menu begins here
@@ -232,7 +189,7 @@
if (i == menu_sel) {
// draw the highlight bar
SetColor(MENU_SEL_BG);
- gr_fill(x, y-2, gr_fb_width()-x, y+char_height+2);
+ 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);
@@ -240,7 +197,7 @@
} else {
if (menu[i][0]) gr_text(x+4, y, menu[i], 0);
}
- y += char_height+4;
+ y += char_height_+4;
}
SetColor(MENU);
y += 4;
@@ -256,9 +213,9 @@
int ty;
int row = (text_top+text_rows-1) % text_rows;
size_t count = 0;
- for (int ty = gr_fb_height() - char_height - outer_height;
+ for (int ty = gr_fb_height() - char_height_ - outer_height;
ty > y+2 && count < text_rows;
- ty -= char_height, ++count) {
+ ty -= char_height_, ++count) {
gr_text(x+4, ty, text[row], 0);
--row;
if (row < 0) row = text_rows-1;
@@ -324,26 +281,19 @@
}
}
-void WearRecoveryUI::LoadBitmap(const char* filename, GRSurface** surface) {
- int result = res_create_display_surface(filename, surface);
- if (result < 0) {
- LOGE("missing bitmap %s\n(Code %d)\n", filename, result);
- }
-}
-
void WearRecoveryUI::Init()
{
gr_init();
- gr_font_size(&char_width, &char_height);
+ 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;
+ 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;
+ text_cols = (gr_fb_width() - (outer_width * 2)) / char_width_;
if (text_cols > kMaxCols - 1) text_cols = kMaxCols - 1;
LoadBitmap("icon_installing", &backgroundIcon[INSTALLING_UPDATE]);
@@ -369,29 +319,6 @@
RecoveryUI::Init();
}
-void WearRecoveryUI::SetLocale(const char* locale) {
- if (locale) {
- char* lang = strdup(locale);
- for (char* p = lang; *p; ++p) {
- if (*p == '_') {
- *p = '\0';
- break;
- }
- }
-
- // A bit cheesy: keep an explicit list of supported languages
- // that are RTL.
- if (strcmp(lang, "ar") == 0 || // Arabic
- strcmp(lang, "fa") == 0 || // Persian (Farsi)
- strcmp(lang, "he") == 0 || // Hebrew (new language code)
- strcmp(lang, "iw") == 0 || // Hebrew (old language code)
- strcmp(lang, "ur") == 0) { // Urdu
- rtl_locale = true;
- }
- free(lang);
- }
-}
-
void WearRecoveryUI::SetBackground(Icon icon)
{
pthread_mutex_lock(&updateMutex);
@@ -653,3 +580,35 @@
}
pthread_mutex_unlock(&updateMutex);
}
+
+void WearRecoveryUI::PrintOnScreenOnly(const char *fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ PrintV(fmt, false, ap);
+ va_end(ap);
+}
+
+void WearRecoveryUI::PrintV(const char* fmt, bool copy_to_stdout, va_list ap) {
+ std::string str;
+ android::base::StringAppendV(&str, fmt, ap);
+
+ if (copy_to_stdout) {
+ fputs(str.c_str(), stdout);
+ }
+
+ pthread_mutex_lock(&updateMutex);
+ 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[text_row][text_col++] = *ptr;
+ }
+ text[text_row][text_col] = '\0';
+ update_screen_locked();
+ }
+ pthread_mutex_unlock(&updateMutex);
+}
diff --git a/wear_ui.h b/wear_ui.h
index 63c1b6e..e2d6fe0 100644
--- a/wear_ui.h
+++ b/wear_ui.h
@@ -17,19 +17,13 @@
#ifndef RECOVERY_WEAR_UI_H
#define RECOVERY_WEAR_UI_H
-#include <pthread.h>
-#include <stdio.h>
+#include "screen_ui.h"
-#include "ui.h"
-#include "minui/minui.h"
-
-class WearRecoveryUI : public RecoveryUI {
+class WearRecoveryUI : public ScreenRecoveryUI {
public:
WearRecoveryUI();
void Init();
- void SetLocale(const char* locale);
-
// overall recovery state ("background image")
void SetBackground(Icon icon);
@@ -47,6 +41,7 @@
// printing messages
void Print(const char* fmt, ...);
+ void PrintOnScreenOnly(const char* fmt, ...) __printflike(2, 3);
void ShowFile(const char* filename);
void ShowFile(FILE* fp);
@@ -58,9 +53,6 @@
void Redraw();
- enum UIElement { HEADER, MENU, MENU_SEL_BG, MENU_SEL_FG, LOG, TEXT_FILL };
- virtual void SetColor(UIElement e);
-
protected:
int progress_bar_height, progress_bar_width;
@@ -89,9 +81,6 @@
int current_frame;
- bool rtl_locale;
-
- pthread_mutex_t updateMutex;
GRSurface* backgroundIcon[5];
GRSurface* *introFrames;
GRSurface* *loopFrames;
@@ -128,11 +117,9 @@
void update_screen_locked();
static void* progress_thread(void* cookie);
void progress_loop();
- void LoadBitmap(const char* filename, GRSurface** surface);
void PutChar(char);
void ClearText();
- void DrawTextLine(int x, int* y, const char* line, bool bold);
- void DrawTextLines(int x, int* y, const char* const* lines);
+ void PrintV(const char*, bool, va_list);
};
#endif // RECOVERY_WEAR_UI_H