summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk6
-rw-r--r--applypatch/Android.mk2
-rw-r--r--bootloader.c21
-rw-r--r--common.h22
-rw-r--r--default_recovery_ui.c3
-rw-r--r--encryptedfs_provisioning.c283
-rw-r--r--encryptedfs_provisioning.h51
-rw-r--r--install.c26
-rw-r--r--make-overlay.py102
-rw-r--r--minui/resources.c11
-rw-r--r--mtdutils/Android.mk2
-rw-r--r--mtdutils/mtdutils.c2
-rw-r--r--recovery.c74
-rw-r--r--recovery_ui.h6
-rw-r--r--[-rwxr-xr-x]res/images/icon_error.pngbin10398 -> 14566 bytes
-rw-r--r--[-rwxr-xr-x]res/images/icon_installing.pngbin11493 -> 8046 bytes
-rw-r--r--res/images/icon_installing_overlay01.pngbin0 -> 15591 bytes
-rw-r--r--res/images/icon_installing_overlay02.pngbin0 -> 15487 bytes
-rw-r--r--res/images/icon_installing_overlay03.pngbin0 -> 15467 bytes
-rw-r--r--res/images/icon_installing_overlay04.pngbin0 -> 15561 bytes
-rw-r--r--res/images/icon_installing_overlay05.pngbin0 -> 15506 bytes
-rw-r--r--res/images/icon_installing_overlay06.pngbin0 -> 15471 bytes
-rw-r--r--res/images/icon_installing_overlay07.pngbin0 -> 15645 bytes
-rw-r--r--res/images/indeterminate01.pngbin0 -> 929 bytes
-rw-r--r--res/images/indeterminate02.pngbin0 -> 972 bytes
-rw-r--r--res/images/indeterminate03.pngbin0 -> 976 bytes
-rw-r--r--res/images/indeterminate04.pngbin0 -> 977 bytes
-rw-r--r--res/images/indeterminate05.pngbin0 -> 1024 bytes
-rw-r--r--res/images/indeterminate06.pngbin0 -> 968 bytes
-rw-r--r--res/images/indeterminate1.pngbin1919 -> 0 bytes
-rw-r--r--res/images/indeterminate2.pngbin1912 -> 0 bytes
-rw-r--r--res/images/indeterminate3.pngbin1917 -> 0 bytes
-rw-r--r--res/images/indeterminate4.pngbin1912 -> 0 bytes
-rw-r--r--res/images/indeterminate5.pngbin1902 -> 0 bytes
-rw-r--r--res/images/indeterminate6.pngbin1914 -> 0 bytes
-rw-r--r--res/images/progress_empty.pngbin361 -> 1117 bytes
-rw-r--r--res/images/progress_fill.pngbin286 -> 2885 bytes
-rw-r--r--ui.c239
-rw-r--r--updater/install.c67
-rw-r--r--verifier.c2
40 files changed, 411 insertions, 508 deletions
diff --git a/Android.mk b/Android.mk
index 27ffec70f..508eb4c64 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,5 +1,4 @@
ifneq ($(TARGET_SIMULATOR),true)
-ifeq ($(TARGET_ARCH),arm)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
@@ -12,8 +11,7 @@ LOCAL_SRC_FILES := \
install.c \
roots.c \
ui.c \
- verifier.c \
- encryptedfs_provisioning.c
+ verifier.c
LOCAL_MODULE := recovery
@@ -77,6 +75,4 @@ include $(commands_recovery_local_path)/updater/Android.mk
include $(commands_recovery_local_path)/applypatch/Android.mk
commands_recovery_local_path :=
-endif # TARGET_ARCH == arm
endif # !TARGET_SIMULATOR
-
diff --git a/applypatch/Android.mk b/applypatch/Android.mk
index eff1d77b3..2848b517e 100644
--- a/applypatch/Android.mk
+++ b/applypatch/Android.mk
@@ -14,7 +14,6 @@
ifneq ($(TARGET_SIMULATOR),true)
-ifeq ($(TARGET_ARCH),arm)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
@@ -59,5 +58,4 @@ LOCAL_STATIC_LIBRARIES += libz libbz
include $(BUILD_HOST_EXECUTABLE)
-endif # TARGET_ARCH == arm
endif # !TARGET_SIMULATOR
diff --git a/bootloader.c b/bootloader.c
index b690c5582..709656602 100644
--- a/bootloader.c
+++ b/bootloader.c
@@ -22,6 +22,8 @@
#include <errno.h>
#include <stdio.h>
#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
static int get_bootloader_message_mtd(struct bootloader_message *out, const Volume* v);
static int set_bootloader_message_mtd(const struct bootloader_message *in, const Volume* v);
@@ -132,8 +134,26 @@ static int set_bootloader_message_mtd(const struct bootloader_message *in,
// for misc partitions on block devices
// ------------------------------------
+static void wait_for_device(const char* fn) {
+ int tries = 0;
+ int ret;
+ struct stat buf;
+ do {
+ ++tries;
+ ret = stat(fn, &buf);
+ if (ret) {
+ printf("stat %s try %d: %s\n", fn, tries, strerror(errno));
+ sleep(1);
+ }
+ } while (ret && tries < 10);
+ if (ret) {
+ printf("failed to stat %s\n", fn);
+ }
+}
+
static int get_bootloader_message_block(struct bootloader_message *out,
const Volume* v) {
+ wait_for_device(v->device);
FILE* f = fopen(v->device, "rb");
if (f == NULL) {
LOGE("Can't open %s\n(%s)\n", v->device, strerror(errno));
@@ -155,6 +175,7 @@ static int get_bootloader_message_block(struct bootloader_message *out,
static int set_bootloader_message_block(const struct bootloader_message *in,
const Volume* v) {
+ wait_for_device(v->device);
FILE* f = fopen(v->device, "wb");
if (f == NULL) {
LOGE("Can't open %s\n(%s)\n", v->device, strerror(errno));
diff --git a/common.h b/common.h
index e6e8f8564..ef2fe9f62 100644
--- a/common.h
+++ b/common.h
@@ -107,4 +107,26 @@ typedef struct {
// (that much).
} Volume;
+typedef struct {
+ // number of frames in indeterminate progress bar animation
+ int indeterminate_frames;
+
+ // number of frames per second to try to maintain when animating
+ int update_fps;
+
+ // number of frames in installing animation. may be zero for a
+ // static installation icon.
+ int installing_frames;
+
+ // the install icon is animated by drawing images containing the
+ // changing part over the base icon. These specify the
+ // coordinates of the upper-left corner.
+ int install_overlay_offset_x;
+ int install_overlay_offset_y;
+
+} UIParameters;
+
+// fopen a file, mounting volumes and making parent dirs as necessary.
+FILE* fopen_path(const char *path, const char *mode);
+
#endif // RECOVERY_COMMON_H
diff --git a/default_recovery_ui.c b/default_recovery_ui.c
index bcba88826..7c4017e7e 100644
--- a/default_recovery_ui.c
+++ b/default_recovery_ui.c
@@ -29,6 +29,9 @@ char* MENU_ITEMS[] = { "reboot system now",
"wipe cache partition",
NULL };
+void device_ui_init(UIParameters* ui_parameters) {
+}
+
int device_recovery_start() {
return 0;
}
diff --git a/encryptedfs_provisioning.c b/encryptedfs_provisioning.c
deleted file mode 100644
index 601c817de..000000000
--- a/encryptedfs_provisioning.c
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * Copyright (C) 2009 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "encryptedfs_provisioning.h"
-#include "cutils/misc.h"
-#include "cutils/properties.h"
-#include "common.h"
-#include "mtdutils/mtdutils.h"
-#include "mtdutils/mounts.h"
-#include "roots.h"
-
-const char* encrypted_fs_enabled_property = "persist.security.secfs.enabled";
-const char* encrypted_fs_property_dir = "/data/property/";
-const char* encrypted_fs_system_dir = "/data/system/";
-const char* encrypted_fs_key_file_name = "/data/fs_key.dat";
-const char* encrypted_fs_salt_file_name = "/data/hash_salt.dat";
-const char* encrypted_fs_hash_file_src_name = "/data/system/password.key";
-const char* encrypted_fs_hash_file_dst_name = "/data/hash.dat";
-const char* encrypted_fs_entropy_file_src_name = "/data/system/entropy.dat";
-const char* encrypted_fs_entropy_file_dst_name = "/data/ported_entropy.dat";
-
-void get_property_file_name(char *buffer, const char *property_name) {
- sprintf(buffer, "%s%s", encrypted_fs_property_dir, property_name);
-}
-
-int get_binary_file_contents(char *buffer, int buf_size, const char *file_name, int *out_size) {
- FILE *in_file;
- int read_bytes;
-
- in_file = fopen(file_name, "r");
- if (in_file == NULL) {
- LOGE("Secure FS: error accessing key file.");
- return ENCRYPTED_FS_ERROR;
- }
-
- read_bytes = fread(buffer, 1, buf_size, in_file);
- if (out_size == NULL) {
- if (read_bytes != buf_size) {
- // Error or unexpected data
- fclose(in_file);
- LOGE("Secure FS: error reading conmplete key.");
- return ENCRYPTED_FS_ERROR;
- }
- } else {
- *out_size = read_bytes;
- }
- fclose(in_file);
- return ENCRYPTED_FS_OK;
-}
-
-int set_binary_file_contents(char *buffer, int buf_size, const char *file_name) {
- FILE *out_file;
- int write_bytes;
-
- out_file = fopen(file_name, "w");
- if (out_file == NULL) {
- LOGE("Secure FS: error setting up key file.");
- return ENCRYPTED_FS_ERROR;
- }
-
- write_bytes = fwrite(buffer, 1, buf_size, out_file);
- if (write_bytes != buf_size) {
- // Error or unexpected data
- fclose(out_file);
- LOGE("Secure FS: error reading conmplete key.");
- return ENCRYPTED_FS_ERROR;
- }
-
- fclose(out_file);
- return ENCRYPTED_FS_OK;
-}
-
-int get_text_file_contents(char *buffer, int buf_size, char *file_name) {
- FILE *in_file;
- char *read_data;
-
- in_file = fopen(file_name, "r");
- if (in_file == NULL) {
- LOGE("Secure FS: error accessing properties.");
- return ENCRYPTED_FS_ERROR;
- }
-
- read_data = fgets(buffer, buf_size, in_file);
- if (read_data == NULL) {
- // Error or unexpected data
- fclose(in_file);
- LOGE("Secure FS: error accessing properties.");
- return ENCRYPTED_FS_ERROR;
- }
-
- fclose(in_file);
- return ENCRYPTED_FS_OK;
-}
-
-int set_text_file_contents(char *buffer, char *file_name) {
- FILE *out_file;
- int result;
-
- out_file = fopen(file_name, "w");
- if (out_file == NULL) {
- LOGE("Secure FS: error setting up properties.");
- return ENCRYPTED_FS_ERROR;
- }
-
- result = fputs(buffer, out_file);
- if (result != 0) {
- // Error or unexpected data
- fclose(out_file);
- LOGE("Secure FS: error setting up properties.");
- return ENCRYPTED_FS_ERROR;
- }
-
- fflush(out_file);
- fclose(out_file);
- return ENCRYPTED_FS_OK;
-}
-
-int read_encrypted_fs_boolean_property(const char *prop_name, int *value) {
- char prop_file_name[PROPERTY_KEY_MAX + 32];
- char prop_value[PROPERTY_VALUE_MAX];
- int result;
-
- get_property_file_name(prop_file_name, prop_name);
- result = get_text_file_contents(prop_value, PROPERTY_VALUE_MAX, prop_file_name);
-
- if (result < 0) {
- return result;
- }
-
- if (strncmp(prop_value, "1", 1) == 0) {
- *value = 1;
- } else if (strncmp(prop_value, "0", 1) == 0) {
- *value = 0;
- } else {
- LOGE("Secure FS: error accessing properties.");
- return ENCRYPTED_FS_ERROR;
- }
-
- return ENCRYPTED_FS_OK;
-}
-
-int write_encrypted_fs_boolean_property(const char *prop_name, int value) {
- char prop_file_name[PROPERTY_KEY_MAX + 32];
- char prop_value[PROPERTY_VALUE_MAX];
- int result;
-
- get_property_file_name(prop_file_name, prop_name);
-
- // Create the directory if needed
- mkdir(encrypted_fs_property_dir, 0755);
- if (value == 1) {
- result = set_text_file_contents("1", prop_file_name);
- } else if (value == 0) {
- result = set_text_file_contents("0", prop_file_name);
- } else {
- return ENCRYPTED_FS_ERROR;
- }
- if (result < 0) {
- return result;
- }
-
- return ENCRYPTED_FS_OK;
-}
-
-int read_encrypted_fs_info(encrypted_fs_info *encrypted_fs_data) {
- int result;
- int value;
- result = ensure_path_mounted("/data");
- if (result != 0) {
- LOGE("Secure FS: error mounting userdata partition.");
- return ENCRYPTED_FS_ERROR;
- }
-
- // Read the pre-generated encrypted FS key, password hash and salt.
- result = get_binary_file_contents(encrypted_fs_data->key, ENCRYPTED_FS_KEY_SIZE,
- encrypted_fs_key_file_name, NULL);
- if (result != 0) {
- LOGE("Secure FS: error reading generated file system key.");
- return ENCRYPTED_FS_ERROR;
- }
-
- result = get_binary_file_contents(encrypted_fs_data->salt, ENCRYPTED_FS_SALT_SIZE,
- encrypted_fs_salt_file_name, &(encrypted_fs_data->salt_length));
- if (result != 0) {
- LOGE("Secure FS: error reading file system salt.");
- return ENCRYPTED_FS_ERROR;
- }
-
- result = get_binary_file_contents(encrypted_fs_data->hash, ENCRYPTED_FS_MAX_HASH_SIZE,
- encrypted_fs_hash_file_src_name, &(encrypted_fs_data->hash_length));
- if (result != 0) {
- LOGE("Secure FS: error reading password hash.");
- return ENCRYPTED_FS_ERROR;
- }
-
- result = get_binary_file_contents(encrypted_fs_data->entropy, ENTROPY_MAX_SIZE,
- encrypted_fs_entropy_file_src_name, &(encrypted_fs_data->entropy_length));
- if (result != 0) {
- LOGE("Secure FS: error reading ported entropy.");
- return ENCRYPTED_FS_ERROR;
- }
-
- result = ensure_path_unmounted("/data");
- if (result != 0) {
- LOGE("Secure FS: error unmounting data partition.");
- return ENCRYPTED_FS_ERROR;
- }
-
- return ENCRYPTED_FS_OK;
-}
-
-int restore_encrypted_fs_info(encrypted_fs_info *encrypted_fs_data) {
- int result;
- result = ensure_path_mounted("/data");
- if (result != 0) {
- LOGE("Secure FS: error mounting userdata partition.");
- return ENCRYPTED_FS_ERROR;
- }
-
- // Write the pre-generated secure FS key, password hash and salt.
- result = set_binary_file_contents(encrypted_fs_data->key, ENCRYPTED_FS_KEY_SIZE,
- encrypted_fs_key_file_name);
- if (result != 0) {
- LOGE("Secure FS: error writing generated file system key.");
- return ENCRYPTED_FS_ERROR;
- }
-
- result = set_binary_file_contents(encrypted_fs_data->salt, encrypted_fs_data->salt_length,
- encrypted_fs_salt_file_name);
- if (result != 0) {
- LOGE("Secure FS: error writing file system salt.");
- return ENCRYPTED_FS_ERROR;
- }
-
- result = set_binary_file_contents(encrypted_fs_data->hash, encrypted_fs_data->hash_length,
- encrypted_fs_hash_file_dst_name);
- if (result != 0) {
- LOGE("Secure FS: error writing password hash.");
- return ENCRYPTED_FS_ERROR;
- }
-
- result = set_binary_file_contents(encrypted_fs_data->entropy, encrypted_fs_data->entropy_length,
- encrypted_fs_entropy_file_dst_name);
- if (result != 0) {
- LOGE("Secure FS: error writing ported entropy.");
- return ENCRYPTED_FS_ERROR;
- }
-
- // Set the secure FS properties to their respective values
- result = write_encrypted_fs_boolean_property(encrypted_fs_enabled_property, encrypted_fs_data->mode);
- if (result != 0) {
- return result;
- }
-
- result = ensure_path_unmounted("/data");
- if (result != 0) {
- LOGE("Secure FS: error unmounting data partition.");
- return ENCRYPTED_FS_ERROR;
- }
-
- return ENCRYPTED_FS_OK;
-}
diff --git a/encryptedfs_provisioning.h b/encryptedfs_provisioning.h
deleted file mode 100644
index 284605d20..000000000
--- a/encryptedfs_provisioning.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2009 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 <stdio.h>
-
-#ifndef __ENCRYPTEDFS_PROVISIONING_H__
-#define __ENCRYPTEDFS_PROVISIONING_H__
-
-#define MODE_ENCRYPTED_FS_DISABLED 0
-#define MODE_ENCRYPTED_FS_ENABLED 1
-
-#define ENCRYPTED_FS_OK 0
-#define ENCRYPTED_FS_ERROR (-1)
-
-#define ENCRYPTED_FS_KEY_SIZE 16
-#define ENCRYPTED_FS_SALT_SIZE 16
-#define ENCRYPTED_FS_MAX_HASH_SIZE 128
-#define ENTROPY_MAX_SIZE 4096
-
-struct encrypted_fs_info {
- int mode;
- char key[ENCRYPTED_FS_KEY_SIZE];
- char salt[ENCRYPTED_FS_SALT_SIZE];
- int salt_length;
- char hash[ENCRYPTED_FS_MAX_HASH_SIZE];
- int hash_length;
- char entropy[ENTROPY_MAX_SIZE];
- int entropy_length;
-};
-
-typedef struct encrypted_fs_info encrypted_fs_info;
-
-int read_encrypted_fs_info(encrypted_fs_info *secure_fs_data);
-
-int restore_encrypted_fs_info(encrypted_fs_info *secure_data);
-
-#endif /* __ENCRYPTEDFS_PROVISIONING_H__ */
-
diff --git a/install.c b/install.c
index 5bb3a78fa..707cda438 100644
--- a/install.c
+++ b/install.c
@@ -36,6 +36,8 @@
#define ASSUMED_UPDATE_BINARY_NAME "META-INF/com/google/android/update-binary"
#define PUBLIC_KEYS_FILE "/res/keys"
+static const char *LAST_INSTALL_FILE = "/cache/recovery/last_install";
+
// If the package contains an update binary, extract it and run it.
static int
try_update_binary(const char *path, ZipArchive *zip) {
@@ -233,8 +235,8 @@ exit:
return NULL;
}
-int
-install_package(const char *path)
+static int
+really_install_package(const char *path)
{
ui_set_background(BACKGROUND_ICON_INSTALLING);
ui_print("Finding update package...\n");
@@ -285,3 +287,23 @@ install_package(const char *path)
ui_print("Installing update...\n");
return try_update_binary(path, &zip);
}
+
+int
+install_package(const char* path)
+{
+ FILE* install_log = fopen_path(LAST_INSTALL_FILE, "w");
+ if (install_log) {
+ fputs(path, install_log);
+ fputc('\n', install_log);
+ } else {
+ LOGE("failed to open last_install: %s\n", strerror(errno));
+ }
+ int result = really_install_package(path);
+ if (install_log) {
+ fputc(result == INSTALL_SUCCESS ? '1' : '0', install_log);
+ fputc('\n', install_log);
+ fclose(install_log);
+ chmod(LAST_INSTALL_FILE, 0644);
+ }
+ return result;
+}
diff --git a/make-overlay.py b/make-overlay.py
new file mode 100644
index 000000000..7f931b373
--- /dev/null
+++ b/make-overlay.py
@@ -0,0 +1,102 @@
+# Copyright (C) 2011 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.
+
+"""Script to take a set of frames (PNG files) for a recovery
+"installing" icon animation and turn it into a base image plus a set
+of overlays, as needed by the recovery UI code. Run with the names of
+all the input frames on the command line, in order."""
+
+import sys
+try:
+ import Image
+except ImportError:
+ print "This script requires the Python Imaging Library to be installed."
+ sys.exit(1)
+
+# Find the smallest box that contains all the pixels which change
+# between images.
+
+print "reading", sys.argv[1]
+base = Image.open(sys.argv[1])
+
+minmini = base.size[0]-1
+maxmaxi = 0
+minminj = base.size[1]-1
+maxmaxj = 0
+
+for top_name in sys.argv[2:]:
+ print "reading", top_name
+ top = Image.open(top_name)
+
+ assert base.size == top.size
+
+ mini = base.size[0]-1
+ maxi = 0
+ minj = base.size[1]-1
+ maxj = 0
+
+ h, w = base.size
+ for j in range(w):
+ for i in range(h):
+ b = base.getpixel((i,j))
+ t = top.getpixel((i,j))
+ if b != t:
+ if i < mini: mini = i
+ if i > maxi: maxi = i
+ if j < minj: minj = j
+ if j > maxj: maxj = j
+
+ minmini = min(minmini, mini)
+ maxmaxi = max(maxmaxi, maxi)
+ minminj = min(minminj, minj)
+ maxmaxj = max(maxmaxj, maxj)
+
+w = maxmaxi - minmini + 1
+h = maxmaxj - minminj + 1
+
+# Now write out an image containing just that box, for each frame.
+
+for num, top_name in enumerate(sys.argv[1:]):
+ top = Image.open(top_name)
+
+ out = Image.new("RGB", (w, h))
+ for i in range(w):
+ for j in range(h):
+ t = top.getpixel((i+minmini, j+minminj))
+ out.putpixel((i, j), t)
+
+ fn = "icon_installing_overlay%02d.png" % (num+1,)
+ out.save(fn)
+ print "saved", fn
+
+# Write out the base icon, which is the first frame with that box
+# blacked out (just to make the file smaller, since it's always
+# displayed with one of the overlays on top of it).
+
+for i in range(w):
+ for j in range(h):
+ base.putpixel((i+minmini, j+minminj), (0, 0, 0))
+fn = "icon_installing.png"
+base.save(fn)
+print "saved", fn
+
+# The device_ui_init() function needs to tell the recovery UI the
+# position of the overlay box.
+
+print
+print "add this to your device_ui_init() function:"
+print "-" * 40
+print " ui_parameters->install_overlay_offset_x = %d;" % (minmini,)
+print " ui_parameters->install_overlay_offset_y = %d;" % (minminj,)
+print "-" * 40
diff --git a/minui/resources.c b/minui/resources.c
index 3d2c727fb..b437a87cb 100644
--- a/minui/resources.c
+++ b/minui/resources.c
@@ -49,6 +49,8 @@ int res_create_surface(const char* name, gr_surface* pSurface) {
png_structp png_ptr = NULL;
png_infop info_ptr = NULL;
+ *pSurface = NULL;
+
snprintf(resPath, sizeof(resPath)-1, "/res/images/%s.png", name);
resPath[sizeof(resPath)-1] = '\0';
FILE* fp = fopen(resPath, "rb");
@@ -119,12 +121,17 @@ int res_create_surface(const char* name, gr_surface* pSurface) {
surface->format = (channels == 3) ?
GGL_PIXEL_FORMAT_RGBX_8888 : GGL_PIXEL_FORMAT_RGBA_8888;
+ int alpha = 0;
if (color_type == PNG_COLOR_TYPE_PALETTE) {
- png_set_palette_to_rgb(png_ptr);
+ png_set_palette_to_rgb(png_ptr);
+ }
+ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
+ png_set_tRNS_to_alpha(png_ptr);
+ alpha = 1;
}
int y;
- if (channels == 3) {
+ if (channels == 3 || (channels == 1 && !alpha)) {
for (y = 0; y < height; ++y) {
unsigned char* pRow = pData + y * stride;
png_read_row(png_ptr, pRow, NULL);
diff --git a/mtdutils/Android.mk b/mtdutils/Android.mk
index 57ab579b2..416653698 100644
--- a/mtdutils/Android.mk
+++ b/mtdutils/Android.mk
@@ -1,5 +1,4 @@
ifneq ($(TARGET_SIMULATOR),true)
-ifeq ($(TARGET_ARCH),arm)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
@@ -20,5 +19,4 @@ LOCAL_STATIC_LIBRARIES := libmtdutils
LOCAL_SHARED_LIBRARIES := libcutils libc
include $(BUILD_EXECUTABLE)
-endif # TARGET_ARCH == arm
endif # !TARGET_SIMULATOR
diff --git a/mtdutils/mtdutils.c b/mtdutils/mtdutils.c
index 198f4989d..e4d2a6064 100644
--- a/mtdutils/mtdutils.c
+++ b/mtdutils/mtdutils.c
@@ -269,8 +269,8 @@ MtdReadContext *mtd_read_partition(const MtdPartition *partition)
sprintf(mtddevname, "/dev/mtd/mtd%d", partition->device_index);
ctx->fd = open(mtddevname, O_RDONLY);
if (ctx->fd < 0) {
- free(ctx);
free(ctx->buffer);
+ free(ctx);
return NULL;
}
diff --git a/recovery.c b/recovery.c
index c81a13c37..3a412d5c5 100644
--- a/recovery.c
+++ b/recovery.c
@@ -23,7 +23,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/reboot.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
@@ -33,19 +32,18 @@
#include "bootloader.h"
#include "common.h"
#include "cutils/properties.h"
+#include "cutils/android_reboot.h"
#include "install.h"
#include "minui/minui.h"
#include "minzip/DirUtil.h"
#include "roots.h"
#include "recovery_ui.h"
-#include "encryptedfs_provisioning.h"
static const struct option OPTIONS[] = {
{ "send_intent", required_argument, NULL, 's' },
{ "update_package", required_argument, NULL, 'u' },
{ "wipe_data", no_argument, NULL, 'w' },
{ "wipe_cache", no_argument, NULL, 'c' },
- { "set_encrypted_filesystems", required_argument, NULL, 'e' },
{ "show_text", no_argument, NULL, 't' },
{ NULL, 0, NULL, 0 },
};
@@ -58,6 +56,8 @@ static const char *SDCARD_ROOT = "/sdcard";
static const char *TEMPORARY_LOG_FILE = "/tmp/recovery.log";
static const char *SIDELOAD_TEMP_DIR = "/tmp/sideload";
+extern UIParameters ui_parameters; // from ui.c
+
/*
* The recovery tool communicates with the main system through /cache files.
* /cache/recovery/command - INPUT - command line for tool, one arg per line
@@ -114,33 +114,13 @@ static const char *SIDELOAD_TEMP_DIR = "/tmp/sideload";
* 8g. finish_recovery() erases BCB
* -- after this, rebooting will (try to) restart the main system --
* 9. main() calls reboot() to boot main system
- *
- * SECURE FILE SYSTEMS ENABLE/DISABLE
- * 1. user selects "enable encrypted file systems"
- * 2. main system writes "--set_encrypted_filesystems=on|off" to
- * /cache/recovery/command
- * 3. main system reboots into recovery
- * 4. get_args() writes BCB with "boot-recovery" and
- * "--set_encrypted_filesystems=on|off"
- * -- after this, rebooting will restart the transition --
- * 5. read_encrypted_fs_info() retrieves encrypted file systems settings from /data
- * Settings include: property to specify the Encrypted FS istatus and
- * FS encryption key if enabled (not yet implemented)
- * 6. erase_volume() reformats /data
- * 7. erase_volume() reformats /cache
- * 8. restore_encrypted_fs_info() writes required encrypted file systems settings to /data
- * Settings include: property to specify the Encrypted FS status and
- * FS encryption key if enabled (not yet implemented)
- * 9. finish_recovery() erases BCB
- * -- after this, rebooting will restart the main system --
- * 10. main() calls reboot() to boot main system
*/
static const int MAX_ARG_LENGTH = 4096;
static const int MAX_ARGS = 100;
// open a given path, mounting partitions as necessary
-static FILE*
+FILE*
fopen_path(const char *path, const char *mode) {
if (ensure_path_mounted(path) != 0) {
LOGE("Can't mount %s\n", path);
@@ -710,6 +690,7 @@ main(int argc, char **argv) {
freopen(TEMPORARY_LOG_FILE, "a", stderr); setbuf(stderr, NULL);
printf("Starting recovery on %s", ctime(&start));
+ device_ui_init(&ui_parameters);
ui_init();
ui_set_background(BACKGROUND_ICON_INSTALLING);
load_volume_table();
@@ -718,10 +699,7 @@ main(int argc, char **argv) {
int previous_runs = 0;
const char *send_intent = NULL;
const char *update_package = NULL;
- const char *encrypted_fs_mode = NULL;
int wipe_data = 0, wipe_cache = 0;
- int toggle_secure_fs = 0;
- encrypted_fs_info encrypted_fs_data;
int arg;
while ((arg = getopt_long(argc, argv, "", OPTIONS, NULL)) != -1) {
@@ -731,7 +709,6 @@ main(int argc, char **argv) {
case 'u': update_package = optarg; break;
case 'w': wipe_data = wipe_cache = 1; break;
case 'c': wipe_cache = 1; break;
- case 'e': encrypted_fs_mode = optarg; toggle_secure_fs = 1; break;
case 't': ui_show_text(1); break;
case '?':
LOGE("Invalid command argument\n");
@@ -768,43 +745,7 @@ main(int argc, char **argv) {
int status = INSTALL_SUCCESS;
- if (toggle_secure_fs) {
- if (strcmp(encrypted_fs_mode,"on") == 0) {
- encrypted_fs_data.mode = MODE_ENCRYPTED_FS_ENABLED;
- ui_print("Enabling Encrypted FS.\n");
- } else if (strcmp(encrypted_fs_mode,"off") == 0) {
- encrypted_fs_data.mode = MODE_ENCRYPTED_FS_DISABLED;
- ui_print("Disabling Encrypted FS.\n");
- } else {
- ui_print("Error: invalid Encrypted FS setting.\n");
- status = INSTALL_ERROR;
- }
-
- // Recovery strategy: if the data partition is damaged, disable encrypted file systems.
- // This preventsthe device recycling endlessly in recovery mode.
- if ((encrypted_fs_data.mode == MODE_ENCRYPTED_FS_ENABLED) &&
- (read_encrypted_fs_info(&encrypted_fs_data))) {
- ui_print("Encrypted FS change aborted, resetting to disabled state.\n");
- encrypted_fs_data.mode = MODE_ENCRYPTED_FS_DISABLED;
- }
-
- if (status != INSTALL_ERROR) {
- if (erase_volume("/data")) {
- ui_print("Data wipe failed.\n");
- status = INSTALL_ERROR;
- } else if (erase_volume("/cache")) {
- ui_print("Cache wipe failed.\n");
- status = INSTALL_ERROR;
- } else if ((encrypted_fs_data.mode == MODE_ENCRYPTED_FS_ENABLED) &&
- (restore_encrypted_fs_info(&encrypted_fs_data))) {
- ui_print("Encrypted FS change aborted.\n");
- status = INSTALL_ERROR;
- } else {
- ui_print("Successfully updated Encrypted FS.\n");
- status = INSTALL_SUCCESS;
- }
- }
- } else if (update_package != NULL) {
+ if (update_package != NULL) {
status = install_package(update_package);
if (status != INSTALL_SUCCESS) ui_print("Installation aborted.\n");
} else if (wipe_data) {
@@ -827,7 +768,6 @@ main(int argc, char **argv) {
// Otherwise, get ready to boot the main system...
finish_recovery(send_intent);
ui_print("Rebooting...\n");
- sync();
- reboot(RB_AUTOBOOT);
+ android_reboot(ANDROID_RB_RESTART, 0, 0);
return EXIT_SUCCESS;
}
diff --git a/recovery_ui.h b/recovery_ui.h
index 77ce7f93d..e56a24b29 100644
--- a/recovery_ui.h
+++ b/recovery_ui.h
@@ -17,6 +17,12 @@
#ifndef _RECOVERY_UI_H
#define _RECOVERY_UI_H
+#include "common.h"
+
+// Called before UI library is initialized. Can change things like
+// how many frames are included in various animations, etc.
+extern void device_ui_init(UIParameters* ui_parameters);
+
// Called when recovery starts up. Returns 0.
extern int device_recovery_start();
diff --git a/res/images/icon_error.png b/res/images/icon_error.png
index 90c8d878a..446c3fb19 100755..100644
--- a/res/images/icon_error.png
+++ b/res/images/icon_error.png
Binary files differ
diff --git a/res/images/icon_installing.png b/res/images/icon_installing.png
index d428f57d1..7e42628e7 100755..100644
--- a/res/images/icon_installing.png
+++ b/res/images/icon_installing.png
Binary files differ
diff --git a/res/images/icon_installing_overlay01.png b/res/images/icon_installing_overlay01.png
new file mode 100644
index 000000000..2c4c89a8b
--- /dev/null
+++ b/res/images/icon_installing_overlay01.png
Binary files differ
diff --git a/res/images/icon_installing_overlay02.png b/res/images/icon_installing_overlay02.png
new file mode 100644
index 000000000..b63552bca
--- /dev/null
+++ b/res/images/icon_installing_overlay02.png
Binary files differ
diff --git a/res/images/icon_installing_overlay03.png b/res/images/icon_installing_overlay03.png
new file mode 100644
index 000000000..6acb5ef63
--- /dev/null
+++ b/res/images/icon_installing_overlay03.png
Binary files differ
diff --git a/res/images/icon_installing_overlay04.png b/res/images/icon_installing_overlay04.png
new file mode 100644
index 000000000..0d4608aa4
--- /dev/null
+++ b/res/images/icon_installing_overlay04.png
Binary files differ
diff --git a/res/images/icon_installing_overlay05.png b/res/images/icon_installing_overlay05.png
new file mode 100644
index 000000000..4bfacb269
--- /dev/null
+++ b/res/images/icon_installing_overlay05.png
Binary files differ
diff --git a/res/images/icon_installing_overlay06.png b/res/images/icon_installing_overlay06.png
new file mode 100644
index 000000000..5fd252862
--- /dev/null
+++ b/res/images/icon_installing_overlay06.png
Binary files differ
diff --git a/res/images/icon_installing_overlay07.png b/res/images/icon_installing_overlay07.png
new file mode 100644
index 000000000..350b3814d
--- /dev/null
+++ b/res/images/icon_installing_overlay07.png
Binary files differ
diff --git a/res/images/indeterminate01.png b/res/images/indeterminate01.png
new file mode 100644
index 000000000..84f04b0d2
--- /dev/null
+++ b/res/images/indeterminate01.png
Binary files differ
diff --git a/res/images/indeterminate02.png b/res/images/indeterminate02.png
new file mode 100644
index 000000000..21d012168
--- /dev/null
+++ b/res/images/indeterminate02.png
Binary files differ
diff --git a/res/images/indeterminate03.png b/res/images/indeterminate03.png
new file mode 100644
index 000000000..8a190a8c6
--- /dev/null
+++ b/res/images/indeterminate03.png
Binary files differ
diff --git a/res/images/indeterminate04.png b/res/images/indeterminate04.png
new file mode 100644
index 000000000..baf8d63e4
--- /dev/null
+++ b/res/images/indeterminate04.png
Binary files differ
diff --git a/res/images/indeterminate05.png b/res/images/indeterminate05.png
new file mode 100644
index 000000000..5653c7b06
--- /dev/null
+++ b/res/images/indeterminate05.png
Binary files differ
diff --git a/res/images/indeterminate06.png b/res/images/indeterminate06.png
new file mode 100644
index 000000000..858de85a5
--- /dev/null
+++ b/res/images/indeterminate06.png
Binary files differ
diff --git a/res/images/indeterminate1.png b/res/images/indeterminate1.png
deleted file mode 100644
index 90cb9fba9..000000000
--- a/res/images/indeterminate1.png
+++ /dev/null
Binary files differ
diff --git a/res/images/indeterminate2.png b/res/images/indeterminate2.png
deleted file mode 100644
index f7fb28989..000000000
--- a/res/images/indeterminate2.png
+++ /dev/null
Binary files differ
diff --git a/res/images/indeterminate3.png b/res/images/indeterminate3.png
deleted file mode 100644
index ba10dfa53..000000000
--- a/res/images/indeterminate3.png
+++ /dev/null
Binary files differ
diff --git a/res/images/indeterminate4.png b/res/images/indeterminate4.png
deleted file mode 100644
index ad5d9a542..000000000
--- a/res/images/indeterminate4.png
+++ /dev/null
Binary files differ
diff --git a/res/images/indeterminate5.png b/res/images/indeterminate5.png
deleted file mode 100644
index 8c19c8d57..000000000
--- a/res/images/indeterminate5.png
+++ /dev/null
Binary files differ
diff --git a/res/images/indeterminate6.png b/res/images/indeterminate6.png
deleted file mode 100644
index c0c66386a..000000000
--- a/res/images/indeterminate6.png
+++ /dev/null
Binary files differ
diff --git a/res/images/progress_empty.png b/res/images/progress_empty.png
index 4cb4998dd..c6820159b 100644
--- a/res/images/progress_empty.png
+++ b/res/images/progress_empty.png
Binary files differ
diff --git a/res/images/progress_fill.png b/res/images/progress_fill.png
index eb71754db..9748435f5 100644
--- a/res/images/progress_fill.png
+++ b/res/images/progress_fill.png
Binary files differ
diff --git a/ui.c b/ui.c
index 82004f031..0744da4d9 100644
--- a/ui.c
+++ b/ui.c
@@ -14,19 +14,22 @@
* limitations under the License.
*/
+#include <errno.h>
+#include <fcntl.h>
#include <linux/input.h>
#include <pthread.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/reboot.h>
+#include <sys/stat.h>
#include <sys/time.h>
+#include <sys/types.h>
#include <time.h>
#include <unistd.h>
-#include <errno.h>
#include "common.h"
+#include <cutils/android_reboot.h>
#include "minui/minui.h"
#include "recovery_ui.h"
@@ -36,32 +39,32 @@
#define CHAR_WIDTH 10
#define CHAR_HEIGHT 18
-#define PROGRESSBAR_INDETERMINATE_STATES 6
-#define PROGRESSBAR_INDETERMINATE_FPS 15
-
#define UI_WAIT_KEY_TIMEOUT_SEC 120
+UIParameters ui_parameters = {
+ 6, // indeterminate progress bar frames
+ 20, // fps
+ 7, // installation icon frames (0 == static image)
+ 23, 83, // installation icon overlay offset
+};
+
static pthread_mutex_t gUpdateMutex = PTHREAD_MUTEX_INITIALIZER;
static gr_surface gBackgroundIcon[NUM_BACKGROUND_ICONS];
-static gr_surface gProgressBarIndeterminate[PROGRESSBAR_INDETERMINATE_STATES];
+static gr_surface *gInstallationOverlay;
+static gr_surface *gProgressBarIndeterminate;
static gr_surface gProgressBarEmpty;
static gr_surface gProgressBarFill;
static const struct { gr_surface* surface; const char *name; } BITMAPS[] = {
{ &gBackgroundIcon[BACKGROUND_ICON_INSTALLING], "icon_installing" },
{ &gBackgroundIcon[BACKGROUND_ICON_ERROR], "icon_error" },
- { &gProgressBarIndeterminate[0], "indeterminate1" },
- { &gProgressBarIndeterminate[1], "indeterminate2" },
- { &gProgressBarIndeterminate[2], "indeterminate3" },
- { &gProgressBarIndeterminate[3], "indeterminate4" },
- { &gProgressBarIndeterminate[4], "indeterminate5" },
- { &gProgressBarIndeterminate[5], "indeterminate6" },
{ &gProgressBarEmpty, "progress_empty" },
{ &gProgressBarFill, "progress_fill" },
{ NULL, NULL },
};
-static gr_surface gCurrentIcon = NULL;
+static int gCurrentIcon = 0;
+static int gInstallingFrame = 0;
static enum ProgressBarType {
PROGRESSBAR_TYPE_NONE,
@@ -71,7 +74,7 @@ static enum ProgressBarType {
// Progress bar scope of current operation
static float gProgressScopeStart = 0, gProgressScopeSize = 0, gProgress = 0;
-static time_t gProgressScopeTime, gProgressScopeDuration;
+static double gProgressScopeTime, gProgressScopeDuration;
// Set to 1 when both graphics pages are the same (except for the progress bar)
static int gPagesIdentical = 0;
@@ -93,20 +96,46 @@ static pthread_cond_t key_queue_cond = PTHREAD_COND_INITIALIZER;
static int key_queue[256], key_queue_len = 0;
static volatile char key_pressed[KEY_MAX + 1];
+// Return the current time as a double (including fractions of a second).
+static double now() {
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return tv.tv_sec + tv.tv_usec / 1000000.0;
+}
+
+// Draw the given frame over the installation overlay animation. The
+// background is not cleared or draw with the base icon first; we
+// assume that the frame already contains some other frame of the
+// animation. Does nothing if no overlay animation is defined.
+// Should only be called with gUpdateMutex locked.
+static void draw_install_overlay_locked(int frame) {
+ if (gInstallationOverlay == NULL) return;
+ gr_surface surface = gInstallationOverlay[frame];
+ int iconWidth = gr_get_width(surface);
+ int iconHeight = gr_get_height(surface);
+ gr_blit(surface, 0, 0, iconWidth, iconHeight,
+ ui_parameters.install_overlay_offset_x,
+ ui_parameters.install_overlay_offset_y);
+}
+
// Clear the screen and draw the currently selected background icon (if any).
// Should only be called with gUpdateMutex locked.
-static void draw_background_locked(gr_surface icon)
+static void draw_background_locked(int icon)
{
gPagesIdentical = 0;
gr_color(0, 0, 0, 255);
gr_fill(0, 0, gr_fb_width(), gr_fb_height());
if (icon) {
- int iconWidth = gr_get_width(icon);
- int iconHeight = gr_get_height(icon);
+ gr_surface surface = gBackgroundIcon[icon];
+ int iconWidth = gr_get_width(surface);
+ int iconHeight = gr_get_height(surface);
int iconX = (gr_fb_width() - iconWidth) / 2;
int iconY = (gr_fb_height() - iconHeight) / 2;
- gr_blit(icon, 0, 0, iconWidth, iconHeight, iconX, iconY);
+ gr_blit(surface, 0, 0, iconWidth, iconHeight, iconX, iconY);
+ if (icon == BACKGROUND_ICON_INSTALLING) {
+ draw_install_overlay_locked(gInstallingFrame);
+ }
}
}
@@ -114,35 +143,39 @@ static void draw_background_locked(gr_surface icon)
// Should only be called with gUpdateMutex locked.
static void draw_progress_locked()
{
- if (gProgressBarType == PROGRESSBAR_TYPE_NONE) return;
+ if (gCurrentIcon == BACKGROUND_ICON_INSTALLING) {
+ draw_install_overlay_locked(gInstallingFrame);
+ }
- int iconHeight = gr_get_height(gBackgroundIcon[BACKGROUND_ICON_INSTALLING]);
- int width = gr_get_width(gProgressBarEmpty);
- int height = gr_get_height(gProgressBarEmpty);
+ if (gProgressBarType != PROGRESSBAR_TYPE_NONE) {
+ int iconHeight = gr_get_height(gBackgroundIcon[BACKGROUND_ICON_INSTALLING]);
+ int width = gr_get_width(gProgressBarEmpty);
+ int height = gr_get_height(gProgressBarEmpty);
- int dx = (gr_fb_width() - width)/2;
- int dy = (3*gr_fb_height() + iconHeight - 2*height)/4;
+ int dx = (gr_fb_width() - width)/2;
+ int dy = (3*gr_fb_height() + iconHeight - 2*height)/4;
- // Erase behind the progress bar (in case this was a progress-only update)
- gr_color(0, 0, 0, 255);
- gr_fill(dx, dy, width, height);
+ // Erase behind the progress bar (in case this was a progress-only update)
+ gr_color(0, 0, 0, 255);
+ gr_fill(dx, dy, width, height);
- if (gProgressBarType == PROGRESSBAR_TYPE_NORMAL) {
- float progress = gProgressScopeStart + gProgress * gProgressScopeSize;
- int pos = (int) (progress * width);
+ if (gProgressBarType == PROGRESSBAR_TYPE_NORMAL) {
+ float progress = gProgressScopeStart + gProgress * gProgressScopeSize;
+ int pos = (int) (progress * width);
- if (pos > 0) {
- gr_blit(gProgressBarFill, 0, 0, pos, height, dx, dy);
- }
- if (pos < width-1) {
- gr_blit(gProgressBarEmpty, pos, 0, width-pos, height, dx+pos, dy);
+ if (pos > 0) {
+ gr_blit(gProgressBarFill, 0, 0, pos, height, dx, dy);
+ }
+ if (pos < width-1) {
+ gr_blit(gProgressBarEmpty, pos, 0, width-pos, height, dx+pos, dy);
+ }
}
- }
- if (gProgressBarType == PROGRESSBAR_TYPE_INDETERMINATE) {
- static int frame = 0;
- gr_blit(gProgressBarIndeterminate[frame], 0, 0, width, height, dx, dy);
- frame = (frame + 1) % PROGRESSBAR_INDETERMINATE_STATES;
+ if (gProgressBarType == PROGRESSBAR_TYPE_INDETERMINATE) {
+ static int frame = 0;
+ gr_blit(gProgressBarIndeterminate[frame], 0, 0, width, height, dx, dy);
+ frame = (frame + 1) % ui_parameters.indeterminate_frames;
+ }
}
}
@@ -207,7 +240,7 @@ static void update_progress_locked(void)
draw_screen_locked(); // Must redraw the whole screen
gPagesIdentical = 1;
} else {
- draw_progress_locked(); // Draw only the progress bar
+ draw_progress_locked(); // Draw only the progress bar and overlays
}
gr_flip();
}
@@ -215,29 +248,49 @@ static void update_progress_locked(void)
// Keeps the progress bar updated, even when the process is otherwise busy.
static void *progress_thread(void *cookie)
{
+ double interval = 1.0 / ui_parameters.update_fps;
for (;;) {
- usleep(1000000 / PROGRESSBAR_INDETERMINATE_FPS);
+ double start = now();
pthread_mutex_lock(&gUpdateMutex);
+ int redraw = 0;
+
+ // update the installation animation, if active
+ // skip this if we have a text overlay (too expensive to update)
+ if (gCurrentIcon == BACKGROUND_ICON_INSTALLING &&
+ ui_parameters.installing_frames > 0 &&
+ !show_text) {
+ gInstallingFrame =
+ (gInstallingFrame + 1) % ui_parameters.installing_frames;
+ redraw = 1;
+ }
+
// update the progress bar animation, if active
// skip this if we have a text overlay (too expensive to update)
if (gProgressBarType == PROGRESSBAR_TYPE_INDETERMINATE && !show_text) {
- update_progress_locked();
+ redraw = 1;
}
// move the progress bar forward on timed intervals, if configured
int duration = gProgressScopeDuration;
if (gProgressBarType == PROGRESSBAR_TYPE_NORMAL && duration > 0) {
- int elapsed = time(NULL) - gProgressScopeTime;
+ double elapsed = now() - gProgressScopeTime;
float progress = 1.0 * elapsed / duration;
if (progress > 1.0) progress = 1.0;
if (progress > gProgress) {
gProgress = progress;
- update_progress_locked();
+ redraw = 1;
}
}
+ if (redraw) update_progress_locked();
+
pthread_mutex_unlock(&gUpdateMutex);
+ double end = now();
+ // minimum of 20ms delay between frames
+ double delay = interval - (end-start);
+ if (delay < 0.02) delay = 0.02;
+ usleep((long)(delay * 1000000));
}
return NULL;
}
@@ -305,7 +358,7 @@ static void *input_thread(void *cookie)
}
if (ev.value > 0 && device_reboot_now(key_pressed, ev.code)) {
- reboot(RB_AUTOBOOT);
+ android_reboot(ANDROID_RB_RESTART, 0, 0);
}
}
return NULL;
@@ -328,13 +381,47 @@ void ui_init(void)
for (i = 0; BITMAPS[i].name != NULL; ++i) {
int result = res_create_surface(BITMAPS[i].name, BITMAPS[i].surface);
if (result < 0) {
- if (result == -2) {
- LOGI("Bitmap %s missing header\n", BITMAPS[i].name);
- } else {
- LOGE("Missing bitmap %s\n(Code %d)\n", BITMAPS[i].name, result);
+ LOGE("Missing bitmap %s\n(Code %d)\n", BITMAPS[i].name, result);
+ }
+ }
+
+ gProgressBarIndeterminate = malloc(ui_parameters.indeterminate_frames *
+ sizeof(gr_surface));
+ for (i = 0; i < ui_parameters.indeterminate_frames; ++i) {
+ char filename[40];
+ // "indeterminate01.png", "indeterminate02.png", ...
+ sprintf(filename, "indeterminate%02d", i+1);
+ int result = res_create_surface(filename, gProgressBarIndeterminate+i);
+ if (result < 0) {
+ LOGE("Missing bitmap %s\n(Code %d)\n", filename, result);
+ }
+ }
+
+ if (ui_parameters.installing_frames > 0) {
+ gInstallationOverlay = malloc(ui_parameters.installing_frames *
+ sizeof(gr_surface));
+ for (i = 0; i < ui_parameters.installing_frames; ++i) {
+ char filename[40];
+ // "icon_installing_overlay01.png",
+ // "icon_installing_overlay02.png", ...
+ sprintf(filename, "icon_installing_overlay%02d", i+1);
+ int result = res_create_surface(filename, gInstallationOverlay+i);
+ if (result < 0) {
+ LOGE("Missing bitmap %s\n(Code %d)\n", filename, result);
}
- *BITMAPS[i].surface = NULL;
}
+
+ // Adjust the offset to account for the positioning of the
+ // base image on the screen.
+ if (gBackgroundIcon[BACKGROUND_ICON_INSTALLING] != NULL) {
+ gr_surface bg = gBackgroundIcon[BACKGROUND_ICON_INSTALLING];
+ ui_parameters.install_overlay_offset_x +=
+ (gr_fb_width() - gr_get_width(bg)) / 2;
+ ui_parameters.install_overlay_offset_y +=
+ (gr_fb_height() - gr_get_height(bg)) / 2;
+ }
+ } else {
+ gInstallationOverlay = NULL;
}
pthread_t t;
@@ -345,7 +432,7 @@ void ui_init(void)
void ui_set_background(int icon)
{
pthread_mutex_lock(&gUpdateMutex);
- gCurrentIcon = gBackgroundIcon[icon];
+ gCurrentIcon = icon;
update_screen_locked();
pthread_mutex_unlock(&gUpdateMutex);
}
@@ -366,7 +453,7 @@ void ui_show_progress(float portion, int seconds)
gProgressBarType = PROGRESSBAR_TYPE_NORMAL;
gProgressScopeStart += gProgressScopeSize;
gProgressScopeSize = portion;
- gProgressScopeTime = time(NULL);
+ gProgressScopeTime = now();
gProgressScopeDuration = seconds;
gProgress = 0;
update_progress_locked();
@@ -503,22 +590,44 @@ void ui_show_text(int visible)
pthread_mutex_unlock(&gUpdateMutex);
}
+// Return true if USB is connected.
+static int usb_connected() {
+ int fd = open("/sys/class/switch/usb_connected/state", O_RDONLY);
+ if (fd < 0) {
+ printf("failed to open /sys/class/switch/usb_connected/state: %s\n",
+ strerror(errno));
+ return 0;
+ }
+
+ char buf;
+ int connected = (read(fd, &buf, 1) == 1) && (buf == '1');
+ if (close(fd) < 0) {
+ printf("failed to close /sys/class/switch/usb_connected/state: %s\n",
+ strerror(errno));
+ }
+ return connected;
+}
+
int ui_wait_key()
{
pthread_mutex_lock(&key_queue_mutex);
- struct timeval now;
- struct timespec timeout;
- gettimeofday(&now, NULL);
- timeout.tv_sec = now.tv_sec;
- timeout.tv_nsec = now.tv_usec * 1000;
- timeout.tv_sec += UI_WAIT_KEY_TIMEOUT_SEC;
-
- int rc = 0;
- while (key_queue_len == 0 && rc != ETIMEDOUT) {
- rc = pthread_cond_timedwait(&key_queue_cond, &key_queue_mutex,
- &timeout);
- }
+ // Time out after UI_WAIT_KEY_TIMEOUT_SEC, unless a USB cable is
+ // plugged in.
+ do {
+ struct timeval now;
+ struct timespec timeout;
+ gettimeofday(&now, NULL);
+ timeout.tv_sec = now.tv_sec;
+ timeout.tv_nsec = now.tv_usec * 1000;
+ timeout.tv_sec += UI_WAIT_KEY_TIMEOUT_SEC;
+
+ int rc = 0;
+ while (key_queue_len == 0 && rc != ETIMEDOUT) {
+ rc = pthread_cond_timedwait(&key_queue_cond, &key_queue_mutex,
+ &timeout);
+ }
+ } while (usb_connected() && key_queue_len == 0);
int key = -1;
if (key_queue_len > 0) {
diff --git a/updater/install.c b/updater/install.c
index 6a7996467..0396bae6c 100644
--- a/updater/install.c
+++ b/updater/install.c
@@ -782,21 +782,26 @@ static bool write_raw_image_cb(const unsigned char* data,
return false;
}
-// write_raw_image(file, partition)
+// write_raw_image(filename_or_blob, partition)
Value* WriteRawImageFn(const char* name, State* state, int argc, Expr* argv[]) {
char* result = NULL;
- char* partition;
- char* filename;
- if (ReadArgs(state, argv, 2, &filename, &partition) < 0) {
+ Value* partition_value;
+ Value* contents;
+ if (ReadValueArgs(state, argv, 2, &contents, &partition_value) < 0) {
return NULL;
}
+ if (partition_value->type != VAL_STRING) {
+ ErrorAbort(state, "partition argument to %s must be string", name);
+ goto done;
+ }
+ char* partition = partition_value->data;
if (strlen(partition) == 0) {
ErrorAbort(state, "partition argument to %s can't be empty", name);
goto done;
}
- if (strlen(filename) == 0) {
+ if (contents->type == VAL_STRING && strlen((char*) contents->data) == 0) {
ErrorAbort(state, "file argument to %s can't be empty", name);
goto done;
}
@@ -819,27 +824,35 @@ Value* WriteRawImageFn(const char* name, State* state, int argc, Expr* argv[]) {
bool success;
- FILE* f = fopen(filename, "rb");
- if (f == NULL) {
- fprintf(stderr, "%s: can't open %s: %s\n",
- name, filename, strerror(errno));
- result = strdup("");
- goto done;
- }
+ if (contents->type == VAL_STRING) {
+ // we're given a filename as the contents
+ char* filename = contents->data;
+ FILE* f = fopen(filename, "rb");
+ if (f == NULL) {
+ fprintf(stderr, "%s: can't open %s: %s\n",
+ name, filename, strerror(errno));
+ result = strdup("");
+ goto done;
+ }
- success = true;
- char* buffer = malloc(BUFSIZ);
- int read;
- while (success && (read = fread(buffer, 1, BUFSIZ, f)) > 0) {
- int wrote = mtd_write_data(ctx, buffer, read);
- success = success && (wrote == read);
- if (!success) {
- fprintf(stderr, "mtd_write_data to %s failed: %s\n",
- partition, strerror(errno));
+ success = true;
+ char* buffer = malloc(BUFSIZ);
+ int read;
+ while (success && (read = fread(buffer, 1, BUFSIZ, f)) > 0) {
+ int wrote = mtd_write_data(ctx, buffer, read);
+ success = success && (wrote == read);
}
+ free(buffer);
+ fclose(f);
+ } else {
+ // we're given a blob as the contents
+ ssize_t wrote = mtd_write_data(ctx, contents->data, contents->size);
+ success = (wrote == contents->size);
+ }
+ if (!success) {
+ fprintf(stderr, "mtd_write_data to %s failed: %s\n",
+ partition, strerror(errno));
}
- free(buffer);
- fclose(f);
if (mtd_erase_blocks(ctx, -1) == -1) {
fprintf(stderr, "%s: error erasing blocks of %s\n", name, partition);
@@ -848,14 +861,14 @@ Value* WriteRawImageFn(const char* name, State* state, int argc, Expr* argv[]) {
fprintf(stderr, "%s: error closing write of %s\n", name, partition);
}
- printf("%s %s partition from %s\n",
- success ? "wrote" : "failed to write", partition, filename);
+ printf("%s %s partition\n",
+ success ? "wrote" : "failed to write", partition);
result = success ? partition : strdup("");
done:
- if (result != partition) free(partition);
- free(filename);
+ if (result != partition) FreeValue(partition_value);
+ FreeValue(contents);
return StringValue(result);
}
diff --git a/verifier.c b/verifier.c
index 9d39fd139..729e085cf 100644
--- a/verifier.c
+++ b/verifier.c
@@ -173,7 +173,7 @@ int verify_file(const char* path, const RSAPublicKey *pKeys, unsigned int numKey
// the signing tool appends after the signature itself.
if (RSA_verify(pKeys+i, eocd + eocd_size - 6 - RSANUMBYTES,
RSANUMBYTES, sha1)) {
- LOGI("whole-file signature verified\n");
+ LOGI("whole-file signature verified against key %d\n", i);
free(eocd);
return VERIFY_SUCCESS;
}