summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk107
-rw-r--r--recovery.cpp5
-rw-r--r--screen_ui.cpp12
-rw-r--r--screen_ui.h3
-rw-r--r--stub_ui.h2
-rw-r--r--tests/Android.mk16
-rw-r--r--ui.h2
-rw-r--r--updater/blockimg.cpp45
-rw-r--r--updater_sample/src/com/example/android/systemupdatersample/services/PrepareStreamingService.java10
-rw-r--r--updater_sample/src/com/example/android/systemupdatersample/ui/MainActivity.java3
-rw-r--r--updater_sample/src/com/example/android/systemupdatersample/util/PayloadSpecs.java8
-rw-r--r--updater_sample/tests/src/com/example/android/systemupdatersample/util/PayloadSpecsTest.java9
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_;
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<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 \
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<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());