From fd0ace8f6ee5b098c400af03bfe31797994476cd Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Wed, 11 Oct 2017 20:25:36 -0700 Subject: Move stuff from recovery into librecovery. Move most source files into librecovery so they become testable. Only recovery_main.cpp and logging.cpp are built into recovery module, as they perform one-time setup (e.g. setting up logger). Test: `mmma -j bootable/recovery` with aosp_{angler,bullhead,fugu,dragon,marlin}-userdebug Test: recovery_host_test; recovery_unit_test; recovery_component_test; recovery_manual_test Test: Build and boot into recovery image on angler. Change-Id: Ic4444f87a2f123557c71085f81dc2b2764c05ed8 (cherry picked from commit bf4c006d7bc8a4517c82399bbffd9cb09971c0b4) --- Android.mk | 107 +++++++++++++++++++++++++++---------------------------- tests/Android.mk | 16 +++++++-- 2 files changed, 66 insertions(+), 57 deletions(-) diff --git a/Android.mk b/Android.mk index 09feba289..efd7462c2 100644 --- a/Android.mk +++ b/Android.mk @@ -97,12 +97,61 @@ endif include $(BUILD_STATIC_LIBRARY) +# Health HAL dependency +health_hal_static_libraries := \ + android.hardware.health@2.0-impl \ + android.hardware.health@2.0 \ + android.hardware.health@1.0 \ + android.hardware.health@1.0-convert \ + libhealthstoragedefault \ + libhidltransport \ + libhidlbase \ + libhwbinder_noltopgo \ + libvndksupport \ + libbatterymonitor + +librecovery_static_libraries := \ + $(TARGET_RECOVERY_UI_LIB) \ + libbootloader_message \ + libfusesideload \ + libminadbd \ + librecovery_ui \ + libminui \ + libverifier \ + libotautil \ + $(health_hal_static_libraries) \ + libasyncio \ + libcrypto_utils \ + libcrypto \ + libext4_utils \ + libfs_mgr \ + libpng \ + libsparse \ + libvintf_recovery \ + libvintf \ + libhidl-gen-utils \ + libtinyxml2 \ + libziparchive \ + libbase \ + libutils \ + libcutils \ + liblog \ + libselinux \ + libz \ + # librecovery (static library) # =============================== include $(CLEAR_VARS) LOCAL_SRC_FILES := \ - install.cpp + adb_install.cpp \ + fuse_sdcard_provider.cpp \ + install.cpp \ + recovery.cpp \ + roots.cpp \ + +LOCAL_C_INCLUDES := \ + system/vold \ LOCAL_CFLAGS := $(recovery_common_cflags) @@ -113,13 +162,7 @@ endif LOCAL_MODULE := librecovery LOCAL_STATIC_LIBRARIES := \ - libminui \ - libotautil \ - libvintf_recovery \ - libcrypto_utils \ - libcrypto \ - libbase \ - libziparchive \ + $(librecovery_static_libraries) include $(BUILD_STATIC_LIBRARY) @@ -128,12 +171,8 @@ include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_SRC_FILES := \ - adb_install.cpp \ - fuse_sdcard_provider.cpp \ logging.cpp \ - recovery.cpp \ recovery_main.cpp \ - roots.cpp \ LOCAL_MODULE := recovery @@ -147,51 +186,9 @@ LOCAL_USE_CLANG_LLD := false LOCAL_CFLAGS := $(recovery_common_cflags) -LOCAL_C_INCLUDES += \ - system/vold \ - -# Health HAL dependency LOCAL_STATIC_LIBRARIES := \ - android.hardware.health@2.0-impl \ - android.hardware.health@2.0 \ - android.hardware.health@1.0 \ - android.hardware.health@1.0-convert \ - libhealthstoragedefault \ - libhidltransport \ - libhidlbase \ - libhwbinder_noltopgo \ - libvndksupport \ - libbatterymonitor - -LOCAL_STATIC_LIBRARIES += \ librecovery \ - $(TARGET_RECOVERY_UI_LIB) \ - libbootloader_message \ - libfusesideload \ - libminadbd \ - librecovery_ui \ - libminui \ - libverifier \ - libotautil \ - libasyncio \ - libbatterymonitor \ - libcrypto_utils \ - libcrypto \ - libext4_utils \ - libfs_mgr \ - libpng \ - libsparse \ - libvintf_recovery \ - libvintf \ - libhidl-gen-utils \ - libtinyxml2 \ - libziparchive \ - libbase \ - libutils \ - libcutils \ - liblog \ - libselinux \ - libz \ + $(librecovery_static_libraries) LOCAL_HAL_STATIC_LIBRARIES := libhealthd diff --git a/tests/Android.mk b/tests/Android.mk index cdc5b523a..efe46b8ee 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -150,6 +150,18 @@ libupdater_static_libraries := \ libbrotli \ $(tune2fs_static_libraries) +health_hal_static_libraries := \ + android.hardware.health@2.0-impl \ + android.hardware.health@2.0 \ + android.hardware.health@1.0 \ + android.hardware.health@1.0-convert \ + libhealthstoragedefault \ + libhidltransport \ + libhidlbase \ + libhwbinder_noltopgo \ + libvndksupport \ + libbatterymonitor + librecovery_static_libraries := \ librecovery \ $(TARGET_RECOVERY_UI_LIB) \ @@ -160,8 +172,8 @@ librecovery_static_libraries := \ libminui \ libverifier \ libotautil \ + $(health_hal_static_libraries) \ libasyncio \ - libbatterymonitor \ libcrypto_utils \ libcrypto \ libext4_utils \ @@ -174,8 +186,8 @@ librecovery_static_libraries := \ libtinyxml2 \ libziparchive \ libbase \ - libcutils \ libutils \ + libcutils \ liblog \ libselinux \ libz \ -- cgit v1.2.3 From 371fe6e8bc18384f6328edc589ff3a83f0fd04b0 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Wed, 11 Oct 2017 20:25:36 -0700 Subject: Move stuff from recovery into librecovery. Move most source files into librecovery so they become testable. Only recovery_main.cpp and logging.cpp are built into recovery module, as they perform one-time setup (e.g. setting up logger). Test: `mmma -j bootable/recovery` with aosp_{angler,bullhead,fugu,dragon,marlin}-userdebug Test: recovery_host_test; recovery_unit_test; recovery_component_test; recovery_manual_test Test: Build and boot into recovery image on angler. Change-Id: Ic4444f87a2f123557c71085f81dc2b2764c05ed8 Merged-In: Ic4444f87a2f123557c71085f81dc2b2764c05ed8 --- Android.mk | 81 +++++++++++++++++++++++++++----------------------------- tests/Android.mk | 2 +- 2 files changed, 40 insertions(+), 43 deletions(-) diff --git a/Android.mk b/Android.mk index 214d028da..fef5846ac 100644 --- a/Android.mk +++ b/Android.mk @@ -97,12 +97,48 @@ endif include $(BUILD_STATIC_LIBRARY) +librecovery_static_libraries := \ + $(TARGET_RECOVERY_UI_LIB) \ + libbootloader_message \ + libfusesideload \ + libminadbd \ + librecovery_ui \ + libminui \ + libverifier \ + libotautil \ + libasyncio \ + libbatterymonitor \ + libcrypto_utils \ + libcrypto \ + libext4_utils \ + libfs_mgr \ + libpng \ + libsparse \ + libvintf_recovery \ + libvintf \ + libhidl-gen-utils \ + libtinyxml2 \ + libziparchive \ + libbase \ + libutils \ + libcutils \ + liblog \ + libselinux \ + libz \ + # librecovery (static library) # =============================== include $(CLEAR_VARS) LOCAL_SRC_FILES := \ - install.cpp + adb_install.cpp \ + fuse_sdcard_provider.cpp \ + install.cpp \ + recovery.cpp \ + roots.cpp \ + +LOCAL_C_INCLUDES := \ + system/vold \ LOCAL_CFLAGS := $(recovery_common_cflags) @@ -113,13 +149,7 @@ endif LOCAL_MODULE := librecovery LOCAL_STATIC_LIBRARIES := \ - libminui \ - libotautil \ - libvintf_recovery \ - libcrypto_utils \ - libcrypto \ - libbase \ - libziparchive \ + $(librecovery_static_libraries) include $(BUILD_STATIC_LIBRARY) @@ -128,12 +158,8 @@ include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_SRC_FILES := \ - adb_install.cpp \ - fuse_sdcard_provider.cpp \ logging.cpp \ - recovery.cpp \ recovery_main.cpp \ - roots.cpp \ LOCAL_MODULE := recovery @@ -147,38 +173,9 @@ LOCAL_USE_CLANG_LLD := false LOCAL_CFLAGS := $(recovery_common_cflags) -LOCAL_C_INCLUDES += \ - system/vold \ - LOCAL_STATIC_LIBRARIES := \ librecovery \ - $(TARGET_RECOVERY_UI_LIB) \ - libbootloader_message \ - libfusesideload \ - libminadbd \ - librecovery_ui \ - libminui \ - libverifier \ - libotautil \ - libasyncio \ - libbatterymonitor \ - libcrypto_utils \ - libcrypto \ - libext4_utils \ - libfs_mgr \ - libpng \ - libsparse \ - libvintf_recovery \ - libvintf \ - libhidl-gen-utils \ - libtinyxml2 \ - libziparchive \ - libbase \ - libcutils \ - libutils \ - liblog \ - libselinux \ - libz \ + $(librecovery_static_libraries) LOCAL_HAL_STATIC_LIBRARIES := libhealthd diff --git a/tests/Android.mk b/tests/Android.mk index cdc5b523a..853ca273b 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -174,8 +174,8 @@ librecovery_static_libraries := \ libtinyxml2 \ libziparchive \ libbase \ - libcutils \ libutils \ + libcutils \ liblog \ libselinux \ libz \ -- cgit v1.2.3 From b0361ffa3e25ab3e234a5ccaa5587b7dca88de76 Mon Sep 17 00:00:00 2001 From: Zhomart Mukhamejanov Date: Fri, 18 May 2018 10:22:13 -0700 Subject: updater_config: make utils/PayloadSpecs non-static PayloadSpecs has complicated methods, which makes hard to test other dependent classes. Making it non-static allows mocking it, which makes testing other classes easier. Test: manually Test: using JUnit4 Change-Id: I818dc59c6bb0e7d131439d0d41f88d5cd9a451b4 Signed-off-by: Zhomart Mukhamejanov --- .../systemupdatersample/services/PrepareStreamingService.java | 10 ++++++---- .../example/android/systemupdatersample/ui/MainActivity.java | 3 ++- .../example/android/systemupdatersample/util/PayloadSpecs.java | 8 +++----- .../android/systemupdatersample/util/PayloadSpecsTest.java | 9 ++++++--- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/updater_sample/src/com/example/android/systemupdatersample/services/PrepareStreamingService.java b/updater_sample/src/com/example/android/systemupdatersample/services/PrepareStreamingService.java index 222bb0a58..ac6e223e3 100644 --- a/updater_sample/src/com/example/android/systemupdatersample/services/PrepareStreamingService.java +++ b/updater_sample/src/com/example/android/systemupdatersample/services/PrepareStreamingService.java @@ -116,6 +116,8 @@ public class PrepareStreamingService extends IntentService { PackageFiles.PAYLOAD_PROPERTIES_FILE_NAME ); + private final PayloadSpecs mPayloadSpecs = new PayloadSpecs(); + @Override protected void onHandleIntent(Intent intent) { Log.d(TAG, "On handle intent is called"); @@ -137,7 +139,7 @@ public class PrepareStreamingService extends IntentService { * 3. Checks OTA package compatibility with the device. * 4. Constructs {@link PayloadSpec} for streaming update. */ - private static PayloadSpec execute(UpdateConfig config) + private PayloadSpec execute(UpdateConfig config) throws IOException, PreparationFailedException { downloadPreStreamingFiles(config, OTA_PACKAGE_DIR); @@ -164,7 +166,7 @@ public class PrepareStreamingService extends IntentService { } } - return PayloadSpecs.forStreaming(config.getUrl(), + return mPayloadSpecs.forStreaming(config.getUrl(), payloadBinary.get().getOffset(), payloadBinary.get().getSize(), Paths.get(OTA_PACKAGE_DIR, PAYLOAD_PROPERTIES_FILE_NAME).toFile()); @@ -176,7 +178,7 @@ public class PrepareStreamingService extends IntentService { * in directory {@code dir}. * @throws IOException when can't download a file */ - private static void downloadPreStreamingFiles(UpdateConfig config, String dir) + private void downloadPreStreamingFiles(UpdateConfig config, String dir) throws IOException { Log.d(TAG, "Deleting existing files from " + dir); for (String file : PRE_STREAMING_FILES_SET) { @@ -200,7 +202,7 @@ public class PrepareStreamingService extends IntentService { * @param file physical location of {@link PackageFiles#COMPATIBILITY_ZIP_FILE_NAME} * @return true if OTA package is compatible with this device */ - private static boolean verifyPackageCompatibility(File file) { + private boolean verifyPackageCompatibility(File file) { try { return RecoverySystem.verifyPackageCompatibility(file); } catch (IOException e) { diff --git a/updater_sample/src/com/example/android/systemupdatersample/ui/MainActivity.java b/updater_sample/src/com/example/android/systemupdatersample/ui/MainActivity.java index c5a7f9556..9bab1319d 100644 --- a/updater_sample/src/com/example/android/systemupdatersample/ui/MainActivity.java +++ b/updater_sample/src/com/example/android/systemupdatersample/ui/MainActivity.java @@ -77,6 +77,7 @@ public class MainActivity extends Activity { new AtomicInteger(UpdateEngine.UpdateStatusConstants.IDLE); private PayloadSpec mLastPayloadSpec; private AtomicBoolean mManualSwitchSlotRequired = new AtomicBoolean(true); + private final PayloadSpecs mPayloadSpecs = new PayloadSpecs(); /** * Listen to {@code update_engine} events. @@ -338,7 +339,7 @@ public class MainActivity extends Activity { if (config.getInstallType() == UpdateConfig.AB_INSTALL_TYPE_NON_STREAMING) { PayloadSpec payload; try { - payload = PayloadSpecs.forNonStreaming(config.getUpdatePackageFile()); + payload = mPayloadSpecs.forNonStreaming(config.getUpdatePackageFile()); } catch (IOException e) { Log.e(TAG, "Error creating payload spec", e); Toast.makeText(this, "Error creating payload spec", Toast.LENGTH_LONG) diff --git a/updater_sample/src/com/example/android/systemupdatersample/util/PayloadSpecs.java b/updater_sample/src/com/example/android/systemupdatersample/util/PayloadSpecs.java index 4db448a31..b98b97c37 100644 --- a/updater_sample/src/com/example/android/systemupdatersample/util/PayloadSpecs.java +++ b/updater_sample/src/com/example/android/systemupdatersample/util/PayloadSpecs.java @@ -43,7 +43,7 @@ public final class PayloadSpecs { * zip file. So we enumerate the entries to identify the offset of the payload file. * http://developer.android.com/reference/java/util/zip/ZipFile.html#entries() */ - public static PayloadSpec forNonStreaming(File packageFile) throws IOException { + public PayloadSpec forNonStreaming(File packageFile) throws IOException { boolean payloadFound = false; long payloadOffset = 0; long payloadSize = 0; @@ -100,7 +100,7 @@ public final class PayloadSpecs { /** * Creates a {@link PayloadSpec} for streaming update. */ - public static PayloadSpec forStreaming(String updateUrl, + public PayloadSpec forStreaming(String updateUrl, long offset, long size, File propertiesFile) throws IOException { @@ -115,7 +115,7 @@ public final class PayloadSpecs { /** * Converts an {@link PayloadSpec} to a string. */ - public static String toString(PayloadSpec payloadSpec) { + public String specToString(PayloadSpec payloadSpec) { return ""; } - private PayloadSpecs() {} - } diff --git a/updater_sample/tests/src/com/example/android/systemupdatersample/util/PayloadSpecsTest.java b/updater_sample/tests/src/com/example/android/systemupdatersample/util/PayloadSpecsTest.java index d9e54652f..3ba84c116 100644 --- a/updater_sample/tests/src/com/example/android/systemupdatersample/util/PayloadSpecsTest.java +++ b/updater_sample/tests/src/com/example/android/systemupdatersample/util/PayloadSpecsTest.java @@ -55,6 +55,8 @@ public class PayloadSpecsTest { private Context mTargetContext; private Context mTestContext; + private PayloadSpecs mPayloadSpecs; + @Rule public final ExpectedException thrown = ExpectedException.none(); @@ -64,6 +66,7 @@ public class PayloadSpecsTest { mTestContext = InstrumentationRegistry.getContext(); mTestDir = mTargetContext.getFilesDir(); + mPayloadSpecs = new PayloadSpecs(); } @Test @@ -75,7 +78,7 @@ public class PayloadSpecsTest { java.nio.file.Files.deleteIfExists(packageFile.toPath()); java.nio.file.Files.copy(mTestContext.getResources().openRawResource(R.raw.ota_002_package), packageFile.toPath()); - PayloadSpec spec = PayloadSpecs.forNonStreaming(packageFile); + PayloadSpec spec = mPayloadSpecs.forNonStreaming(packageFile); assertEquals("correct url", "file://" + packageFile.getAbsolutePath(), spec.getUrl()); assertEquals("correct payload offset", @@ -90,7 +93,7 @@ public class PayloadSpecsTest { @Test public void forNonStreaming_IOException() throws Exception { thrown.expect(IOException.class); - PayloadSpecs.forNonStreaming(new File("/fake/news.zip")); + mPayloadSpecs.forNonStreaming(new File("/fake/news.zip")); } @Test @@ -100,7 +103,7 @@ public class PayloadSpecsTest { long size = 200; File propertiesFile = createMockPropertiesFile(); - PayloadSpec spec = PayloadSpecs.forStreaming(url, offset, size, propertiesFile); + PayloadSpec spec = mPayloadSpecs.forStreaming(url, offset, size, propertiesFile); assertEquals("same url", url, spec.getUrl()); assertEquals("same offset", offset, spec.getOffset()); assertEquals("same size", size, spec.getSize()); -- cgit v1.2.3 From ab20706a842d14ed1b2fbe0c52fa6851a41eeb94 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Mon, 21 May 2018 14:48:49 -0700 Subject: updater: Clean up the header lines computation. It no longer needs to be conditional, as we've removed the support for BBOTA v1/v2. Test: mmma bootable/recovery Change-Id: I881de8afa38cc5b41b48e6d48d85170699ea5eb4 --- updater/blockimg.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp index 236644e7f..48d1f4e10 100644 --- a/updater/blockimg.cpp +++ b/updater/blockimg.cpp @@ -1666,7 +1666,6 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, return StringValue("t"); } - size_t start = 2; if (lines.size() < 4) { ErrorAbort(state, kArgsParsingFailure, "too few lines in the transfer list [%zu]", lines.size()); @@ -1708,8 +1707,6 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, saved_last_command_index = -1; } - start += 2; - // Build a map of the available commands std::unordered_map cmd_map; for (size_t i = 0; i < cmdcount; ++i) { @@ -1722,17 +1719,18 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int rc = -1; + static constexpr size_t kTransferListHeaderLines = 4; // Subsequent lines are all individual transfer commands - for (size_t i = start; i < lines.size(); i++) { + for (size_t i = kTransferListHeaderLines; i < lines.size(); i++) { const std::string& line = lines[i]; if (line.empty()) continue; params.tokens = android::base::Split(line, " "); params.cpos = 0; - if (i - start > std::numeric_limits::max()) { + if (i - kTransferListHeaderLines > std::numeric_limits::max()) { params.cmdindex = -1; } else { - params.cmdindex = i - start; + params.cmdindex = i - kTransferListHeaderLines; } params.cmdname = params.tokens[params.cpos++].c_str(); params.cmdline = line.c_str(); -- cgit v1.2.3 From 26efb0ae3adff89513e7de4bb886bf6aeec99202 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Mon, 21 May 2018 14:59:55 -0700 Subject: updater: Use a bool to indicate if allowed to skip a command. This avoids the signedness issue, and makes the code more readable. Test: mmma bootable/recovery Test: Run recovery_component_test. Change-Id: I01c3a0357887cfd7c9d4aba4239ef650cfa18388 --- updater/blockimg.cpp | 39 +++++++++++++++++---------------------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp index 48d1f4e10..4a70b98a1 100644 --- a/updater/blockimg.cpp +++ b/updater/blockimg.cpp @@ -82,7 +82,7 @@ static void DeleteLastCommandFile() { // Parse the last command index of the last update and save the result to |last_command_index|. // Return true if we successfully read the index. -static bool ParseLastCommandFile(int* last_command_index) { +static bool ParseLastCommandFile(size_t* last_command_index) { const std::string& last_command_file = Paths::Get().last_command_file(); android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(last_command_file.c_str(), O_RDONLY))); if (fd == -1) { @@ -133,7 +133,7 @@ static bool FsyncDir(const std::string& dirname) { } // Update the last executed command index in the last_command_file. -static bool UpdateLastCommandIndex(int command_index, const std::string& command_string) { +static bool UpdateLastCommandIndex(size_t command_index, const std::string& command_string) { const std::string& last_command_file = Paths::Get().last_command_file(); std::string last_command_tmp = last_command_file + ".tmp"; std::string content = std::to_string(command_index) + "\n" + command_string; @@ -546,7 +546,6 @@ static int WriteBlocks(const RangeSet& tgt, const std::vector& buffer, struct CommandParameters { std::vector tokens; size_t cpos; - int cmdindex; const char* cmdname; const char* cmdline; std::string freestash; @@ -1690,8 +1689,8 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, params.createdstash = res; - // When performing an update, save the index and cmdline of the current command into - // the last_command_file. + // When performing an update, save the index and cmdline of the current command into the + // last_command_file. // Upon resuming an update, read the saved index first; then // 1. In verification mode, check if the 'move' or 'diff' commands before the saved index has // the expected target blocks already. If not, these commands cannot be skipped and we need @@ -1700,11 +1699,12 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, // 2. In update mode, skip all commands before the saved index. Therefore, we can avoid deleting // stashes with duplicate id unintentionally (b/69858743); and also speed up the update. // If an update succeeds or is unresumable, delete the last_command_file. - int saved_last_command_index; + bool skip_executed_command = true; + size_t saved_last_command_index; if (!ParseLastCommandFile(&saved_last_command_index)) { DeleteLastCommandFile(); - // We failed to parse the last command, set it explicitly to -1. - saved_last_command_index = -1; + // We failed to parse the last command. Disallow skipping executed commands. + skip_executed_command = false; } // Build a map of the available commands @@ -1725,13 +1725,9 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, const std::string& line = lines[i]; if (line.empty()) continue; + size_t cmdindex = i - kTransferListHeaderLines; params.tokens = android::base::Split(line, " "); params.cpos = 0; - if (i - kTransferListHeaderLines > std::numeric_limits::max()) { - params.cmdindex = -1; - } else { - params.cmdindex = i - kTransferListHeaderLines; - } params.cmdname = params.tokens[params.cpos++].c_str(); params.cmdline = line.c_str(); params.target_verified = false; @@ -1754,9 +1750,9 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, // Skip all commands before the saved last command index when resuming an update, except for // "new" command. Because new commands read in the data sequentially. - if (params.canwrite && params.cmdindex != -1 && params.cmdindex <= saved_last_command_index && + if (params.canwrite && skip_executed_command && cmdindex <= saved_last_command_index && cmdname != "new") { - LOG(INFO) << "Skipping already executed command: " << params.cmdindex + LOG(INFO) << "Skipping already executed command: " << cmdindex << ", last executed command for previous update: " << saved_last_command_index; continue; } @@ -1766,17 +1762,16 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, goto pbiudone; } - // In verify mode, check if the commands before the saved last_command_index have been - // executed correctly. If some target blocks have unexpected contents, delete the last command - // file so that we will resume the update from the first command in the transfer list. - if (!params.canwrite && saved_last_command_index != -1 && params.cmdindex != -1 && - params.cmdindex <= saved_last_command_index) { + // In verify mode, check if the commands before the saved last_command_index have been executed + // correctly. If some target blocks have unexpected contents, delete the last command file so + // that we will resume the update from the first command in the transfer list. + if (!params.canwrite && skip_executed_command && cmdindex <= saved_last_command_index) { // TODO(xunchang) check that the cmdline of the saved index is correct. if ((cmdname == "move" || cmdname == "bsdiff" || cmdname == "imgdiff") && !params.target_verified) { LOG(WARNING) << "Previously executed command " << saved_last_command_index << ": " << params.cmdline << " doesn't produce expected target blocks."; - saved_last_command_index = -1; + skip_executed_command = false; DeleteLastCommandFile(); } } @@ -1787,7 +1782,7 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, goto pbiudone; } - if (!UpdateLastCommandIndex(params.cmdindex, params.cmdline)) { + if (!UpdateLastCommandIndex(cmdindex, params.cmdline)) { LOG(WARNING) << "Failed to update the last command file."; } -- cgit v1.2.3 From 0e577ee424acf7a5e6600560d702ab3c8020a29f Mon Sep 17 00:00:00 2001 From: Jerry Zhang Date: Mon, 7 May 2018 11:21:10 -0700 Subject: recovery: Add ability to set title lines Add the ability to change the contents of the title lines, displayed at the top of the screen. Once set, the same lines are displayed for all menus until changed again. Test: Recovery works Bug: 78793464 Change-Id: I7ef5594b0d76dbbd2e01ad7508863af1270b2a2a --- recovery.cpp | 5 +++++ screen_ui.cpp | 12 +++++++----- screen_ui.h | 3 +++ stub_ui.h | 2 ++ ui.h | 2 ++ 5 files changed, 19 insertions(+), 5 deletions(-) diff --git a/recovery.cpp b/recovery.cpp index 21f633011..56b2567d1 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -1063,6 +1063,11 @@ Device::BuiltinAction start_recovery(Device* device, const std::vectorSetStage(st_cur, st_max); } + std::vector title_lines = + android::base::Split(android::base::GetProperty("ro.bootimage.build.fingerprint", ""), ":"); + title_lines.insert(std::begin(title_lines), "Android Recovery"); + ui->SetTitle(title_lines); + device->StartRecovery(); printf("Command:"); diff --git a/screen_ui.cpp b/screen_ui.cpp index fd7a1bea5..f1b38781a 100644 --- a/screen_ui.cpp +++ b/screen_ui.cpp @@ -496,6 +496,10 @@ int ScreenRecoveryUI::DrawWrappedTextLines(int x, int y, return offset; } +void ScreenRecoveryUI::SetTitle(const std::vector& lines) { + title_lines_ = lines; +} + // Redraws everything on the screen. Does not flip pages. Should only be called with updateMutex // locked. void ScreenRecoveryUI::draw_screen_locked() { @@ -529,11 +533,9 @@ void ScreenRecoveryUI::draw_menu_and_text_buffer_locked( int x = kMarginWidth + kMenuIndent; SetColor(INFO); - y += DrawTextLine(x, y, "Android Recovery", true); - std::string recovery_fingerprint = - android::base::GetProperty("ro.bootimage.build.fingerprint", ""); - for (const auto& chunk : android::base::Split(recovery_fingerprint, ":")) { - y += DrawTextLine(x, y, chunk, false); + + for (size_t i = 0; i < title_lines_.size(); i++) { + y += DrawTextLine(x, y, title_lines_[i], i == 0); } y += DrawTextLines(x, y, help_message); diff --git a/screen_ui.h b/screen_ui.h index 2d6b621d5..c90a2cd17 100644 --- a/screen_ui.h +++ b/screen_ui.h @@ -141,6 +141,7 @@ class ScreenRecoveryUI : public RecoveryUI { size_t ShowMenu(const std::vector& headers, const std::vector& items, size_t initial_selection, bool menu_only, const std::function& key_handler) override; + void SetTitle(const std::vector& lines) override; void KeyLongPress(int) override; @@ -266,6 +267,8 @@ class ScreenRecoveryUI : public RecoveryUI { bool show_text; bool show_text_ever; // has show_text ever been true? + std::vector title_lines_; + bool scrollable_menu_; std::unique_ptr menu_; diff --git a/stub_ui.h b/stub_ui.h index 67c338e99..a3cf12b05 100644 --- a/stub_ui.h +++ b/stub_ui.h @@ -67,6 +67,8 @@ class StubRecoveryUI : public RecoveryUI { const std::function& /* key_handler */) override { return initial_selection; } + + void SetTitle(const std::vector& /* lines */) override {} }; #endif // RECOVERY_STUB_UI_H diff --git a/ui.h b/ui.h index 39284268d..a74b14f85 100644 --- a/ui.h +++ b/ui.h @@ -134,6 +134,8 @@ class RecoveryUI { // --- menu display --- + virtual void SetTitle(const std::vector& lines) = 0; + // Displays a menu with the given 'headers' and 'items'. The supplied 'key_handler' callback, // which is typically bound to Device::HandleMenuKey(), should return the expected action for the // given key code and menu visibility (e.g. to move the cursor or to select an item). Caller sets -- cgit v1.2.3