Merge "update_verifier: Support AVB."
diff --git a/Android.mk b/Android.mk
index e619db0..5348e36 100644
--- a/Android.mk
+++ b/Android.mk
@@ -76,6 +76,7 @@
rotate_logs.cpp \
screen_ui.cpp \
ui.cpp \
+ vr_ui.cpp \
wear_ui.cpp \
wear_touch.cpp \
@@ -182,6 +183,17 @@
LOCAL_CFLAGS := -Werror
include $(BUILD_STATIC_LIBRARY)
+# vr headset default device
+# ===============================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := vr_device.cpp
+
+# should match TARGET_RECOVERY_UI_LIB set in BoardConfig.mk
+LOCAL_MODULE := librecovery_ui_vr
+
+include $(BUILD_STATIC_LIBRARY)
+
include \
$(LOCAL_PATH)/applypatch/Android.mk \
$(LOCAL_PATH)/boot_control/Android.mk \
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..09754c6
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1,3 @@
+enh+aosp-gerrit@google.com
+tbao@google.com
+xunchang@google.com
diff --git a/applypatch/imgpatch.cpp b/applypatch/imgpatch.cpp
index 702a624..df75f98 100644
--- a/applypatch/imgpatch.cpp
+++ b/applypatch/imgpatch.cpp
@@ -26,12 +26,14 @@
#include <sys/stat.h>
#include <unistd.h>
+#include <memory>
#include <string>
#include <vector>
+#include <android-base/logging.h>
+#include <android-base/memory.h>
#include <applypatch/applypatch.h>
#include <applypatch/imgdiff.h>
-#include <android-base/memory.h>
#include <openssl/sha.h>
#include <zlib.h>
@@ -43,6 +45,86 @@
return android::base::get_unaligned<int32_t>(address);
}
+// This function is a wrapper of ApplyBSDiffPatch(). It has a custom sink function to deflate the
+// patched data and stream the deflated data to output.
+static bool ApplyBSDiffPatchAndStreamOutput(const uint8_t* src_data, size_t src_len,
+ const Value* patch, size_t patch_offset,
+ const char* deflate_header, SinkFn sink, SHA_CTX* ctx) {
+ size_t expected_target_length = static_cast<size_t>(Read8(deflate_header + 32));
+ int level = Read4(deflate_header + 40);
+ int method = Read4(deflate_header + 44);
+ int window_bits = Read4(deflate_header + 48);
+ int mem_level = Read4(deflate_header + 52);
+ int strategy = Read4(deflate_header + 56);
+
+ std::unique_ptr<z_stream, decltype(&deflateEnd)> strm(new z_stream(), deflateEnd);
+ strm->zalloc = Z_NULL;
+ strm->zfree = Z_NULL;
+ strm->opaque = Z_NULL;
+ strm->avail_in = 0;
+ strm->next_in = nullptr;
+ int ret = deflateInit2(strm.get(), level, method, window_bits, mem_level, strategy);
+ if (ret != Z_OK) {
+ LOG(ERROR) << "Failed to init uncompressed data deflation: " << ret;
+ return false;
+ }
+
+ // Define a custom sink wrapper that feeds to bspatch. It deflates the available patch data on
+ // the fly and outputs the compressed data to the given sink.
+ size_t actual_target_length = 0;
+ size_t total_written = 0;
+ static constexpr size_t buffer_size = 32768;
+ auto compression_sink = [&](const uint8_t* data, size_t len) -> size_t {
+ // The input patch length for an update never exceeds INT_MAX.
+ strm->avail_in = len;
+ strm->next_in = data;
+ do {
+ std::vector<uint8_t> buffer(buffer_size);
+ strm->avail_out = buffer_size;
+ strm->next_out = buffer.data();
+ if (actual_target_length + len < expected_target_length) {
+ ret = deflate(strm.get(), Z_NO_FLUSH);
+ } else {
+ ret = deflate(strm.get(), Z_FINISH);
+ }
+ if (ret != Z_OK && ret != Z_STREAM_END) {
+ LOG(ERROR) << "Failed to deflate stream: " << ret;
+ // zero length indicates an error in the sink function of bspatch().
+ return 0;
+ }
+
+ size_t have = buffer_size - strm->avail_out;
+ total_written += have;
+ if (sink(buffer.data(), have) != have) {
+ LOG(ERROR) << "Failed to write " << have << " compressed bytes to output.";
+ return 0;
+ }
+ if (ctx) SHA1_Update(ctx, buffer.data(), have);
+ } while ((strm->avail_in != 0 || strm->avail_out == 0) && ret != Z_STREAM_END);
+
+ actual_target_length += len;
+ return len;
+ };
+
+ if (ApplyBSDiffPatch(src_data, src_len, patch, patch_offset, compression_sink, nullptr) != 0) {
+ return false;
+ }
+
+ if (ret != Z_STREAM_END) {
+ LOG(ERROR) << "ret is expected to be Z_STREAM_END, but it's " << ret;
+ return false;
+ }
+
+ if (expected_target_length != actual_target_length) {
+ LOG(ERROR) << "target length is expected to be " << expected_target_length << ", but it's "
+ << actual_target_length;
+ return false;
+ }
+ LOG(DEBUG) << "bspatch writes " << total_written << " bytes in total to streaming output.";
+
+ return true;
+}
+
int ApplyImagePatch(const unsigned char* old_data, size_t old_size, const unsigned char* patch_data,
size_t patch_size, SinkFn sink) {
Value patch(VAL_BLOB, std::string(reinterpret_cast<const char*>(patch_data), patch_size));
@@ -137,12 +219,6 @@
size_t src_len = static_cast<size_t>(Read8(deflate_header + 8));
size_t patch_offset = static_cast<size_t>(Read8(deflate_header + 16));
size_t expanded_len = static_cast<size_t>(Read8(deflate_header + 24));
- size_t target_len = static_cast<size_t>(Read8(deflate_header + 32));
- int level = Read4(deflate_header + 40);
- int method = Read4(deflate_header + 44);
- int windowBits = Read4(deflate_header + 48);
- int memLevel = Read4(deflate_header + 52);
- int strategy = Read4(deflate_header + 56);
if (src_start + src_len > old_size) {
printf("source data too short\n");
@@ -199,60 +275,12 @@
}
}
- // Next, apply the bsdiff patch (in memory) to the uncompressed data.
- std::vector<uint8_t> uncompressed_target_data;
- // TODO: replace the custom sink function passed into ApplyBSDiffPatch so that it wraps the
- // given sink function to stream output to save memory.
- if (ApplyBSDiffPatch(expanded_source.data(), expanded_len, patch, patch_offset,
- [&uncompressed_target_data](const uint8_t* data, size_t len) {
- uncompressed_target_data.insert(uncompressed_target_data.end(), data, data + len);
- return len;
- }, nullptr) != 0) {
- return -1;
- }
- if (uncompressed_target_data.size() != target_len) {
- printf("expected target len to be %zu, but it's %zu\n", target_len,
- uncompressed_target_data.size());
+ if (!ApplyBSDiffPatchAndStreamOutput(expanded_source.data(), expanded_len, patch,
+ patch_offset, deflate_header, sink, ctx)) {
+ LOG(ERROR) << "Fail to apply streaming bspatch.";
return -1;
}
- // Now compress the target data and append it to the output.
-
- // we're done with the expanded_source data buffer, so we'll
- // reuse that memory to receive the output of deflate.
- if (expanded_source.size() < 32768U) {
- expanded_source.resize(32768U);
- }
-
- {
- std::vector<unsigned char>& temp_data = expanded_source;
-
- // now the deflate stream
- z_stream strm;
- strm.zalloc = Z_NULL;
- strm.zfree = Z_NULL;
- strm.opaque = Z_NULL;
- strm.avail_in = uncompressed_target_data.size();
- strm.next_in = uncompressed_target_data.data();
- int ret = deflateInit2(&strm, level, method, windowBits, memLevel, strategy);
- if (ret != Z_OK) {
- printf("failed to init uncompressed data deflation: %d\n", ret);
- return -1;
- }
- do {
- strm.avail_out = temp_data.size();
- strm.next_out = temp_data.data();
- ret = deflate(&strm, Z_FINISH);
- size_t have = temp_data.size() - strm.avail_out;
-
- if (sink(temp_data.data(), have) != have) {
- printf("failed to write %zd compressed bytes to output\n", have);
- return -1;
- }
- if (ctx) SHA1_Update(ctx, temp_data.data(), have);
- } while (ret != Z_STREAM_END);
- deflateEnd(&strm);
- }
} else {
printf("patch chunk %d is unknown type %d\n", i, type);
return -1;
diff --git a/error_code.h b/error_code.h
index 0e79c87..9fe047c 100644
--- a/error_code.h
+++ b/error_code.h
@@ -44,6 +44,7 @@
kTune2FsFailure,
kRebootFailure,
kPackageExtractFileFailure,
+ kPatchApplicationFailure,
kVendorFailure = 200
};
diff --git a/install.cpp b/install.cpp
index a1f2e4f..db4ba93 100644
--- a/install.cpp
+++ b/install.cpp
@@ -27,6 +27,7 @@
#include <unistd.h>
#include <algorithm>
+#include <atomic>
#include <chrono>
#include <condition_variable>
#include <functional>
@@ -294,11 +295,12 @@
}
#endif // !AB_OTA_UPDATER
-static void log_max_temperature(int* max_temperature) {
+static void log_max_temperature(int* max_temperature, const std::atomic<bool>& logger_finished) {
CHECK(max_temperature != nullptr);
std::mutex mtx;
std::unique_lock<std::mutex> lck(mtx);
- while (finish_log_temperature.wait_for(lck, 20s) == std::cv_status::timeout) {
+ while (!logger_finished.load() &&
+ finish_log_temperature.wait_for(lck, 20s) == std::cv_status::timeout) {
*max_temperature = std::max(*max_temperature, GetMaxValueFromThermalZone());
}
}
@@ -403,7 +405,8 @@
}
close(pipefd[1]);
- std::thread temperature_logger(log_max_temperature, max_temperature);
+ std::atomic<bool> logger_finished(false);
+ std::thread temperature_logger(log_max_temperature, max_temperature, std::ref(logger_finished));
*wipe_cache = false;
bool retry_update = false;
@@ -467,6 +470,7 @@
int status;
waitpid(pid, &status, 0);
+ logger_finished.store(true);
finish_log_temperature.notify_one();
temperature_logger.join();
diff --git a/otautil/Android.bp b/otautil/Android.bp
index 0b23143..a2eaa04 100644
--- a/otautil/Android.bp
+++ b/otautil/Android.bp
@@ -18,7 +18,6 @@
srcs: [
"SysUtil.cpp",
"DirUtil.cpp",
- "ZipUtil.cpp",
"ThermalUtil.cpp",
],
diff --git a/otautil/ZipUtil.cpp b/otautil/ZipUtil.cpp
deleted file mode 100644
index 9cc97e4..0000000
--- a/otautil/ZipUtil.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * 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 "ZipUtil.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <utime.h>
-
-#include <string>
-
-#include <android-base/logging.h>
-#include <android-base/unique_fd.h>
-#include <selinux/label.h>
-#include <selinux/selinux.h>
-#include <ziparchive/zip_archive.h>
-
-#include "DirUtil.h"
-
-static constexpr mode_t UNZIP_DIRMODE = 0755;
-static constexpr mode_t UNZIP_FILEMODE = 0644;
-
-bool ExtractPackageRecursive(ZipArchiveHandle zip, const std::string& zip_path,
- const std::string& dest_path, const struct utimbuf* timestamp,
- struct selabel_handle* sehnd) {
- if (!zip_path.empty() && zip_path[0] == '/') {
- LOG(ERROR) << "ExtractPackageRecursive(): zip_path must be a relative path " << zip_path;
- return false;
- }
- if (dest_path.empty() || dest_path[0] != '/') {
- LOG(ERROR) << "ExtractPackageRecursive(): dest_path must be an absolute path " << dest_path;
- return false;
- }
-
- void* cookie;
- std::string target_dir(dest_path);
- if (dest_path.back() != '/') {
- target_dir += '/';
- }
- std::string prefix_path(zip_path);
- if (!zip_path.empty() && zip_path.back() != '/') {
- prefix_path += '/';
- }
- const ZipString zip_prefix(prefix_path.c_str());
-
- int ret = StartIteration(zip, &cookie, &zip_prefix, nullptr);
- if (ret != 0) {
- LOG(ERROR) << "failed to start iterating zip entries.";
- return false;
- }
-
- std::unique_ptr<void, decltype(&EndIteration)> guard(cookie, EndIteration);
- ZipEntry entry;
- ZipString name;
- int extractCount = 0;
- while (Next(cookie, &entry, &name) == 0) {
- std::string entry_name(name.name, name.name + name.name_length);
- CHECK_LE(prefix_path.size(), entry_name.size());
- std::string path = target_dir + entry_name.substr(prefix_path.size());
- // Skip dir.
- if (path.back() == '/') {
- continue;
- }
-
- if (dirCreateHierarchy(path.c_str(), UNZIP_DIRMODE, timestamp, true, sehnd) != 0) {
- LOG(ERROR) << "failed to create dir for " << path;
- return false;
- }
-
- char *secontext = NULL;
- if (sehnd) {
- selabel_lookup(sehnd, &secontext, path.c_str(), UNZIP_FILEMODE);
- setfscreatecon(secontext);
- }
- android::base::unique_fd fd(open(path.c_str(), O_CREAT|O_WRONLY|O_TRUNC, UNZIP_FILEMODE));
- if (fd == -1) {
- PLOG(ERROR) << "Can't create target file \"" << path << "\"";
- return false;
- }
- if (secontext) {
- freecon(secontext);
- setfscreatecon(NULL);
- }
-
- int err = ExtractEntryToFile(zip, &entry, fd);
- if (err != 0) {
- LOG(ERROR) << "Error extracting \"" << path << "\" : " << ErrorCodeString(err);
- return false;
- }
-
- if (fsync(fd) != 0) {
- PLOG(ERROR) << "Error syncing file descriptor when extracting \"" << path << "\"";
- return false;
- }
-
- if (timestamp != nullptr && utime(path.c_str(), timestamp)) {
- PLOG(ERROR) << "Error touching \"" << path << "\"";
- return false;
- }
-
- LOG(INFO) << "Extracted file \"" << path << "\"";
- ++extractCount;
- }
-
- LOG(INFO) << "Extracted " << extractCount << " file(s)";
- return true;
-}
diff --git a/otautil/ZipUtil.h b/otautil/ZipUtil.h
deleted file mode 100644
index cda405c..0000000
--- a/otautil/ZipUtil.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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 _OTAUTIL_ZIPUTIL_H
-#define _OTAUTIL_ZIPUTIL_H
-
-#include <utime.h>
-
-#include <string>
-
-#include <selinux/label.h>
-#include <ziparchive/zip_archive.h>
-
-/*
- * Inflate all files under zip_path to the directory specified by
- * dest_path, which must exist and be a writable directory. The zip_path
- * is allowed to be an empty string, in which case the whole package
- * will be extracted.
- *
- * Directory entries are not extracted.
- *
- * The immediate children of zip_path will become the immediate
- * children of dest_path; e.g., if the archive contains the entries
- *
- * a/b/c/one
- * a/b/c/two
- * a/b/c/d/three
- *
- * and ExtractPackageRecursive(a, "a/b/c", "/tmp", ...) is called, the resulting
- * files will be
- *
- * /tmp/one
- * /tmp/two
- * /tmp/d/three
- *
- * If timestamp is non-NULL, file timestamps will be set accordingly.
- *
- * Returns true on success, false on failure.
- */
-bool ExtractPackageRecursive(ZipArchiveHandle zip, const std::string& zip_path,
- const std::string& dest_path, const struct utimbuf* timestamp,
- struct selabel_handle* sehnd);
-
-#endif // _OTAUTIL_ZIPUTIL_H
diff --git a/recovery.cpp b/recovery.cpp
index dfae7f0..122b89d 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -112,8 +112,9 @@
static const char *TEMPORARY_INSTALL_FILE = "/tmp/last_install";
static const char *LAST_KMSG_FILE = "/cache/recovery/last_kmsg";
static const char *LAST_LOG_FILE = "/cache/recovery/last_log";
-// We will try to apply the update package 5 times at most in case of an I/O error.
-static const int EIO_RETRY_COUNT = 4;
+// We will try to apply the update package 5 times at most in case of an I/O error or
+// bspatch | imgpatch error.
+static const int RETRY_LIMIT = 4;
static const int BATTERY_READ_TIMEOUT_IN_SEC = 10;
// GmsCore enters recovery mode to install package when having enough battery
// percentage. Normally, the threshold is 40% without charger and 20% with charger.
@@ -1530,9 +1531,9 @@
}
if (status != INSTALL_SUCCESS) {
ui->Print("Installation aborted.\n");
- // When I/O error happens, reboot and retry installation EIO_RETRY_COUNT
+ // When I/O error happens, reboot and retry installation RETRY_LIMIT
// times before we abandon this OTA update.
- if (status == INSTALL_RETRY && retry_count < EIO_RETRY_COUNT) {
+ if (status == INSTALL_RETRY && retry_count < RETRY_LIMIT) {
copy_logs();
set_retry_bootloader_message(retry_count, args);
// Print retry count on screen.
diff --git a/screen_ui.cpp b/screen_ui.cpp
index bb2772d..61ef591 100644
--- a/screen_ui.cpp
+++ b/screen_ui.cpp
@@ -256,6 +256,10 @@
*y += 4;
}
+void ScreenRecoveryUI::DrawHighlightBar(int x, int y, int width, int height) const {
+ gr_fill(x, y, x + width, y + height);
+}
+
void ScreenRecoveryUI::DrawTextLine(int x, int* y, const char* line, bool bold) const {
gr_text(gr_sys_font(), x, *y, line, bold);
*y += char_height_ + 4;
@@ -310,15 +314,14 @@
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);
+ DrawHighlightBar(0, y - 2, gr_fb_width(), char_height_ + 4);
// Bold white text for the selected item.
SetColor(MENU_SEL_FG);
- gr_text(gr_sys_font(), 4, y, menu_[i], true);
+ DrawTextLine(TEXT_INDENT, &y, menu_[i], true);
SetColor(MENU);
} else {
- gr_text(gr_sys_font(), 4, y, menu_[i], false);
+ DrawTextLine(TEXT_INDENT, &y, menu_[i], false);
}
- y += char_height_ + 4;
}
DrawHorizontalRule(&y);
}
@@ -329,10 +332,11 @@
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_ - log_bottom_offset_;
ty >= y && count < text_rows_;
ty -= char_height_, ++count) {
- gr_text(gr_sys_font(), 0, ty, text_[row], false);
+ int temp_y = ty;
+ DrawTextLine(0, &temp_y, text_[row], false);
--row;
if (row < 0) row = text_rows_ - 1;
}
@@ -453,6 +457,7 @@
gr_font_size(gr_sys_font(), &char_width_, &char_height_);
text_rows_ = gr_fb_height() / char_height_;
text_cols_ = gr_fb_width() / char_width_;
+ log_bottom_offset_ = 0;
return true;
}
diff --git a/screen_ui.h b/screen_ui.h
index a2322c3..bd99254 100644
--- a/screen_ui.h
+++ b/screen_ui.h
@@ -107,6 +107,7 @@
// Log text overlay, displayed when a magic key is pressed.
char** text_;
size_t text_col_, text_row_, text_top_;
+ int log_bottom_offset_;
bool show_text;
bool show_text_ever; // has show_text ever been true?
@@ -165,8 +166,9 @@
virtual int GetProgressBaseline();
virtual int GetTextBaseline();
- void DrawHorizontalRule(int* y);
- void DrawTextLine(int x, int* y, const char* line, bool bold) const;
+ virtual void DrawHorizontalRule(int* y);
+ virtual void DrawHighlightBar(int x, int y, int width, int height) const;
+ virtual void DrawTextLine(int x, int* y, const char* line, bool bold) const;
void DrawTextLines(int x, int* y, const char* const* lines) const;
};
diff --git a/tests/Android.mk b/tests/Android.mk
index 4ee59b5..346873d 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -39,7 +39,6 @@
unit/rangeset_test.cpp \
unit/sysutil_test.cpp \
unit/zip_test.cpp \
- unit/ziputil_test.cpp
LOCAL_C_INCLUDES := bootable/recovery
LOCAL_SHARED_LIBRARIES := liblog
diff --git a/tests/unit/zip_test.cpp b/tests/unit/zip_test.cpp
index df4e38c..8276685 100644
--- a/tests/unit/zip_test.cpp
+++ b/tests/unit/zip_test.cpp
@@ -24,47 +24,10 @@
#include <android-base/test_utils.h>
#include <gtest/gtest.h>
#include <otautil/SysUtil.h>
-#include <otautil/ZipUtil.h>
#include <ziparchive/zip_archive.h>
#include "common/test_constants.h"
-TEST(ZipTest, ExtractPackageRecursive) {
- std::string zip_path = from_testdata_base("ziptest_valid.zip");
- ZipArchiveHandle handle;
- ASSERT_EQ(0, OpenArchive(zip_path.c_str(), &handle));
-
- // Extract the whole package into a temp directory.
- TemporaryDir td;
- ASSERT_NE(nullptr, td.path);
- ExtractPackageRecursive(handle, "", td.path, nullptr, nullptr);
-
- // Make sure all the files are extracted correctly.
- std::string path(td.path);
- ASSERT_EQ(0, access((path + "/a.txt").c_str(), F_OK));
- ASSERT_EQ(0, access((path + "/b.txt").c_str(), F_OK));
- ASSERT_EQ(0, access((path + "/b/c.txt").c_str(), F_OK));
- ASSERT_EQ(0, access((path + "/b/d.txt").c_str(), F_OK));
-
- // The content of the file is the same as expected.
- std::string content1;
- ASSERT_TRUE(android::base::ReadFileToString(path + "/a.txt", &content1));
- ASSERT_EQ(kATxtContents, content1);
-
- std::string content2;
- ASSERT_TRUE(android::base::ReadFileToString(path + "/b/d.txt", &content2));
- ASSERT_EQ(kDTxtContents, content2);
-
- CloseArchive(handle);
-
- // Clean up.
- ASSERT_EQ(0, unlink((path + "/a.txt").c_str()));
- ASSERT_EQ(0, unlink((path + "/b.txt").c_str()));
- ASSERT_EQ(0, unlink((path + "/b/c.txt").c_str()));
- ASSERT_EQ(0, unlink((path + "/b/d.txt").c_str()));
- ASSERT_EQ(0, rmdir((path + "/b").c_str()));
-}
-
TEST(ZipTest, OpenFromMemory) {
std::string zip_path = from_testdata_base("ziptest_dummy-update.zip");
MemMapping map;
diff --git a/tests/unit/ziputil_test.cpp b/tests/unit/ziputil_test.cpp
deleted file mode 100644
index 14e5416..0000000
--- a/tests/unit/ziputil_test.cpp
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright 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 <sys/stat.h>
-#include <unistd.h>
-
-#include <string>
-
-#include <android-base/file.h>
-#include <android-base/test_utils.h>
-#include <gtest/gtest.h>
-#include <otautil/ZipUtil.h>
-#include <ziparchive/zip_archive.h>
-
-#include "common/test_constants.h"
-
-TEST(ZipUtilTest, invalid_args) {
- std::string zip_path = from_testdata_base("ziptest_valid.zip");
- ZipArchiveHandle handle;
- ASSERT_EQ(0, OpenArchive(zip_path.c_str(), &handle));
-
- // zip_path must be a relative path.
- ASSERT_FALSE(ExtractPackageRecursive(handle, "/a/b", "/tmp", nullptr, nullptr));
-
- // dest_path must be an absolute path.
- ASSERT_FALSE(ExtractPackageRecursive(handle, "a/b", "tmp", nullptr, nullptr));
- ASSERT_FALSE(ExtractPackageRecursive(handle, "a/b", "", nullptr, nullptr));
-
- CloseArchive(handle);
-}
-
-TEST(ZipUtilTest, extract_all) {
- std::string zip_path = from_testdata_base("ziptest_valid.zip");
- ZipArchiveHandle handle;
- ASSERT_EQ(0, OpenArchive(zip_path.c_str(), &handle));
-
- // Extract the whole package into a temp directory.
- TemporaryDir td;
- ExtractPackageRecursive(handle, "", td.path, nullptr, nullptr);
-
- // Make sure all the files are extracted correctly.
- std::string path(td.path);
- ASSERT_EQ(0, access((path + "/a.txt").c_str(), F_OK));
- ASSERT_EQ(0, access((path + "/b.txt").c_str(), F_OK));
- ASSERT_EQ(0, access((path + "/b/c.txt").c_str(), F_OK));
- ASSERT_EQ(0, access((path + "/b/d.txt").c_str(), F_OK));
-
- // The content of the file is the same as expected.
- std::string content1;
- ASSERT_TRUE(android::base::ReadFileToString(path + "/a.txt", &content1));
- ASSERT_EQ(kATxtContents, content1);
-
- std::string content2;
- ASSERT_TRUE(android::base::ReadFileToString(path + "/b/d.txt", &content2));
- ASSERT_EQ(kDTxtContents, content2);
-
- // Clean up the temp files under td.
- ASSERT_EQ(0, unlink((path + "/a.txt").c_str()));
- ASSERT_EQ(0, unlink((path + "/b.txt").c_str()));
- ASSERT_EQ(0, unlink((path + "/b/c.txt").c_str()));
- ASSERT_EQ(0, unlink((path + "/b/d.txt").c_str()));
- ASSERT_EQ(0, rmdir((path + "/b").c_str()));
-
- CloseArchive(handle);
-}
-
-TEST(ZipUtilTest, extract_prefix_with_slash) {
- std::string zip_path = from_testdata_base("ziptest_valid.zip");
- ZipArchiveHandle handle;
- ASSERT_EQ(0, OpenArchive(zip_path.c_str(), &handle));
-
- // Extract all the entries starting with "b/".
- TemporaryDir td;
- ExtractPackageRecursive(handle, "b/", td.path, nullptr, nullptr);
-
- // Make sure all the files with "b/" prefix are extracted correctly.
- std::string path(td.path);
- ASSERT_EQ(0, access((path + "/c.txt").c_str(), F_OK));
- ASSERT_EQ(0, access((path + "/d.txt").c_str(), F_OK));
-
- // And the rest are not extracted.
- ASSERT_EQ(-1, access((path + "/a.txt").c_str(), F_OK));
- ASSERT_EQ(ENOENT, errno);
- ASSERT_EQ(-1, access((path + "/b.txt").c_str(), F_OK));
- ASSERT_EQ(ENOENT, errno);
-
- // The content of the file is the same as expected.
- std::string content1;
- ASSERT_TRUE(android::base::ReadFileToString(path + "/c.txt", &content1));
- ASSERT_EQ(kCTxtContents, content1);
-
- std::string content2;
- ASSERT_TRUE(android::base::ReadFileToString(path + "/d.txt", &content2));
- ASSERT_EQ(kDTxtContents, content2);
-
- // Clean up the temp files under td.
- ASSERT_EQ(0, unlink((path + "/c.txt").c_str()));
- ASSERT_EQ(0, unlink((path + "/d.txt").c_str()));
-
- CloseArchive(handle);
-}
-
-TEST(ZipUtilTest, extract_prefix_without_slash) {
- std::string zip_path = from_testdata_base("ziptest_valid.zip");
- ZipArchiveHandle handle;
- ASSERT_EQ(0, OpenArchive(zip_path.c_str(), &handle));
-
- // Extract all the file entries starting with "b/".
- TemporaryDir td;
- ExtractPackageRecursive(handle, "b", td.path, nullptr, nullptr);
-
- // Make sure all the files with "b/" prefix are extracted correctly.
- std::string path(td.path);
- ASSERT_EQ(0, access((path + "/c.txt").c_str(), F_OK));
- ASSERT_EQ(0, access((path + "/d.txt").c_str(), F_OK));
-
- // And the rest are not extracted.
- ASSERT_EQ(-1, access((path + "/a.txt").c_str(), F_OK));
- ASSERT_EQ(ENOENT, errno);
- ASSERT_EQ(-1, access((path + "/b.txt").c_str(), F_OK));
- ASSERT_EQ(ENOENT, errno);
-
- // The content of the file is the same as expected.
- std::string content1;
- ASSERT_TRUE(android::base::ReadFileToString(path + "/c.txt", &content1));
- ASSERT_EQ(kCTxtContents, content1);
-
- std::string content2;
- ASSERT_TRUE(android::base::ReadFileToString(path + "/d.txt", &content2));
- ASSERT_EQ(kDTxtContents, content2);
-
- // Clean up the temp files under td.
- ASSERT_EQ(0, unlink((path + "/c.txt").c_str()));
- ASSERT_EQ(0, unlink((path + "/d.txt").c_str()));
-
- CloseArchive(handle);
-}
-
-TEST(ZipUtilTest, set_timestamp) {
- std::string zip_path = from_testdata_base("ziptest_valid.zip");
- ZipArchiveHandle handle;
- ASSERT_EQ(0, OpenArchive(zip_path.c_str(), &handle));
-
- // Set the timestamp to 8/1/2008.
- constexpr struct utimbuf timestamp = { 1217592000, 1217592000 };
-
- // Extract all the entries starting with "b/".
- TemporaryDir td;
- ExtractPackageRecursive(handle, "b", td.path, ×tamp, nullptr);
-
- // Make sure all the files with "b/" prefix are extracted correctly.
- std::string path(td.path);
- std::string file_c = path + "/c.txt";
- std::string file_d = path + "/d.txt";
- ASSERT_EQ(0, access(file_c.c_str(), F_OK));
- ASSERT_EQ(0, access(file_d.c_str(), F_OK));
-
- // Verify the timestamp.
- timespec time;
- time.tv_sec = 1217592000;
- time.tv_nsec = 0;
-
- struct stat sb;
- ASSERT_EQ(0, stat(file_c.c_str(), &sb)) << strerror(errno);
- ASSERT_EQ(time.tv_sec, static_cast<long>(sb.st_atime));
- ASSERT_EQ(time.tv_sec, static_cast<long>(sb.st_mtime));
-
- ASSERT_EQ(0, stat(file_d.c_str(), &sb)) << strerror(errno);
- ASSERT_EQ(time.tv_sec, static_cast<long>(sb.st_atime));
- ASSERT_EQ(time.tv_sec, static_cast<long>(sb.st_mtime));
-
- // Clean up the temp files under td.
- ASSERT_EQ(0, unlink(file_c.c_str()));
- ASSERT_EQ(0, unlink(file_d.c_str()));
-
- CloseArchive(handle);
-}
diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp
index d5c1704..df366b0 100644
--- a/updater/blockimg.cpp
+++ b/updater/blockimg.cpp
@@ -1213,6 +1213,7 @@
std::placeholders::_2),
nullptr, nullptr) != 0) {
LOG(ERROR) << "Failed to apply image patch.";
+ failure_type = kPatchApplicationFailure;
return -1;
}
} else {
@@ -1221,6 +1222,7 @@
std::placeholders::_2),
nullptr) != 0) {
LOG(ERROR) << "Failed to apply bsdiff patch.";
+ failure_type = kPatchApplicationFailure;
return -1;
}
}
diff --git a/updater/install.cpp b/updater/install.cpp
index c5f9a89..ff79edc 100644
--- a/updater/install.cpp
+++ b/updater/install.cpp
@@ -61,7 +61,6 @@
#include "mounts.h"
#include "ota_io.h"
#include "otautil/DirUtil.h"
-#include "otautil/ZipUtil.h"
#include "print_sha1.h"
#include "tune2fs.h"
#include "updater/updater.h"
@@ -389,36 +388,6 @@
return StringValue(frac_str);
}
-// package_extract_dir(package_dir, dest_dir)
-// Extracts all files from the package underneath package_dir and writes them to the
-// corresponding tree beneath dest_dir. Any existing files are overwritten.
-// Example: package_extract_dir("system", "/system")
-//
-// Note: package_dir needs to be a relative path; dest_dir needs to be an absolute path.
-Value* PackageExtractDirFn(const char* name, State* state,
- const std::vector<std::unique_ptr<Expr>>&argv) {
- if (argv.size() != 2) {
- return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
- argv.size());
- }
-
- std::vector<std::string> args;
- if (!ReadArgs(state, argv, &args)) {
- return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
- }
- const std::string& zip_path = args[0];
- const std::string& dest_path = args[1];
-
- ZipArchiveHandle za = static_cast<UpdaterInfo*>(state->cookie)->package_zip;
-
- // To create a consistent system image, never use the clock for timestamps.
- constexpr struct utimbuf timestamp = { 1217592000, 1217592000 }; // 8/1/2008 default
-
- bool success = ExtractPackageRecursive(za, zip_path, dest_path, ×tamp, sehandle);
-
- return StringValue(success ? "t" : "");
-}
-
// package_extract_file(package_file[, dest_file])
// Extracts a single package_file from the update package and writes it to dest_file,
// overwriting existing files if necessary. Without the dest_file argument, returns the
@@ -1037,7 +1006,6 @@
RegisterFunction("format", FormatFn);
RegisterFunction("show_progress", ShowProgressFn);
RegisterFunction("set_progress", SetProgressFn);
- RegisterFunction("package_extract_dir", PackageExtractDirFn);
RegisterFunction("package_extract_file", PackageExtractFileFn);
RegisterFunction("getprop", GetPropFn);
diff --git a/updater/updater.cpp b/updater/updater.cpp
index 1be8b60..f5ff6df 100644
--- a/updater/updater.cpp
+++ b/updater/updater.cpp
@@ -202,6 +202,10 @@
// Cause code should provide additional information about the abort.
if (state.cause_code != kNoCause) {
fprintf(cmd_pipe, "log cause: %d\n", state.cause_code);
+ if (state.cause_code == kPatchApplicationFailure) {
+ LOG(INFO) << "Patch application failed, retry update.";
+ fprintf(cmd_pipe, "retry_update\n");
+ }
}
if (updater_info.package_zip) {
diff --git a/vr_device.cpp b/vr_device.cpp
new file mode 100644
index 0000000..61e15cb
--- /dev/null
+++ b/vr_device.cpp
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2017 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 "device.h"
+#include "vr_ui.h"
+
+Device* make_device() {
+ return new Device(new VrRecoveryUI);
+}
+
diff --git a/vr_ui.cpp b/vr_ui.cpp
new file mode 100644
index 0000000..b2c65e3
--- /dev/null
+++ b/vr_ui.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2017 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 "vr_ui.h"
+
+#include <minui/minui.h>
+
+VrRecoveryUI::VrRecoveryUI() :
+ x_offset(400),
+ y_offset(400),
+ stereo_offset(100) {
+}
+
+bool VrRecoveryUI::InitTextParams() {
+ if (gr_init() < 0) {
+ return false;
+ }
+
+ gr_font_size(gr_sys_font(), &char_width_, &char_height_);
+ int mid_divide = gr_fb_width() / 2;
+ text_rows_ = (gr_fb_height() - 2 * y_offset) / char_height_;
+ text_cols_ = (mid_divide - x_offset - stereo_offset) / char_width_;
+ log_bottom_offset_ = gr_fb_height() - 2 * y_offset;
+ return true;
+}
+
+void VrRecoveryUI::DrawHorizontalRule(int* y) {
+ SetColor(MENU);
+ *y += 4;
+ gr_fill(0, *y + y_offset, gr_fb_width(), *y + y_offset + 2);
+ *y += 4;
+}
+
+void VrRecoveryUI::DrawHighlightBar(int x, int y, int width, int height) const {
+ gr_fill(x, y + y_offset, x + width, y + y_offset + height);
+}
+
+void VrRecoveryUI::DrawTextLine(int x, int* y, const char* line, bool bold) const {
+ int mid_divide = gr_fb_width() / 2;
+ gr_text(gr_sys_font(), x + x_offset + stereo_offset, *y + y_offset, line, bold);
+ gr_text(gr_sys_font(), x + x_offset - stereo_offset + mid_divide, *y + y_offset, line, bold);
+ *y += char_height_ + 4;
+}
diff --git a/vr_ui.h b/vr_ui.h
new file mode 100644
index 0000000..85c5708
--- /dev/null
+++ b/vr_ui.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2017 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 RECOVERY_VR_UI_H
+#define RECOVERY_VR_UI_H
+
+#include "screen_ui.h"
+
+class VrRecoveryUI : public ScreenRecoveryUI {
+ public:
+ VrRecoveryUI();
+
+ protected:
+ // Pixel offsets to move drawing functions to visible range.
+ // Can vary per device depending on screen size and lens distortion.
+ int x_offset, y_offset, stereo_offset;
+
+ bool InitTextParams() override;
+
+ void DrawHorizontalRule(int* y) override;
+ void DrawHighlightBar(int x, int y, int width, int height) const override;
+ void DrawTextLine(int x, int* y, const char* line, bool bold) const override;
+};
+
+#endif // RECOVERY_VR_UI_H