diff options
-rw-r--r-- | Android.mk | 107 | ||||
-rw-r--r-- | recovery.cpp | 5 | ||||
-rw-r--r-- | screen_ui.cpp | 12 | ||||
-rw-r--r-- | screen_ui.h | 3 | ||||
-rw-r--r-- | stub_ui.h | 2 | ||||
-rw-r--r-- | tests/Android.mk | 16 | ||||
-rw-r--r-- | ui.h | 2 | ||||
-rw-r--r-- | updater/blockimg.cpp | 45 | ||||
-rw-r--r-- | updater_sample/src/com/example/android/systemupdatersample/services/PrepareStreamingService.java | 10 | ||||
-rw-r--r-- | updater_sample/src/com/example/android/systemupdatersample/ui/MainActivity.java | 3 | ||||
-rw-r--r-- | updater_sample/src/com/example/android/systemupdatersample/util/PayloadSpecs.java | 8 | ||||
-rw-r--r-- | updater_sample/tests/src/com/example/android/systemupdatersample/util/PayloadSpecsTest.java | 9 |
12 files changed, 121 insertions, 101 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/recovery.cpp b/recovery.cpp index ac3e7c633..69b149906 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -1083,6 +1083,11 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri ui->SetStage(st_cur, st_max); } + std::vector<std::string> 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<std::string>& 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<std::string>& headers, const std::vector<std::string>& items, size_t initial_selection, bool menu_only, const std::function<int(int, bool)>& key_handler) override; + void SetTitle(const std::vector<std::string>& 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<std::string> title_lines_; + bool scrollable_menu_; std::unique_ptr<Menu> menu_; @@ -67,6 +67,8 @@ class StubRecoveryUI : public RecoveryUI { const std::function<int(int, bool)>& /* key_handler */) override { return initial_selection; } + + void SetTitle(const std::vector<std::string>& /* lines */) override {} }; #endif // RECOVERY_STUB_UI_H 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 \ @@ -134,6 +134,8 @@ class RecoveryUI { // --- menu display --- + virtual void SetTitle(const std::vector<std::string>& 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 diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp index 236644e7f..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<uint8_t>& buffer, struct CommandParameters { std::vector<std::string> tokens; size_t cpos; - int cmdindex; const char* cmdname; const char* cmdline; std::string freestash; @@ -1666,7 +1665,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()); @@ -1691,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 @@ -1701,15 +1699,14 @@ 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; } - start += 2; - // Build a map of the available commands std::unordered_map<std::string, const Command*> cmd_map; for (size_t i = 0; i < cmdcount; ++i) { @@ -1722,18 +1719,15 @@ 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; + size_t cmdindex = i - kTransferListHeaderLines; params.tokens = android::base::Split(line, " "); params.cpos = 0; - if (i - start > std::numeric_limits<int>::max()) { - params.cmdindex = -1; - } else { - params.cmdindex = i - start; - } params.cmdname = params.tokens[params.cpos++].c_str(); params.cmdline = line.c_str(); params.target_verified = false; @@ -1756,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; } @@ -1768,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(); } } @@ -1789,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."; } 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 "<PayloadSpec url=" + payloadSpec.getUrl() + ", offset=" + payloadSpec.getOffset() + ", size=" + payloadSpec.getSize() @@ -124,6 +124,4 @@ public final class PayloadSpecs { + ">"; } - 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()); |