Merge "Add a header-version argument to fastboot"
diff --git a/adb/fdevent.cpp b/adb/fdevent.cpp
index 9776c1b..cf441cf 100644
--- a/adb/fdevent.cpp
+++ b/adb/fdevent.cpp
@@ -75,6 +75,7 @@
static bool main_thread_valid;
static uint64_t main_thread_id;
+static bool run_needs_flush = false;
static auto& run_queue_notify_fd = *new unique_fd();
static auto& run_queue_mutex = *new std::mutex();
static auto& run_queue GUARDED_BY(run_queue_mutex) = *new std::deque<std::function<void()>>();
@@ -317,7 +318,8 @@
PLOG(FATAL) << "failed to empty run queue notify fd";
}
- fdevent_run_flush();
+ // Mark that we need to flush, and then run it at the end of fdevent_loop.
+ run_needs_flush = true;
}
static void fdevent_run_setup() {
@@ -378,6 +380,11 @@
g_pending_list.pop_front();
fdevent_call_fdfunc(fde);
}
+
+ if (run_needs_flush) {
+ fdevent_run_flush();
+ run_needs_flush = false;
+ }
}
}
diff --git a/adb/fdevent_test.cpp b/adb/fdevent_test.cpp
index e3d5a35..2f0ff18 100644
--- a/adb/fdevent_test.cpp
+++ b/adb/fdevent_test.cpp
@@ -80,30 +80,7 @@
TEST_F(FdeventTest, fdevent_terminate) {
PrepareThread();
-
- std::thread thread(fdevent_loop);
- TerminateThread(thread);
-}
-
-static void FdEventThreadFunc(ThreadArg* arg) {
- std::vector<int> read_fds;
- std::vector<int> write_fds;
-
- read_fds.push_back(arg->first_read_fd);
- for (size_t i = 0; i < arg->middle_pipe_count; ++i) {
- int fds[2];
- ASSERT_EQ(0, adb_socketpair(fds));
- read_fds.push_back(fds[0]);
- write_fds.push_back(fds[1]);
- }
- write_fds.push_back(arg->last_write_fd);
-
- std::vector<std::unique_ptr<FdHandler>> fd_handlers;
- for (size_t i = 0; i < read_fds.size(); ++i) {
- fd_handlers.push_back(std::make_unique<FdHandler>(read_fds[i], write_fds[i]));
- }
-
- fdevent_loop();
+ TerminateThread();
}
TEST_F(FdeventTest, smoke) {
@@ -122,7 +99,26 @@
int reader = fd_pair2[0];
PrepareThread();
- std::thread thread(FdEventThreadFunc, &thread_arg);
+
+ std::vector<std::unique_ptr<FdHandler>> fd_handlers;
+ fdevent_run_on_main_thread([&thread_arg, &fd_handlers]() {
+ std::vector<int> read_fds;
+ std::vector<int> write_fds;
+
+ read_fds.push_back(thread_arg.first_read_fd);
+ for (size_t i = 0; i < thread_arg.middle_pipe_count; ++i) {
+ int fds[2];
+ ASSERT_EQ(0, adb_socketpair(fds));
+ read_fds.push_back(fds[0]);
+ write_fds.push_back(fds[1]);
+ }
+ write_fds.push_back(thread_arg.last_write_fd);
+
+ for (size_t i = 0; i < read_fds.size(); ++i) {
+ fd_handlers.push_back(std::make_unique<FdHandler>(read_fds[i], write_fds[i]));
+ }
+ });
+ WaitForFdeventLoop();
for (size_t i = 0; i < MESSAGE_LOOP_COUNT; ++i) {
std::string read_buffer = MESSAGE;
@@ -132,7 +128,10 @@
ASSERT_EQ(read_buffer, write_buffer);
}
- TerminateThread(thread);
+ fdevent_run_on_main_thread([&fd_handlers]() { fd_handlers.clear(); });
+ WaitForFdeventLoop();
+
+ TerminateThread();
ASSERT_EQ(0, adb_close(writer));
ASSERT_EQ(0, adb_close(reader));
}
@@ -143,7 +142,7 @@
size_t* happened_event_count;
};
-static void InvalidFdEventCallback(int fd, unsigned events, void* userdata) {
+static void InvalidFdEventCallback(int, unsigned events, void* userdata) {
InvalidFdArg* arg = reinterpret_cast<InvalidFdArg*>(userdata);
ASSERT_EQ(arg->expected_events, events);
fdevent_remove(&arg->fde);
@@ -179,7 +178,6 @@
std::vector<int> vec;
PrepareThread();
- std::thread thread(fdevent_loop);
// Block the main thread for a long time while we queue our callbacks.
fdevent_run_on_main_thread([]() {
@@ -194,7 +192,7 @@
});
}
- TerminateThread(thread);
+ TerminateThread();
ASSERT_EQ(1000000u, vec.size());
for (int i = 0; i < 1000000; ++i) {
@@ -218,11 +216,8 @@
std::vector<int> vec;
PrepareThread();
- std::thread thread(fdevent_loop);
-
fdevent_run_on_main_thread(make_appender(&vec, 0));
-
- TerminateThread(thread);
+ TerminateThread();
ASSERT_EQ(100u, vec.size());
for (int i = 0; i < 100; ++i) {
diff --git a/adb/fdevent_test.h b/adb/fdevent_test.h
index 1a2d41c..5a417e0 100644
--- a/adb/fdevent_test.h
+++ b/adb/fdevent_test.h
@@ -16,10 +16,31 @@
#include <gtest/gtest.h>
+#include <condition_variable>
+#include <mutex>
#include <thread>
#include "socket.h"
#include "sysdeps.h"
+#include "sysdeps/chrono.h"
+
+static void WaitForFdeventLoop() {
+ // Sleep for a bit to make sure that network events have propagated.
+ std::this_thread::sleep_for(100ms);
+
+ // fdevent_run_on_main_thread has a guaranteed ordering, and is guaranteed to happen after
+ // socket events, so as soon as our function is called, we know that we've processed all
+ // previous events.
+ std::mutex mutex;
+ std::condition_variable cv;
+ std::unique_lock<std::mutex> lock(mutex);
+ fdevent_run_on_main_thread([&]() {
+ mutex.lock();
+ mutex.unlock();
+ cv.notify_one();
+ });
+ cv.wait(lock);
+}
class FdeventTest : public ::testing::Test {
protected:
@@ -49,6 +70,9 @@
}
dummy_socket->ready(dummy_socket);
dummy = dummy_fds[0];
+
+ thread_ = std::thread([]() { fdevent_loop(); });
+ WaitForFdeventLoop();
}
size_t GetAdditionalLocalSocketCount() {
@@ -56,10 +80,12 @@
return 2;
}
- void TerminateThread(std::thread& thread) {
+ void TerminateThread() {
fdevent_terminate_loop();
ASSERT_TRUE(WriteFdExactly(dummy, "", 1));
- thread.join();
+ thread_.join();
ASSERT_EQ(0, adb_close(dummy));
}
+
+ std::thread thread_;
};
diff --git a/adb/socket_test.cpp b/adb/socket_test.cpp
index 6b40056..6c4a8b2 100644
--- a/adb/socket_test.cpp
+++ b/adb/socket_test.cpp
@@ -42,8 +42,6 @@
class LocalSocketTest : public FdeventTest {};
-constexpr auto SLEEP_FOR_FDEVENT = 100ms;
-
TEST_F(LocalSocketTest, smoke) {
// Join two socketpairs with a chain of intermediate socketpairs.
int first[2];
@@ -84,7 +82,6 @@
connect(prev_tail, end);
PrepareThread();
- std::thread thread(fdevent_loop);
for (size_t i = 0; i < MESSAGE_LOOP_COUNT; ++i) {
std::string read_buffer = MESSAGE;
@@ -98,9 +95,9 @@
ASSERT_EQ(0, adb_close(last[1]));
// Wait until the local sockets are closed.
- std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+ WaitForFdeventLoop();
ASSERT_EQ(GetAdditionalLocalSocketCount(), fdevent_installed_count());
- TerminateThread(thread);
+ TerminateThread();
}
struct CloseWithPacketArg {
@@ -109,24 +106,39 @@
int cause_close_fd;
};
-static void CloseWithPacketThreadFunc(CloseWithPacketArg* arg) {
- asocket* s = create_local_socket(arg->socket_fd);
- ASSERT_TRUE(s != nullptr);
- arg->bytes_written = 0;
+static void CreateCloser(CloseWithPacketArg* arg) {
+ fdevent_run_on_main_thread([arg]() {
+ asocket* s = create_local_socket(arg->socket_fd);
+ ASSERT_TRUE(s != nullptr);
+ arg->bytes_written = 0;
- std::string data;
- data.resize(MAX_PAYLOAD);
- arg->bytes_written += data.size();
- int ret = s->enqueue(s, std::move(data));
- ASSERT_EQ(1, ret);
+ // On platforms that implement sockets via underlying sockets (e.g. Wine),
+ // a socket can appear to be full, and then become available for writes
+ // again without read being called on the other end. Loop and sleep after
+ // each write to give the underlying implementation time to flush.
+ bool socket_filled = false;
+ for (int i = 0; i < 128; ++i) {
+ std::string data;
+ data.resize(MAX_PAYLOAD);
+ arg->bytes_written += data.size();
+ int ret = s->enqueue(s, std::move(data));
+ if (ret == 1) {
+ socket_filled = true;
+ break;
+ }
+ ASSERT_NE(-1, ret);
- asocket* cause_close_s = create_local_socket(arg->cause_close_fd);
- ASSERT_TRUE(cause_close_s != nullptr);
- cause_close_s->peer = s;
- s->peer = cause_close_s;
- cause_close_s->ready(cause_close_s);
+ std::this_thread::sleep_for(250ms);
+ }
+ ASSERT_TRUE(socket_filled);
- fdevent_loop();
+ asocket* cause_close_s = create_local_socket(arg->cause_close_fd);
+ ASSERT_TRUE(cause_close_s != nullptr);
+ cause_close_s->peer = s;
+ s->peer = cause_close_s;
+ cause_close_s->ready(cause_close_s);
+ });
+ WaitForFdeventLoop();
}
// This test checks if we can close local socket in the following situation:
@@ -143,16 +155,17 @@
arg.cause_close_fd = cause_close_fd[1];
PrepareThread();
- std::thread thread(CloseWithPacketThreadFunc, &arg);
- // Wait until the fdevent_loop() starts.
- std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+ CreateCloser(&arg);
+
ASSERT_EQ(0, adb_close(cause_close_fd[0]));
- std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+
+ WaitForFdeventLoop();
EXPECT_EQ(1u + GetAdditionalLocalSocketCount(), fdevent_installed_count());
ASSERT_EQ(0, adb_close(socket_fd[0]));
- std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+
+ WaitForFdeventLoop();
ASSERT_EQ(GetAdditionalLocalSocketCount(), fdevent_installed_count());
- TerminateThread(thread);
+ TerminateThread();
}
// This test checks if we can read packets from a closing local socket.
@@ -166,11 +179,12 @@
arg.cause_close_fd = cause_close_fd[1];
PrepareThread();
- std::thread thread(CloseWithPacketThreadFunc, &arg);
- // Wait until the fdevent_loop() starts.
- std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+ CreateCloser(&arg);
+
+ WaitForFdeventLoop();
ASSERT_EQ(0, adb_close(cause_close_fd[0]));
- std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+
+ WaitForFdeventLoop();
EXPECT_EQ(1u + GetAdditionalLocalSocketCount(), fdevent_installed_count());
// Verify if we can read successfully.
@@ -179,9 +193,9 @@
ASSERT_EQ(true, ReadFdExactly(socket_fd[0], buf.data(), buf.size()));
ASSERT_EQ(0, adb_close(socket_fd[0]));
- std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+ WaitForFdeventLoop();
ASSERT_EQ(GetAdditionalLocalSocketCount(), fdevent_installed_count());
- TerminateThread(thread);
+ TerminateThread();
}
// This test checks if we can close local socket in the following situation:
@@ -198,15 +212,15 @@
arg.cause_close_fd = cause_close_fd[1];
PrepareThread();
- std::thread thread(CloseWithPacketThreadFunc, &arg);
- // Wait until the fdevent_loop() starts.
- std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+ CreateCloser(&arg);
+
+ WaitForFdeventLoop();
EXPECT_EQ(2u + GetAdditionalLocalSocketCount(), fdevent_installed_count());
ASSERT_EQ(0, adb_close(socket_fd[0]));
- std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+ WaitForFdeventLoop();
ASSERT_EQ(GetAdditionalLocalSocketCount(), fdevent_installed_count());
- TerminateThread(thread);
+ TerminateThread();
}
// Ensure that if we fail to write output to an fd, we will still flush data coming from it.
@@ -226,7 +240,6 @@
tail->ready(tail);
PrepareThread();
- std::thread thread(fdevent_loop);
EXPECT_TRUE(WriteFdExactly(head_fd[0], "foo", 3));
@@ -242,10 +255,9 @@
adb_close(head_fd[0]);
adb_close(tail_fd[0]);
- // Wait until the local sockets are closed.
- std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+ WaitForFdeventLoop();
ASSERT_EQ(GetAdditionalLocalSocketCount(), fdevent_installed_count());
- TerminateThread(thread);
+ TerminateThread();
}
#if defined(__linux__)
@@ -254,21 +266,10 @@
std::string error;
int fd = network_loopback_client(5038, SOCK_STREAM, &error);
ASSERT_GE(fd, 0) << error;
- std::this_thread::sleep_for(200ms);
+ std::this_thread::sleep_for(1s);
ASSERT_EQ(0, adb_close(fd));
}
-struct CloseRdHupSocketArg {
- int socket_fd;
-};
-
-static void CloseRdHupSocketThreadFunc(CloseRdHupSocketArg* arg) {
- asocket* s = create_local_socket(arg->socket_fd);
- ASSERT_TRUE(s != nullptr);
-
- fdevent_loop();
-}
-
// This test checks if we can close sockets in CLOSE_WAIT state.
TEST_F(LocalSocketTest, close_socket_in_CLOSE_WAIT_state) {
std::string error;
@@ -279,22 +280,23 @@
int accept_fd = adb_socket_accept(listen_fd, nullptr, nullptr);
ASSERT_GE(accept_fd, 0);
- CloseRdHupSocketArg arg;
- arg.socket_fd = accept_fd;
PrepareThread();
- std::thread thread(CloseRdHupSocketThreadFunc, &arg);
- // Wait until the fdevent_loop() starts.
- std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+ fdevent_run_on_main_thread([accept_fd]() {
+ asocket* s = create_local_socket(accept_fd);
+ ASSERT_TRUE(s != nullptr);
+ });
+
+ WaitForFdeventLoop();
EXPECT_EQ(1u + GetAdditionalLocalSocketCount(), fdevent_installed_count());
// Wait until the client closes its socket.
client_thread.join();
- std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+ WaitForFdeventLoop();
ASSERT_EQ(GetAdditionalLocalSocketCount(), fdevent_installed_count());
- TerminateThread(thread);
+ TerminateThread();
}
#endif // defined(__linux__)
diff --git a/adb/sockets.cpp b/adb/sockets.cpp
index e05a3db..0887e6f 100644
--- a/adb/sockets.cpp
+++ b/adb/sockets.cpp
@@ -126,12 +126,12 @@
} else if (rc == -1 && errno == EAGAIN) {
fdevent_add(&s->fde, FDE_WRITE);
return SocketFlushResult::TryAgain;
+ } else {
+ // We failed to write, but it's possible that we can still read from the socket.
+ // Give that a try before giving up.
+ s->has_write_error = true;
+ break;
}
-
- // We failed to write, but it's possible that we can still read from the socket.
- // Give that a try before giving up.
- s->has_write_error = true;
- break;
}
// If we sent the last packet of a closing socket, we can now destroy it.
diff --git a/adb/sysdeps_test.cpp b/adb/sysdeps_test.cpp
index fd19882..79cebe6 100644
--- a/adb/sysdeps_test.cpp
+++ b/adb/sysdeps_test.cpp
@@ -121,10 +121,13 @@
adb_pollfd pfd[3] = {};
pfd[0].fd = fds[0];
pfd[0].events = POLLRDNORM;
+ pfd[0].revents = ~0;
pfd[1].fd = INT_MAX;
pfd[1].events = POLLRDNORM;
+ pfd[1].revents = ~0;
pfd[2].fd = fds[1];
pfd[2].events = POLLWRNORM;
+ pfd[2].revents = ~0;
ASSERT_TRUE(WriteFdExactly(fds[1], "foo", 4));
@@ -136,6 +139,17 @@
EXPECT_EQ(POLLRDNORM, pfd[0].revents);
EXPECT_EQ(POLLNVAL, pfd[1].revents);
EXPECT_EQ(POLLWRNORM, pfd[2].revents);
+
+ // Make sure that we return immediately if an invalid FD is given.
+ pfd[0].fd = fds[0];
+ pfd[0].events = POLLRDNORM;
+ pfd[0].revents = ~0;
+ pfd[1].fd = INT_MAX;
+ pfd[1].events = POLLRDNORM;
+ pfd[1].revents = ~0;
+ EXPECT_EQ(2, adb_poll(pfd, 2, -1));
+ EXPECT_EQ(POLLRDNORM, pfd[0].revents);
+ EXPECT_EQ(POLLNVAL, pfd[1].revents);
}
TEST_F(sysdeps_poll, duplicate_fd) {
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index 62f4ac8..7d35fb6 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -529,6 +529,7 @@
int skipped = 0;
std::vector<WSAPOLLFD> sockets;
std::vector<adb_pollfd*> original;
+
for (size_t i = 0; i < nfds; ++i) {
FH fh = _fh_from_int(fds[i].fd, __func__);
if (!fh || !fh->used || fh->clazz != &_fh_socket_class) {
@@ -549,6 +550,11 @@
return skipped;
}
+ // If we have any invalid FDs in our FD set, make sure to return immediately.
+ if (skipped > 0) {
+ timeout = 0;
+ }
+
int result = WSAPoll(sockets.data(), sockets.size(), timeout);
if (result == SOCKET_ERROR) {
_socket_set_errno(WSAGetLastError());
@@ -560,7 +566,7 @@
original[i]->revents = sockets[i].revents;
}
- // WSAPoll appears to return the number of unique FDs with avaiable events, instead of how many
+ // WSAPoll appears to return the number of unique FDs with available events, instead of how many
// of the pollfd elements have a non-zero revents field, which is what it and poll are specified
// to do. Ignore its result and calculate the proper return value.
result = 0;
diff --git a/fastboot/Android.mk b/fastboot/Android.mk
index f5bcc26..944b00b 100644
--- a/fastboot/Android.mk
+++ b/fastboot/Android.mk
@@ -22,7 +22,8 @@
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/../adb \
- $(LOCAL_PATH)/../mkbootimg \
+
+LOCAL_HEADER_LIBRARIES := bootimg_headers
LOCAL_SRC_FILES := \
bootimg_utils.cpp \
diff --git a/fastboot/engine.cpp b/fastboot/engine.cpp
index 60b7124..551ddba 100644
--- a/fastboot/engine.cpp
+++ b/fastboot/engine.cpp
@@ -109,32 +109,32 @@
void fb_set_active(const std::string& slot) {
Action& a = queue_action(OP_COMMAND, "set_active:" + slot);
- a.msg = "Setting current slot to '" + slot + "'...";
+ a.msg = "Setting current slot to '" + slot + "'";
}
void fb_queue_erase(const std::string& partition) {
Action& a = queue_action(OP_COMMAND, "erase:" + partition);
- a.msg = "Erasing '" + partition + "'...";
+ a.msg = "Erasing '" + partition + "'";
}
void fb_queue_flash_fd(const std::string& partition, int fd, uint32_t sz) {
Action& a = queue_action(OP_DOWNLOAD_FD, "");
a.fd = fd;
a.size = sz;
- a.msg = android::base::StringPrintf("Sending '%s' (%d KB)...", partition.c_str(), sz / 1024);
+ a.msg = android::base::StringPrintf("Sending '%s' (%u KB)", partition.c_str(), sz / 1024);
Action& b = queue_action(OP_COMMAND, "flash:" + partition);
- b.msg = "Writing '" + partition + "'...";
+ b.msg = "Writing '" + partition + "'";
}
void fb_queue_flash(const std::string& partition, void* data, uint32_t sz) {
Action& a = queue_action(OP_DOWNLOAD, "");
a.data = data;
a.size = sz;
- a.msg = android::base::StringPrintf("Sending '%s' (%d KB)...", partition.c_str(), sz / 1024);
+ a.msg = android::base::StringPrintf("Sending '%s' (%u KB)", partition.c_str(), sz / 1024);
Action& b = queue_action(OP_COMMAND, "flash:" + partition);
- b.msg = "Writing '" + partition + "'...";
+ b.msg = "Writing '" + partition + "'";
}
void fb_queue_flash_sparse(const std::string& partition, struct sparse_file* s, uint32_t sz,
@@ -142,12 +142,12 @@
Action& a = queue_action(OP_DOWNLOAD_SPARSE, "");
a.data = s;
a.size = 0;
- a.msg = android::base::StringPrintf("Sending sparse '%s' %zu/%zu (%d KB)...", partition.c_str(),
+ a.msg = android::base::StringPrintf("Sending sparse '%s' %zu/%zu (%u KB)", partition.c_str(),
current, total, sz / 1024);
Action& b = queue_action(OP_COMMAND, "flash:" + partition);
- b.msg =
- android::base::StringPrintf("Writing '%s' %zu/%zu...", partition.c_str(), current, total);
+ b.msg = android::base::StringPrintf("Writing sparse '%s' %zu/%zu", partition.c_str(), current,
+ total);
}
static int match(const char* str, const char** value, unsigned count) {
@@ -270,7 +270,7 @@
void fb_queue_reboot() {
Action& a = queue_action(OP_COMMAND, "reboot");
a.func = cb_do_nothing;
- a.msg = "Rebooting...";
+ a.msg = "Rebooting";
}
void fb_queue_command(const std::string& cmd, const std::string& msg) {
@@ -289,7 +289,7 @@
Action& a = queue_action(OP_DOWNLOAD_FD, "");
a.fd = fd;
a.size = sz;
- a.msg = android::base::StringPrintf("Sending '%s' (%d KB)", name.c_str(), sz / 1024);
+ a.msg = android::base::StringPrintf("Sending '%s' (%u KB)", name.c_str(), sz / 1024);
}
void fb_queue_upload(const std::string& outfile) {
@@ -312,7 +312,8 @@
for (auto& a : action_list) {
a->start = now();
if (!a->msg.empty()) {
- fprintf(stderr, "%s\n", a->msg.c_str());
+ fprintf(stderr, "%-50s ", a->msg.c_str());
+ verbose("\n");
}
if (a->op == OP_DOWNLOAD) {
status = fb_download_data(transport, a->data, a->size);
@@ -333,6 +334,7 @@
if (status) break;
} else if (a->op == OP_NOTICE) {
// We already showed the notice because it's in `Action::msg`.
+ fprintf(stderr, "\n");
} else if (a->op == OP_DOWNLOAD_SPARSE) {
status = fb_download_data_sparse(transport, reinterpret_cast<sparse_file*>(a->data));
status = a->func(*a, status, status ? fb_get_error().c_str() : "");
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 0ce3855..c5b357c 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -238,7 +238,7 @@
// Opens a new Transport connected to a device. If |serial| is non-null it will be used to identify
// a specific device, otherwise the first USB device found will be used.
//
-// If |serial| is non-null but invalid, this prints an error message to stderr and returns nullptr.
+// If |serial| is non-null but invalid, this exits.
// Otherwise it blocks until the target is available.
//
// The returned Transport is a singleton, so multiple calls to this function will return the same
@@ -270,9 +270,7 @@
if (net_address != nullptr) {
std::string error;
if (!android::base::ParseNetAddress(net_address, &host, &port, nullptr, &error)) {
- fprintf(stderr, "error: Invalid network address '%s': %s\n", net_address,
- error.c_str());
- return nullptr;
+ die("invalid network address '%s': %s\n", net_address, error.c_str());
}
}
}
@@ -426,7 +424,7 @@
" trigger a reboot.\n"
" --disable-verity Set the disable-verity flag in the\n"
" the vbmeta image being flashed.\n"
- " --disable-verification Set the disable-verification flag in"
+ " --disable-verification Set the disable-verification flag in\n"
" the vbmeta image being flashed.\n"
#if !defined(_WIN32)
" --wipe-and-use-fbe On devices which support it,\n"
@@ -434,6 +432,7 @@
" enable file-based encryption\n"
#endif
" --unbuffered Do not buffer input or output.\n"
+ " -v, --verbose Verbose output.\n"
" --version Display version.\n"
" --header-version Set boot image header version while\n"
" using flash:raw and boot commands to \n"
@@ -548,7 +547,7 @@
die("make_temporary_directory not supported under Windows, sorry!");
}
-static int make_temporary_fd() {
+static int make_temporary_fd(const char* /*what*/) {
// TODO: reimplement to avoid leaking a FILE*.
return fileno(tmpfile());
}
@@ -564,18 +563,16 @@
static std::string make_temporary_directory() {
std::string result(make_temporary_template());
if (mkdtemp(&result[0]) == nullptr) {
- fprintf(stderr, "Unable to create temporary directory: %s\n", strerror(errno));
- return "";
+ die("unable to create temporary directory: %s", strerror(errno));
}
return result;
}
-static int make_temporary_fd() {
+static int make_temporary_fd(const char* what) {
std::string path_template(make_temporary_template());
int fd = mkstemp(&path_template[0]);
if (fd == -1) {
- fprintf(stderr, "Unable to create temporary file: %s\n", strerror(errno));
- return -1;
+ die("failed to create temporary file for %s: %s\n", what, strerror(errno));
}
unlink(path_template.c_str());
return fd;
@@ -585,16 +582,11 @@
static std::string create_fbemarker_tmpdir() {
std::string dir = make_temporary_directory();
- if (dir.empty()) {
- fprintf(stderr, "Unable to create local temp directory for FBE marker\n");
- return "";
- }
std::string marker_file = dir + "/" + convert_fbe_marker_filename;
int fd = open(marker_file.c_str(), O_CREAT | O_WRONLY | O_CLOEXEC, 0666);
if (fd == -1) {
- fprintf(stderr, "Unable to create FBE marker file %s locally: %d, %s\n",
- marker_file.c_str(), errno, strerror(errno));
- return "";
+ die("unable to create FBE marker file %s locally: %s",
+ marker_file.c_str(), strerror(errno));
}
close(fd);
return dir;
@@ -615,10 +607,7 @@
}
static int unzip_to_file(ZipArchiveHandle zip, const char* entry_name) {
- unique_fd fd(make_temporary_fd());
- if (fd == -1) {
- die("failed to create temporary file for '%s': %s", entry_name, strerror(errno));
- }
+ unique_fd fd(make_temporary_fd(entry_name));
ZipString zip_entry_name(entry_name);
ZipEntry zip_entry;
@@ -779,8 +768,8 @@
static int64_t get_target_sparse_limit(Transport* transport) {
std::string max_download_size;
if (!fb_getvar(transport, "max-download-size", &max_download_size) ||
- max_download_size.empty()) {
- fprintf(stderr, "target didn't report max-download-size\n");
+ max_download_size.empty()) {
+ verbose("target didn't report max-download-size");
return 0;
}
@@ -792,9 +781,7 @@
fprintf(stderr, "couldn't parse max-download-size '%s'\n", max_download_size.c_str());
return 0;
}
- if (limit > 0) {
- fprintf(stderr, "target reported max download size of %" PRId64 " bytes\n", limit);
- }
+ if (limit > 0) verbose("target reported max download size of %" PRId64 " bytes", limit);
return limit;
}
@@ -885,10 +872,7 @@
return;
}
- int fd = make_temporary_fd();
- if (fd == -1) {
- die("Failed to create temporary file for vbmeta rewriting");
- }
+ int fd = make_temporary_fd("vbmeta rewriting");
std::string data;
if (!android::base::ReadFdToString(buf->fd, &data)) {
@@ -1527,12 +1511,13 @@
{"tags-offset", required_argument, 0, 't'},
{"help", no_argument, 0, 'h'},
{"unbuffered", no_argument, 0, 0},
- {"version", no_argument, 0, 0},
{"slot", required_argument, 0, 0},
{"set_active", optional_argument, 0, 'a'},
{"set-active", optional_argument, 0, 'a'},
{"skip-secondary", no_argument, 0, 0},
{"skip-reboot", no_argument, 0, 0},
+ {"verbose", no_argument, 0, 'v'},
+ {"version", no_argument, 0, 0},
{"disable-verity", no_argument, 0, 0},
{"disable-verification", no_argument, 0, 0},
{"header-version", required_argument, 0, 0},
@@ -1545,7 +1530,7 @@
serial = getenv("ANDROID_SERIAL");
while (1) {
- int c = getopt_long(argc, argv, "wub:k:n:r:t:s:S:lc:i:m:ha::", longopts, &longindex);
+ int c = getopt_long(argc, argv, "vwub:k:n:r:t:s:S:lc:i:m:ha::", longopts, &longindex);
if (c < 0) {
break;
}
@@ -1600,6 +1585,9 @@
case 'u':
erase_first = false;
break;
+ case 'v':
+ set_verbose();
+ break;
case 'w':
wants_wipe = true;
break;
@@ -1631,9 +1619,7 @@
} else if (strcmp("header-version", longopts[longindex].name) == 0) {
header_version = strtoul(optarg, nullptr, 0);
} else {
- fprintf(stderr, "Internal error in options processing for %s\n",
- longopts[longindex].name);
- return 1;
+ die("unknown option %s", longopts[longindex].name);
}
break;
default:
@@ -1862,14 +1848,10 @@
}
if (wants_wipe) {
- fprintf(stderr, "wiping userdata...\n");
fb_queue_erase("userdata");
if (set_fbe_marker) {
- fprintf(stderr, "setting FBE marker...\n");
+ fprintf(stderr, "setting FBE marker on initial userdata...\n");
std::string initial_userdata_dir = create_fbemarker_tmpdir();
- if (initial_userdata_dir.empty()) {
- return 1;
- }
fb_perform_format(transport, "userdata", 1, "", "", initial_userdata_dir);
delete_fbemarker_tmpdir(initial_userdata_dir);
} else {
@@ -1878,7 +1860,6 @@
std::string cache_type;
if (fb_getvar(transport, "partition-type:cache", &cache_type) && !cache_type.empty()) {
- fprintf(stderr, "wiping cache...\n");
fb_queue_erase("cache");
fb_perform_format(transport, "cache", 1, "", "", "");
}
diff --git a/fastboot/fastboot.h b/fastboot/fastboot.h
index a31057a..005ba5a 100644
--- a/fastboot/fastboot.h
+++ b/fastboot/fastboot.h
@@ -75,6 +75,7 @@
/* util stuff */
double now();
char* xstrdup(const char*);
+void set_verbose();
// These printf-like functions are implemented in terms of vsnprintf, so they
// use the same attribute for compile-time format string checking. On Windows,
@@ -90,6 +91,7 @@
#endif
void die(const char* fmt, ...) __attribute__((__noreturn__))
__attribute__((__format__(FASTBOOT_FORMAT_ARCHETYPE, 1, 2)));
+void verbose(const char* fmt, ...) __attribute__((__format__(FASTBOOT_FORMAT_ARCHETYPE, 1, 2)));
#undef FASTBOOT_FORMAT_ARCHETYPE
/* Current product */
diff --git a/fastboot/protocol.cpp b/fastboot/protocol.cpp
index c239861..133a2d0 100644
--- a/fastboot/protocol.cpp
+++ b/fastboot/protocol.cpp
@@ -75,18 +75,21 @@
}
if (!memcmp(status, "INFO", 4)) {
- fprintf(stderr,"(bootloader) %s\n", status + 4);
+ verbose("received INFO %s", status + 4);
+ fprintf(stderr, "(bootloader) %s\n", status + 4);
continue;
}
if (!memcmp(status, "OKAY", 4)) {
+ verbose("received OKAY %s", status + 4);
if (response) {
- strcpy(response, (char*) status + 4);
+ strcpy(response, status + 4);
}
return 0;
}
if (!memcmp(status, "FAIL", 4)) {
+ verbose("received FAIL %s", status + 4);
if (r > 4) {
g_error = android::base::StringPrintf("remote: %s", status + 4);
} else {
@@ -96,6 +99,7 @@
}
if (!memcmp(status, "DATA", 4) && size > 0){
+ verbose("received DATA %s", status + 4);
uint32_t dsize = strtol(status + 4, 0, 16);
if (dsize > size) {
g_error = android::base::StringPrintf("data size too large (%d)", dsize);
@@ -105,6 +109,7 @@
return dsize;
}
+ verbose("received unknown status code \"%4.4s\"", status);
g_error = "unknown status code";
transport->Close();
break;
@@ -124,6 +129,8 @@
response[0] = 0;
}
+ verbose("sending command \"%s\"", cmd.c_str());
+
if (transport->Write(cmd.c_str(), cmd.size()) != static_cast<int>(cmd.size())) {
g_error = android::base::StringPrintf("command write failed (%s)", strerror(errno));
transport->Close();
@@ -134,6 +141,8 @@
}
static int64_t _command_write_data(Transport* transport, const void* data, uint32_t size) {
+ verbose("sending data (%" PRIu32 " bytes)", size);
+
int64_t r = transport->Write(data, size);
if (r < 0) {
g_error = android::base::StringPrintf("data write failure (%s)", strerror(errno));
@@ -149,6 +158,8 @@
}
static int64_t _command_read_data(Transport* transport, void* data, uint32_t size) {
+ verbose("reading data (%" PRIu32 " bytes)", size);
+
int64_t r = transport->Read(data, size);
if (r < 0) {
g_error = android::base::StringPrintf("data read failure (%s)", strerror(errno));
diff --git a/fastboot/util.cpp b/fastboot/util.cpp
index fb085e7..140270f 100644
--- a/fastboot/util.cpp
+++ b/fastboot/util.cpp
@@ -35,6 +35,8 @@
#include "fastboot.h"
+static bool g_verbose = false;
+
double now() {
struct timeval tv;
gettimeofday(&tv, NULL);
@@ -44,13 +46,30 @@
void die(const char* fmt, ...) {
va_list ap;
va_start(ap, fmt);
- fprintf(stderr,"error: ");
+ fprintf(stderr, "fastboot: error: ");
vfprintf(stderr, fmt, ap);
- fprintf(stderr,"\n");
+ fprintf(stderr, "\n");
va_end(ap);
exit(EXIT_FAILURE);
}
+void set_verbose() {
+ g_verbose = true;
+}
+
+void verbose(const char* fmt, ...) {
+ if (!g_verbose) return;
+
+ if (*fmt != '\n') {
+ va_list ap;
+ va_start(ap, fmt);
+ fprintf(stderr, "fastboot: verbose: ");
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ }
+ fprintf(stderr, "\n");
+}
+
char* xstrdup(const char* s) {
char* result = strdup(s);
if (!result) die("out of memory");
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index 72a65d2..3fbef9f 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -116,17 +116,21 @@
#define EM_ICE 2
#define EM_AES_256_CTS 3
#define EM_AES_256_HEH 4
+#define EM_SPECK_128_256_XTS 5
+#define EM_SPECK_128_256_CTS 6
static const struct flag_list file_contents_encryption_modes[] = {
{"aes-256-xts", EM_AES_256_XTS},
+ {"speck128/256-xts", EM_SPECK_128_256_XTS},
{"software", EM_AES_256_XTS}, /* alias for backwards compatibility */
- {"ice", EM_ICE}, /* hardware-specific inline cryptographic engine */
+ {"ice", EM_ICE}, /* hardware-specific inline cryptographic engine */
{0, 0},
};
static const struct flag_list file_names_encryption_modes[] = {
{"aes-256-cts", EM_AES_256_CTS},
{"aes-256-heh", EM_AES_256_HEH},
+ {"speck128/256-cts", EM_SPECK_128_256_CTS},
{0, 0},
};
diff --git a/init/Android.bp b/init/Android.bp
index 31c8efb..70a4ac6 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -127,9 +127,7 @@
"watchdogd.cpp",
],
whole_static_libs: ["libcap"],
- include_dirs: [
- "system/core/mkbootimg",
- ],
+ header_libs: ["bootimg_headers"],
proto: {
type: "lite",
export_proto_headers: true,
diff --git a/mkbootimg/Android.bp b/mkbootimg/Android.bp
new file mode 100644
index 0000000..b494346
--- /dev/null
+++ b/mkbootimg/Android.bp
@@ -0,0 +1,32 @@
+// Copyright 2012 The Android Open Source Project
+
+cc_library_headers {
+ name: "libmkbootimg_abi_headers",
+ vendor_available: true,
+ export_include_dirs: ["include"],
+}
+
+cc_library_headers {
+ name: "bootimg_headers",
+ vendor_available: true,
+ export_include_dirs: ["include/bootimg"],
+ host_supported: true,
+ target: {
+ windows: {
+ enabled: true,
+ },
+ },
+}
+
+cc_library {
+ name: "libmkbootimg_abi_check",
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "mkbootimg_dummy.cpp",
+ ],
+ header_libs: ["libmkbootimg_abi_headers"],
+ export_header_lib_headers: ["libmkbootimg_abi_headers"],
+}
diff --git a/mkbootimg/include/abi_check/mkbootimg_abi_check.h b/mkbootimg/include/abi_check/mkbootimg_abi_check.h
new file mode 100644
index 0000000..d478aba
--- /dev/null
+++ b/mkbootimg/include/abi_check/mkbootimg_abi_check.h
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+#include <bootimg/bootimg.h>
+
+// This header has been created for the following reaons:
+// 1) In order for a change in a user defined type to be classified as API /
+// ABI breaking, it needs to be referenced by an 'exported interface'
+// (in this case the function mkbootimg_dummy).
+// 2) Since 'mkbootimg_dummy' needs to be exported, we need to have it
+// exposed through a public header.
+// 3) It is desirable not to pollute bootimg.h with interfaces which are not
+// 'used' in reality by on device binaries. Furthermore, bootimg.h might
+// be exported by a library in the future, so we must avoid polluting it.
+void mkbootimg_dummy(boot_img_hdr*);
diff --git a/mkbootimg/bootimg.h b/mkbootimg/include/bootimg/bootimg.h
similarity index 91%
rename from mkbootimg/bootimg.h
rename to mkbootimg/include/bootimg/bootimg.h
index 1be8c22..4311b46 100644
--- a/mkbootimg/bootimg.h
+++ b/mkbootimg/include/bootimg/bootimg.h
@@ -2,16 +2,16 @@
**
** Copyright 2007, 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
+** 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
+** 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
+** 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.
*/
@@ -34,17 +34,17 @@
struct boot_img_hdr_v0 {
uint8_t magic[BOOT_MAGIC_SIZE];
- uint32_t kernel_size; /* size in bytes */
- uint32_t kernel_addr; /* physical load addr */
+ uint32_t kernel_size; /* size in bytes */
+ uint32_t kernel_addr; /* physical load addr */
uint32_t ramdisk_size; /* size in bytes */
uint32_t ramdisk_addr; /* physical load addr */
- uint32_t second_size; /* size in bytes */
- uint32_t second_addr; /* physical load addr */
+ uint32_t second_size; /* size in bytes */
+ uint32_t second_addr; /* physical load addr */
- uint32_t tags_addr; /* physical addr for kernel tags */
- uint32_t page_size; /* flash page size we assume */
+ uint32_t tags_addr; /* physical addr for kernel tags */
+ uint32_t page_size; /* flash page size we assume */
/*
* version for the boot image header.
*/
diff --git a/mkbootimg/mkbootimg_dummy.cpp b/mkbootimg/mkbootimg_dummy.cpp
new file mode 100644
index 0000000..410d379
--- /dev/null
+++ b/mkbootimg/mkbootimg_dummy.cpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+#include <abi_check/mkbootimg_abi_check.h>
+
+void mkbootimg_dummy(boot_img_hdr* hdr) {
+ // TODO: Hack to trigger abi checks, remove this.
+ if (hdr) {
+ hdr--;
+ }
+}
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index 94465f4..ba96cc8 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -218,13 +218,20 @@
namespace.vndk.asan.permitted.paths += /data/asan/system/${LIB}/vndk-sp%VNDK_VER%/hw
namespace.vndk.asan.permitted.paths += /system/${LIB}/vndk-sp%VNDK_VER%/hw
+# The "vndk" namespace links to "default" namespace for LLNDK libs and links to
+# "sphal" namespace for vendor libs. The ordering matters. The "default"
+# namespace has higher priority than the "sphal" namespace.
+namespace.vndk.links = default,sphal
+
# When these NDK libs are required inside this namespace, then it is redirected
# to the default namespace. This is possible since their ABI is stable across
# Android releases.
-namespace.vndk.links = default
namespace.vndk.link.default.shared_libs = %LLNDK_LIBRARIES%
namespace.vndk.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
+# Allow VNDK-SP extensions to use vendor libraries
+namespace.vndk.link.sphal.allow_all_shared_libs = true
+
###############################################################################
# Namespace config for vendor processes. In O, no restriction is enforced for
# them. However, in O-MR1, access to /system/${LIB} will not be allowed to