Merge "Recovery image is self-contained"
diff --git a/minui/graphics.cpp b/minui/graphics.cpp
index c1aab41..cc02e9e 100644
--- a/minui/graphics.cpp
+++ b/minui/graphics.cpp
@@ -28,7 +28,7 @@
#include "graphics_fbdev.h"
#include "minui/minui.h"
-static GRFont* gr_font = NULL;
+static GRFont* gr_font = nullptr;
static MinuiBackend* gr_backend = nullptr;
static int overscan_percent = OVERSCAN_PERCENT;
@@ -38,7 +38,8 @@
static uint32_t gr_current = ~0;
static constexpr uint32_t alpha_mask = 0xff000000;
-static GRSurface* gr_draw = NULL;
+// gr_draw is owned by backends.
+static const GRSurface* gr_draw = nullptr;
static GRRotation rotation = ROTATION_NONE;
static bool outside(int x, int y) {
@@ -86,7 +87,7 @@
return (out_r & 0xff) | (out_g & 0xff00) | (out_b & 0xff0000) | (gr_current & 0xff000000);
}
-// increments pixel pointer right, with current rotation.
+// Increments pixel pointer right, with current rotation.
static void incr_x(uint32_t** p, int row_pixels) {
if (rotation % 2) {
*p = *p + (rotation == 1 ? 1 : -1) * row_pixels;
@@ -95,7 +96,7 @@
}
}
-// increments pixel pointer down, with current rotation.
+// Increments pixel pointer down, with current rotation.
static void incr_y(uint32_t** p, int row_pixels) {
if (rotation % 2) {
*p = *p + (rotation == 1 ? -1 : 1);
@@ -104,8 +105,8 @@
}
}
-// returns pixel pointer at given coordinates with rotation adjustment.
-static uint32_t* pixel_at(GRSurface* surf, int x, int y, int row_pixels) {
+// Returns pixel pointer at given coordinates with rotation adjustment.
+static uint32_t* pixel_at(const GRSurface* surf, int x, int y, int row_pixels) {
switch (rotation) {
case ROTATION_NONE:
return reinterpret_cast<uint32_t*>(surf->data) + y * row_pixels + x;
@@ -172,7 +173,7 @@
}
void gr_texticon(int x, int y, GRSurface* icon) {
- if (icon == NULL) return;
+ if (icon == nullptr) return;
if (icon->pixel_bytes != 1) {
printf("gr_texticon: source has wrong format\n");
@@ -243,7 +244,7 @@
}
void gr_blit(GRSurface* source, int sx, int sy, int w, int h, int dx, int dy) {
- if (source == NULL) return;
+ if (source == nullptr) return;
if (gr_draw->pixel_bytes != source->pixel_bytes) {
printf("gr_blit: source has wrong format\n");
@@ -275,8 +276,7 @@
unsigned char* src_p = source->data + sy * source->row_bytes + sx * source->pixel_bytes;
unsigned char* dst_p = gr_draw->data + dy * gr_draw->row_bytes + dx * gr_draw->pixel_bytes;
- int i;
- for (i = 0; i < h; ++i) {
+ for (int i = 0; i < h; ++i) {
memcpy(dst_p, src_p, w * source->pixel_bytes);
src_p += source->row_bytes;
dst_p += gr_draw->row_bytes;
@@ -284,15 +284,15 @@
}
}
-unsigned int gr_get_width(GRSurface* surface) {
- if (surface == NULL) {
+unsigned int gr_get_width(const GRSurface* surface) {
+ if (surface == nullptr) {
return 0;
}
return surface->width;
}
-unsigned int gr_get_height(GRSurface* surface) {
- if (surface == NULL) {
+unsigned int gr_get_height(const GRSurface* surface) {
+ if (surface == nullptr) {
return 0;
}
return surface->height;
@@ -372,6 +372,10 @@
void gr_exit() {
delete gr_backend;
+ gr_backend = nullptr;
+
+ delete gr_font;
+ gr_font = nullptr;
}
int gr_fb_width() {
diff --git a/minui/include/minui/minui.h b/minui/include/minui/minui.h
index e96b7ae..ef4abe2 100644
--- a/minui/include/minui/minui.h
+++ b/minui/include/minui/minui.h
@@ -48,7 +48,13 @@
ROTATION_LEFT = 3,
};
+// Initializes the graphics backend and loads font file. Returns 0 on success, or -1 on error. Note
+// that the font initialization failure would be non-fatal, as caller may not need to draw any text
+// at all. Caller can check the font initialization result via gr_sys_font() as needed.
int gr_init();
+
+// Frees the allocated resources. The function is idempotent, and safe to be called if gr_init()
+// didn't finish successfully.
void gr_exit();
int gr_fb_width();
@@ -57,7 +63,8 @@
void gr_flip();
void gr_fb_blank(bool blank);
-void gr_clear(); // clear entire surface to current color
+// Clears entire surface to current color.
+void gr_clear();
void gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a);
void gr_fill(int x1, int y1, int x2, int y2);
@@ -66,16 +73,16 @@
const GRFont* gr_sys_font();
int gr_init_font(const char* name, GRFont** dest);
void gr_text(const GRFont* font, int x, int y, const char* s, bool bold);
-// Return -1 if font is nullptr.
+// Returns -1 if font is nullptr.
int gr_measure(const GRFont* font, const char* s);
-// Return -1 if font is nullptr.
+// Returns -1 if font is nullptr.
int gr_font_size(const GRFont* font, int* x, int* y);
void gr_blit(GRSurface* source, int sx, int sy, int w, int h, int dx, int dy);
-unsigned int gr_get_width(GRSurface* surface);
-unsigned int gr_get_height(GRSurface* surface);
+unsigned int gr_get_width(const GRSurface* surface);
+unsigned int gr_get_height(const GRSurface* surface);
-// Set rotation, flips gr_fb_width/height if 90 degree rotation difference
+// Sets rotation, flips gr_fb_width/height if 90 degree rotation difference
void gr_rotate(GRRotation rotation);
//
diff --git a/tests/component/updater_test.cpp b/tests/component/updater_test.cpp
index 6f3a3a2..fe4f45e 100644
--- a/tests/component/updater_test.cpp
+++ b/tests/component/updater_test.cpp
@@ -100,7 +100,8 @@
}
static void RunBlockImageUpdate(bool is_verify, const PackageEntries& entries,
- const std::string& image_file, const std::string& result) {
+ const std::string& image_file, const std::string& result,
+ CauseCode cause_code = kNoCause) {
CHECK(entries.find("transfer_list") != entries.end());
// Build the update package.
@@ -124,7 +125,7 @@
std::string script = is_verify ? "block_image_verify" : "block_image_update";
script += R"((")" + image_file + R"(", package_extract_file("transfer_list"), ")" + new_data +
R"(", "patch_data"))";
- expect(result.c_str(), script.c_str(), kNoCause, &updater_info);
+ expect(result.c_str(), script.c_str(), cause_code, &updater_info);
ASSERT_EQ(0, fclose(updater_info.cmd_pipe));
CloseArchive(handle);
@@ -504,6 +505,24 @@
ASSERT_EQ(0, fclose(updater_info.cmd_pipe));
}
+TEST_F(UpdaterTest, block_image_update_parsing_error) {
+ std::vector<std::string> transfer_list{
+ // clang-format off
+ "4",
+ "2",
+ "0",
+ // clang-format on
+ };
+
+ PackageEntries entries{
+ { "new_data", "" },
+ { "patch_data", "" },
+ { "transfer_list", android::base::Join(transfer_list, '\n') },
+ };
+
+ RunBlockImageUpdate(false, entries, image_file_, "", kArgsParsingFailure);
+}
+
TEST_F(UpdaterTest, block_image_update_patch_data) {
std::string src_content = std::string(4096, 'a') + std::string(4096, 'c');
std::string tgt_content = std::string(4096, 'b') + std::string(4096, 'd');
diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp
index f2811bc..ff1d20a 100644
--- a/updater/blockimg.cpp
+++ b/updater/blockimg.cpp
@@ -1091,9 +1091,8 @@
* If the return value is 0, source blocks have expected content and the command can be performed.
*/
static int LoadSrcTgtVersion3(CommandParameters& params, RangeSet* tgt, size_t* src_blocks,
- bool onehash, bool* overlap) {
+ bool onehash) {
CHECK(src_blocks != nullptr);
- CHECK(overlap != nullptr);
if (params.cpos >= params.tokens.size()) {
LOG(ERROR) << "missing source hash";
@@ -1135,15 +1134,16 @@
}
// Load source blocks.
- if (LoadSourceBlocks(params, *tgt, src_blocks, overlap) == -1) {
+ bool overlap = false;
+ if (LoadSourceBlocks(params, *tgt, src_blocks, &overlap) == -1) {
return -1;
}
if (VerifyBlocks(srchash, params.buffer, *src_blocks, true) == 0) {
- // If source and target blocks overlap, stash the source blocks so we can
- // resume from possible write errors. In verify mode, we can skip stashing
- // because the source blocks won't be overwritten.
- if (*overlap && params.canwrite) {
+ // If source and target blocks overlap, stash the source blocks so we can resume from possible
+ // write errors. In verify mode, we can skip stashing because the source blocks won't be
+ // overwritten.
+ if (overlap && params.canwrite) {
LOG(INFO) << "stashing " << *src_blocks << " overlapping blocks to " << srchash;
bool stash_exists = false;
@@ -1164,7 +1164,7 @@
return 0;
}
- if (*overlap && LoadStash(params, srchash, true, ¶ms.buffer, true) == 0) {
+ if (overlap && LoadStash(params, srchash, true, ¶ms.buffer, true) == 0) {
// Overlapping source blocks were previously stashed, command can proceed. We are recovering
// from an interrupted command, so we don't know if the stash can safely be deleted after this
// command.
@@ -1182,9 +1182,8 @@
static int PerformCommandMove(CommandParameters& params) {
size_t blocks = 0;
- bool overlap = false;
RangeSet tgt;
- int status = LoadSrcTgtVersion3(params, &tgt, &blocks, true, &overlap);
+ int status = LoadSrcTgtVersion3(params, &tgt, &blocks, true);
if (status == -1) {
LOG(ERROR) << "failed to read blocks for move";
@@ -1382,8 +1381,7 @@
RangeSet tgt;
size_t blocks = 0;
- bool overlap = false;
- int status = LoadSrcTgtVersion3(params, &tgt, &blocks, false, &overlap);
+ int status = LoadSrcTgtVersion3(params, &tgt, &blocks, false);
if (status == -1) {
LOG(ERROR) << "failed to read blocks for diff";
@@ -1628,9 +1626,10 @@
}
}
+ static constexpr size_t kTransferListHeaderLines = 4;
std::vector<std::string> lines = android::base::Split(transfer_list_value->data, "\n");
- if (lines.size() < 2) {
- ErrorAbort(state, kArgsParsingFailure, "too few lines in the transfer list [%zd]",
+ if (lines.size() < kTransferListHeaderLines) {
+ ErrorAbort(state, kArgsParsingFailure, "too few lines in the transfer list [%zu]",
lines.size());
return StringValue("");
}
@@ -1654,12 +1653,6 @@
return StringValue("t");
}
- if (lines.size() < 4) {
- ErrorAbort(state, kArgsParsingFailure, "too few lines in the transfer list [%zu]",
- lines.size());
- return StringValue("");
- }
-
// Third line is how many stash entries are needed simultaneously.
LOG(INFO) << "maximum stash entries " << lines[2];
@@ -1698,7 +1691,6 @@
int rc = -1;
- static constexpr size_t kTransferListHeaderLines = 4;
// Subsequent lines are all individual transfer commands
for (size_t i = kTransferListHeaderLines; i < lines.size(); i++) {
const std::string& line = lines[i];
diff --git a/updater_sample/Android.mk b/updater_sample/Android.mk
index 7662111..a5deee1 100644
--- a/updater_sample/Android.mk
+++ b/updater_sample/Android.mk
@@ -20,9 +20,8 @@
LOCAL_PACKAGE_NAME := SystemUpdaterSample
LOCAL_MODULE_TAGS := samples
LOCAL_SDK_VERSION := system_current
-
-# TODO: enable proguard and use proguard.flags file
-LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_PRIVILEGED_MODULE := true
+LOCAL_PROGUARD_FLAG_FILES := proguard.flags
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/updater_sample/README.md b/updater_sample/README.md
index 8ec43d3..11b55eb 100644
--- a/updater_sample/README.md
+++ b/updater_sample/README.md
@@ -140,6 +140,9 @@
no other update is running. The extra `key_value_pair_headers` will be
included when fetching the payload.
+`key_value_pair_headers` argument also accepts properties other than HTTP Headers.
+List of allowed properties can be found in `system/update_engine/common/constants.cc`.
+
### UpdateEngine#cancel
Cancel the ongoing update. The update could be running or suspended, but it
@@ -181,9 +184,8 @@
- [x] Deferred switch slot demo
- [x] Add UpdateManager; extract update logic from MainActivity
- [x] Add Sample app update state (separate from update_engine status)
-- [-] Add smart update completion detection using onStatusUpdate
-- [ ] Add pause/resume demo
-- [ ] Add demo for passing NETWORK_ID to `UpdateEngine#applyPayload`
+- [x] Add smart update completion detection using onStatusUpdate
+- [x] Add pause/resume demo
- [ ] Verify system partition checksum for package
- [?] Add non-A/B updates demo
diff --git a/updater_sample/proguard.flags b/updater_sample/proguard.flags
new file mode 100644
index 0000000..5883608
--- /dev/null
+++ b/updater_sample/proguard.flags
@@ -0,0 +1,23 @@
+# Copyright (C) 2018 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.
+
+# Keep, used in tests.
+-keep public class com.example.android.systemupdatersample.UpdateManager {
+ public int getUpdaterState();
+}
+
+# Keep, used in tests.
+-keep public class com.example.android.systemupdatersample.UpdateConfig {
+ public <init>(java.lang.String, java.lang.String, int);
+}
diff --git a/updater_sample/tests/Android.mk b/updater_sample/tests/Android.mk
index 9aec372..4157604 100644
--- a/updater_sample/tests/Android.mk
+++ b/updater_sample/tests/Android.mk
@@ -22,10 +22,10 @@
LOCAL_MODULE_TAGS := tests
LOCAL_JAVA_LIBRARIES := \
android.test.base.stubs \
- android.test.runner.stubs \
- guava
+ android.test.runner.stubs
LOCAL_STATIC_JAVA_LIBRARIES := android-support-test \
- mockito-target-minus-junit4
+ mockito-target-minus-junit4 \
+ guava
LOCAL_INSTRUMENTATION_FOR := SystemUpdaterSample
LOCAL_PROGUARD_ENABLED := disabled
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 3ba84c1..0308693 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
@@ -65,7 +65,7 @@
mTargetContext = InstrumentationRegistry.getTargetContext();
mTestContext = InstrumentationRegistry.getContext();
- mTestDir = mTargetContext.getFilesDir();
+ mTestDir = mTargetContext.getCacheDir();
mPayloadSpecs = new PayloadSpecs();
}
diff --git a/updater_sample/tools/gen_update_config.py b/updater_sample/tools/gen_update_config.py
index 7fb64f7..b43e49d 100755
--- a/updater_sample/tools/gen_update_config.py
+++ b/updater_sample/tools/gen_update_config.py
@@ -131,10 +131,10 @@
choices=ab_install_type_choices,
help='A/B update installation type')
parser.add_argument('--ab_force_switch_slot',
- type=bool,
default=False,
- help='if set true device will boot to a new slot, otherwise user manually '
- 'switches slot on the screen')
+ action='store_true',
+ help='if set device will boot to a new slot, otherwise user '
+ 'manually switches slot on the screen')
parser.add_argument('package',
type=str,
help='OTA package zip file')