Merge "libutils: remove whitespaces in String16.cpp and String16.h"
diff --git a/adb/Android.mk b/adb/Android.mk
index baa4985..b792bd4 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -158,7 +158,7 @@
LOCAL_SANITIZE := $(adb_target_sanitize)
LOCAL_STATIC_LIBRARIES := libadbd
-LOCAL_SHARED_LIBRARIES := libbase libcutils
+LOCAL_SHARED_LIBRARIES := liblog libbase libcutils
include $(BUILD_NATIVE_TEST)
# libdiagnose_usb
diff --git a/adb/adb_utils.cpp b/adb/adb_utils.cpp
index 474d1b4..8a16e51 100644
--- a/adb/adb_utils.cpp
+++ b/adb/adb_utils.cpp
@@ -134,7 +134,7 @@
return result;
}
-// Given a relative or absolute filepath, create the parent directory hierarchy
+// Given a relative or absolute filepath, create the directory hierarchy
// as needed. Returns true if the hierarchy is/was setup.
bool mkdirs(const std::string& path) {
// TODO: all the callers do unlink && mkdirs && adb_creat ---
@@ -157,12 +157,12 @@
return true;
}
+ const std::string parent(adb_dirname(path));
+
// If dirname returned the same path as what we passed in, don't go recursive.
// This can happen on Windows when walking up the directory hierarchy and not
// finding anything that already exists (unlike POSIX that will eventually
// find . or /).
- const std::string parent(adb_dirname(path));
-
if (parent == path) {
errno = ENOENT;
return false;
@@ -174,14 +174,14 @@
}
// Now that the parent directory hierarchy of 'path' has been ensured,
- // create parent itself.
+ // create path itself.
if (adb_mkdir(path, 0775) == -1) {
- // Can't just check for errno == EEXIST because it might be a file that
- // exists.
const int saved_errno = errno;
- if (directory_exists(parent)) {
+ // If someone else created the directory, that is ok.
+ if (directory_exists(path)) {
return true;
}
+ // There might be a pre-existing file at 'path', or there might have been some other error.
errno = saved_errno;
return false;
}
diff --git a/adb/adb_utils_test.cpp b/adb/adb_utils_test.cpp
index dfe6f20..f1ebaa1 100644
--- a/adb/adb_utils_test.cpp
+++ b/adb/adb_utils_test.cpp
@@ -112,20 +112,26 @@
}
void test_mkdirs(const std::string basepath) {
- EXPECT_TRUE(mkdirs(adb_dirname(basepath)));
- EXPECT_NE(-1, adb_creat(basepath.c_str(), 0600));
- EXPECT_FALSE(mkdirs(basepath + "/subdir/"));
+ // Test creating a directory hierarchy.
+ EXPECT_TRUE(mkdirs(basepath));
+ // Test finding an existing directory hierarchy.
+ EXPECT_TRUE(mkdirs(basepath));
+ const std::string filepath = basepath + "/file";
+ // Verify that the hierarchy was created by trying to create a file in it.
+ EXPECT_NE(-1, adb_creat(filepath.c_str(), 0600));
+ // If a file exists where we want a directory, the operation should fail.
+ EXPECT_FALSE(mkdirs(filepath));
}
TEST(adb_utils, mkdirs) {
TemporaryDir td;
// Absolute paths.
- test_mkdirs(std::string(td.path) + "/dir/subdir/file");
+ test_mkdirs(std::string(td.path) + "/dir/subdir");
// Relative paths.
ASSERT_EQ(0, chdir(td.path)) << strerror(errno);
- test_mkdirs(std::string("relative/subrel/file"));
+ test_mkdirs(std::string("relative/subrel"));
}
#if !defined(_WIN32)
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index 85ab4d1..8e76168 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -482,7 +482,7 @@
// Loops to read from stdin and push the data to the given FD.
// The argument should be a pointer to a StdinReadArgs object. This function
// will take ownership of the object and delete it when finished.
-static void* stdin_read_thread_loop(void* x) {
+static void stdin_read_thread_loop(void* x) {
std::unique_ptr<StdinReadArgs> args(reinterpret_cast<StdinReadArgs*>(x));
#if !defined(_WIN32)
@@ -586,8 +586,6 @@
}
}
}
-
- return nullptr;
}
// Returns a shell service string with the indicated arguments and command.
diff --git a/adb/services.cpp b/adb/services.cpp
index 9cbf787..75cbe5d 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -57,13 +57,11 @@
void *cookie;
};
-void *service_bootstrap_func(void *x)
-{
+static void service_bootstrap_func(void* x) {
stinfo* sti = reinterpret_cast<stinfo*>(x);
adb_thread_setname(android::base::StringPrintf("service %d", sti->fd));
sti->func(sti->fd, sti->cookie);
free(sti);
- return 0;
}
#if !ADB_HOST
diff --git a/adb/shell_service.cpp b/adb/shell_service.cpp
index d080e09..f84447f 100644
--- a/adb/shell_service.cpp
+++ b/adb/shell_service.cpp
@@ -198,7 +198,7 @@
// Opens the file at |pts_name|.
int OpenPtyChildFd(const char* pts_name, ScopedFd* error_sfd);
- static void* ThreadHandler(void* userdata);
+ static void ThreadHandler(void* userdata);
void PassDataStreams();
void WaitForExit();
@@ -465,7 +465,7 @@
return child_fd;
}
-void* Subprocess::ThreadHandler(void* userdata) {
+void Subprocess::ThreadHandler(void* userdata) {
Subprocess* subprocess = reinterpret_cast<Subprocess*>(userdata);
adb_thread_setname(android::base::StringPrintf(
@@ -475,8 +475,6 @@
D("deleting Subprocess for PID %d", subprocess->pid());
delete subprocess;
-
- return nullptr;
}
void Subprocess::PassDataStreams() {
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index 761a4c7..3bae09e 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -115,25 +115,26 @@
LeaveCriticalSection( lock );
}
-typedef void* (*adb_thread_func_t)(void* arg);
+typedef void (*adb_thread_func_t)(void* arg);
typedef HANDLE adb_thread_t;
-struct win_thread_args {
+struct adb_winthread_args {
adb_thread_func_t func;
void* arg;
};
-static unsigned __stdcall win_thread_wrapper(void* args) {
- win_thread_args thread_args = *static_cast<win_thread_args*>(args);
- delete static_cast<win_thread_args*>(args);
- void* result = thread_args.func(thread_args.arg);
- return reinterpret_cast<unsigned>(result);
+static unsigned __stdcall adb_winthread_wrapper(void* heap_args) {
+ // Move the arguments from the heap onto the thread's stack.
+ adb_winthread_args thread_args = *static_cast<adb_winthread_args*>(heap_args);
+ delete static_cast<adb_winthread_args*>(heap_args);
+ thread_args.func(thread_args.arg);
+ return 0;
}
static __inline__ bool adb_thread_create(adb_thread_func_t func, void* arg,
adb_thread_t* thread = nullptr) {
- win_thread_args* args = new win_thread_args{.func = func, .arg = arg};
- uintptr_t handle = _beginthreadex(nullptr, 0, win_thread_wrapper, args, 0, nullptr);
+ adb_winthread_args* args = new adb_winthread_args{.func = func, .arg = arg};
+ uintptr_t handle = _beginthreadex(nullptr, 0, adb_winthread_wrapper, args, 0, nullptr);
if (handle != static_cast<uintptr_t>(0)) {
if (thread) {
*thread = reinterpret_cast<HANDLE>(handle);
@@ -168,6 +169,10 @@
return true;
}
+static __inline__ void __attribute__((noreturn)) adb_thread_exit() {
+ _endthreadex(0);
+}
+
static __inline__ int adb_thread_setname(const std::string& name) {
// TODO: See https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx for how to set
// the thread name in Windows. Unfortunately, it only works during debugging, but
@@ -701,17 +706,32 @@
#define unix_write adb_write
#define unix_close adb_close
-typedef void* (*adb_thread_func_t)( void* arg );
-
+// Win32 is limited to DWORDs for thread return values; limit the POSIX systems to this as well to
+// ensure compatibility.
+typedef void (*adb_thread_func_t)(void* arg);
typedef pthread_t adb_thread_t;
+struct adb_pthread_args {
+ adb_thread_func_t func;
+ void* arg;
+};
+
+static void* adb_pthread_wrapper(void* heap_args) {
+ // Move the arguments from the heap onto the thread's stack.
+ adb_pthread_args thread_args = *reinterpret_cast<adb_pthread_args*>(heap_args);
+ delete static_cast<adb_pthread_args*>(heap_args);
+ thread_args.func(thread_args.arg);
+ return nullptr;
+}
+
static __inline__ bool adb_thread_create(adb_thread_func_t start, void* arg,
adb_thread_t* thread = nullptr) {
pthread_t temp;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, thread ? PTHREAD_CREATE_JOINABLE : PTHREAD_CREATE_DETACHED);
- errno = pthread_create(&temp, &attr, start, arg);
+ auto* pthread_args = new adb_pthread_args{.func = start, .arg = arg};
+ errno = pthread_create(&temp, &attr, adb_pthread_wrapper, pthread_args);
if (errno == 0) {
if (thread) {
*thread = temp;
@@ -731,6 +751,10 @@
return errno == 0;
}
+static __inline__ void __attribute__((noreturn)) adb_thread_exit() {
+ pthread_exit(nullptr);
+}
+
static __inline__ int adb_thread_setname(const std::string& name) {
#ifdef __APPLE__
return pthread_setname_np(name.c_str());
diff --git a/adb/sysdeps_test.cpp b/adb/sysdeps_test.cpp
index 24a0d6f..360eaa7 100644
--- a/adb/sysdeps_test.cpp
+++ b/adb/sysdeps_test.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2065 The Android Open Source Project
+ * Copyright (C) 2016 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.
@@ -20,10 +20,9 @@
#include "sysdeps.h"
-static void* increment_atomic_int(void* c) {
+static void increment_atomic_int(void* c) {
sleep(1);
reinterpret_cast<std::atomic<int>*>(c)->fetch_add(1);
- return nullptr;
}
TEST(sysdeps_thread, smoke) {
@@ -57,3 +56,14 @@
ASSERT_EQ(500, counter.load());
}
+
+TEST(sysdeps_thread, exit) {
+ adb_thread_t thread;
+ ASSERT_TRUE(adb_thread_create(
+ [](void*) {
+ adb_thread_exit();
+ for (;;) continue;
+ },
+ nullptr, &thread));
+ ASSERT_TRUE(adb_thread_join(thread));
+}
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 6020ad5..d9180bc 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -190,8 +190,7 @@
//
// read_transport thread reads data from a transport (representing a usb/tcp connection),
// and makes the main thread call handle_packet().
-static void *read_transport_thread(void *_t)
-{
+static void read_transport_thread(void* _t) {
atransport *t = reinterpret_cast<atransport*>(_t);
apacket *p;
@@ -244,13 +243,11 @@
D("%s: read_transport thread is exiting", t->serial);
kick_transport(t);
transport_unref(t);
- return 0;
}
// write_transport thread gets packets sent by the main thread (through send_packet()),
// and writes to a transport (representing a usb/tcp connection).
-static void *write_transport_thread(void *_t)
-{
+static void write_transport_thread(void* _t) {
atransport *t = reinterpret_cast<atransport*>(_t);
apacket *p;
int active = 0;
@@ -295,7 +292,6 @@
D("%s: write_transport thread is exiting, fd %d", t->serial, t->fd);
kick_transport(t);
transport_unref(t);
- return 0;
}
static void kick_transport_locked(atransport* t) {
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index d2a375a..e6e699b 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -121,8 +121,7 @@
}
#if ADB_HOST
-static void *client_socket_thread(void *x)
-{
+static void client_socket_thread(void* x) {
adb_thread_setname("client_socket_thread");
D("transport: client_socket_thread() starting");
while (true) {
@@ -135,13 +134,11 @@
}
sleep(1);
}
- return 0;
}
#else // ADB_HOST
-static void *server_socket_thread(void * arg)
-{
+static void server_socket_thread(void* arg) {
int serverfd, fd;
sockaddr_storage ss;
sockaddr *addrp = reinterpret_cast<sockaddr*>(&ss);
@@ -174,7 +171,6 @@
}
}
D("transport: server_socket_thread() exiting");
- return 0;
}
/* This is relevant only for ADB daemon running inside the emulator. */
@@ -220,14 +216,13 @@
* the transport registration is completed. That's why we need to send the
* 'start' request after the transport is registered.
*/
-static void *qemu_socket_thread(void * arg)
-{
-/* 'accept' request to the adb QEMUD service. */
-static const char _accept_req[] = "accept";
-/* 'start' request to the adb QEMUD service. */
-static const char _start_req[] = "start";
-/* 'ok' reply from the adb QEMUD service. */
-static const char _ok_resp[] = "ok";
+static void qemu_socket_thread(void* arg) {
+ /* 'accept' request to the adb QEMUD service. */
+ static const char _accept_req[] = "accept";
+ /* 'start' request to the adb QEMUD service. */
+ static const char _start_req[] = "start";
+ /* 'ok' reply from the adb QEMUD service. */
+ static const char _ok_resp[] = "ok";
const int port = (int) (uintptr_t) arg;
int res, fd;
@@ -247,7 +242,7 @@
* implement adb QEMUD service. Fall back to the old TCP way. */
D("adb service is not available. Falling back to TCP socket.");
adb_thread_create(server_socket_thread, arg);
- return 0;
+ return;
}
for(;;) {
@@ -275,21 +270,21 @@
fd = qemu_pipe_open(con_name);
if (fd < 0) {
D("adb service become unavailable.");
- return 0;
+ return;
}
} else {
D("Unable to send the '%s' request to ADB service.", _accept_req);
- return 0;
+ return;
}
}
D("transport: qemu_socket_thread() exiting");
- return 0;
+ return;
}
#endif // !ADB_HOST
void local_init(int port)
{
- void* (*func)(void *);
+ adb_thread_func_t func;
const char* debug_name = "";
#if ADB_HOST
diff --git a/adb/usb_linux.cpp b/adb/usb_linux.cpp
index ed5d2d67..500898a 100644
--- a/adb/usb_linux.cpp
+++ b/adb/usb_linux.cpp
@@ -571,7 +571,7 @@
register_usb_transport(done_usb, serial.c_str(), dev_path, done_usb->writeable);
}
-static void* device_poll_thread(void* unused) {
+static void device_poll_thread(void*) {
adb_thread_setname("device poll");
D("Created device thread");
while (true) {
@@ -580,7 +580,6 @@
kick_disconnected_devices();
sleep(1);
}
- return nullptr;
}
void usb_init() {
diff --git a/adb/usb_linux_client.cpp b/adb/usb_linux_client.cpp
index a4f1a70..c863ed2 100644
--- a/adb/usb_linux_client.cpp
+++ b/adb/usb_linux_client.cpp
@@ -232,10 +232,7 @@
},
};
-
-
-static void *usb_adb_open_thread(void *x)
-{
+static void usb_adb_open_thread(void* x) {
struct usb_handle *usb = (struct usb_handle *)x;
int fd;
@@ -270,7 +267,7 @@
}
// never gets here
- return 0;
+ abort();
}
static int usb_adb_write(usb_handle *h, const void *data, int len)
@@ -434,8 +431,7 @@
return;
}
-static void *usb_ffs_open_thread(void *x)
-{
+static void usb_ffs_open_thread(void* x) {
struct usb_handle *usb = (struct usb_handle *)x;
adb_thread_setname("usb ffs open");
@@ -462,7 +458,7 @@
}
// never gets here
- return 0;
+ abort();
}
static int usb_ffs_write(usb_handle* h, const void* data, int len) {
diff --git a/adb/usb_osx.cpp b/adb/usb_osx.cpp
index 148be1d..54d4c6c 100644
--- a/adb/usb_osx.cpp
+++ b/adb/usb_osx.cpp
@@ -400,9 +400,7 @@
return NULL;
}
-
-void* RunLoopThread(void* unused)
-{
+static void RunLoopThread(void* unused) {
adb_thread_setname("RunLoop");
InitUSB();
@@ -420,7 +418,6 @@
IONotificationPortDestroy(notificationPort);
LOG(DEBUG) << "RunLoopThread done";
- return NULL;
}
static void usb_cleanup() {
diff --git a/adb/usb_windows.cpp b/adb/usb_windows.cpp
index e79008f..8ecca37 100644
--- a/adb/usb_windows.cpp
+++ b/adb/usb_windows.cpp
@@ -97,7 +97,7 @@
/// Entry point for thread that polls (every second) for new usb interfaces.
/// This routine calls find_devices in infinite loop.
-void* device_poll_thread(void* unused);
+static void device_poll_thread(void*);
/// Initializes this module
void usb_init();
@@ -172,7 +172,7 @@
return 1;
}
-void* device_poll_thread(void* unused) {
+void device_poll_thread(void*) {
adb_thread_setname("Device Poll");
D("Created device thread");
@@ -180,8 +180,6 @@
find_devices();
adb_sleep_ms(1000);
}
-
- return NULL;
}
static LRESULT CALLBACK _power_window_proc(HWND hwnd, UINT uMsg, WPARAM wParam,
@@ -203,7 +201,7 @@
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
}
-static void* _power_notification_thread(void* unused) {
+static void _power_notification_thread(void*) {
// This uses a thread with its own window message pump to get power
// notifications. If adb runs from a non-interactive service account, this
// might not work (not sure). If that happens to not work, we could use
@@ -255,8 +253,6 @@
// shutting down. Not a big deal since the whole process will be going away
// soon anyway.
D("Power notification thread exiting");
-
- return NULL;
}
void usb_init() {
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index 31c84c7..1d16f69 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -105,33 +105,39 @@
return std::string(&temp[0], len);
}
+constexpr int32_t kUnknownBootReason = 1;
+
// A mapping from boot reason string, as read from the ro.boot.bootreason
// system property, to a unique integer ID. Viewers of log data dashboards for
// the boot_reason metric may refer to this mapping to discern the histogram
// values.
-const std::map<std::string, int> kBootReasonMap = {
- {"normal", 0},
- {"recovery", 1},
- {"reboot", 2},
- {"PowerKey", 3},
- {"hard_reset", 4},
- {"kernel_panic", 5},
- {"rpm_err", 6},
- {"hw_reset", 7},
- {"tz_err", 8},
- {"adsp_err", 9},
- {"modem_err", 10},
- {"mba_err", 11},
- {"Watchdog", 12},
- {"Panic", 13},
+const std::map<std::string, int32_t> kBootReasonMap = {
+ {"unknown", kUnknownBootReason},
+ {"normal", 2},
+ {"recovery", 3},
+ {"reboot", 4},
+ {"PowerKey", 5},
+ {"hard_reset", 6},
+ {"kernel_panic", 7},
+ {"rpm_err", 8},
+ {"hw_reset", 9},
+ {"tz_err", 10},
+ {"adsp_err", 11},
+ {"modem_err", 12},
+ {"mba_err", 13},
+ {"Watchdog", 14},
+ {"Panic", 15},
+ {"power_key", 16},
+ {"power_on", 17},
+ {"Reboot", 18},
+ {"rtc", 19},
+ {"edl", 20},
};
// Converts a string value representing the reason the system booted to an
// integer representation. This is necessary for logging the boot_reason metric
// via Tron, which does not accept non-integer buckets in histograms.
int32_t BootReasonStrToEnum(const std::string& boot_reason) {
- static const int32_t kUnknownBootReason = -1;
-
auto mapping = kBootReasonMap.find(boot_reason);
if (mapping != kBootReasonMap.end()) {
return mapping->second;
diff --git a/fs_mgr/fs_mgr_format.c b/fs_mgr/fs_mgr_format.c
index c73045d..853bf0b 100644
--- a/fs_mgr/fs_mgr_format.c
+++ b/fs_mgr/fs_mgr_format.c
@@ -33,7 +33,7 @@
static int format_ext4(char *fs_blkdev, char *fs_mnt_point)
{
- unsigned int nr_sec;
+ uint64_t dev_sz;
int fd, rc = 0;
if ((fd = open(fs_blkdev, O_WRONLY, 0644)) < 0) {
@@ -41,7 +41,7 @@
return -1;
}
- if ((ioctl(fd, BLKGETSIZE, &nr_sec)) == -1) {
+ if ((ioctl(fd, BLKGETSIZE64, &dev_sz)) == -1) {
ERROR("Cannot get block device size. %s\n", strerror(errno));
close(fd);
return -1;
@@ -49,7 +49,7 @@
/* Format the partition using the calculated length */
reset_ext4fs_info();
- info.len = ((off64_t)nr_sec * 512);
+ info.len = (off64_t)dev_sz;
/* Use make_ext4fs_internal to avoid wiping an already-wiped partition. */
rc = make_ext4fs_internal(fd, NULL, NULL, fs_mnt_point, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
diff --git a/libdiskconfig/Android.mk b/libdiskconfig/Android.mk
index 624e385..a49ce58 100644
--- a/libdiskconfig/Android.mk
+++ b/libdiskconfig/Android.mk
@@ -13,6 +13,8 @@
LOCAL_MODULE_TAGS := optional
LOCAL_SYSTEM_SHARED_LIBRARIES := libcutils liblog libc
LOCAL_CFLAGS := -Werror
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
include $(BUILD_SHARED_LIBRARY)
ifeq ($(HOST_OS),linux)
@@ -21,5 +23,7 @@
LOCAL_MODULE := libdiskconfig_host
LOCAL_MODULE_TAGS := optional
LOCAL_CFLAGS := -O2 -g -W -Wall -Werror -D_LARGEFILE64_SOURCE
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
include $(BUILD_HOST_STATIC_LIBRARY)
endif # HOST_OS == linux
diff --git a/include/diskconfig/diskconfig.h b/libdiskconfig/include/diskconfig/diskconfig.h
similarity index 100%
rename from include/diskconfig/diskconfig.h
rename to libdiskconfig/include/diskconfig/diskconfig.h
diff --git a/liblog/fake_log_device.c b/liblog/fake_log_device.c
index 5f7a078..a6d9a34 100644
--- a/liblog/fake_log_device.c
+++ b/liblog/fake_log_device.c
@@ -689,6 +689,17 @@
return redirectOpen(pathName, flags);
}
+/*
+ * The logger API has no means or need to 'stop' or 'close' using the logs,
+ * and as such, there is no way for that 'stop' or 'close' to translate into
+ * a close operation to the fake log handler. fakeLogClose is provided for
+ * completeness only.
+ *
+ * We have no intention of adding a log close operation as it would complicate
+ * every user of the logging API with no gain since the only valid place to
+ * call is in the exit handler. Logging can continue in the exit handler to
+ * help debug HOST tools ...
+ */
int fakeLogClose(int fd)
{
/* Assume that open() was called first. */
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index 8d9c5a3..f8d4c4c 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -173,7 +173,7 @@
return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
}
-TEST(liblog, __android_log_bswrite) {
+static void bswrite_test(const char *message) {
struct logger_list *logger_list;
pid_t pid = getpid();
@@ -181,10 +181,30 @@
ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
- static const char buffer[] = "Hello World";
log_time ts(android_log_clockid());
- ASSERT_LT(0, __android_log_bswrite(0, buffer));
+ ASSERT_LT(0, __android_log_bswrite(0, message));
+ size_t num_lines = 1, size = 0, length = 0, total = 0;
+ const char *cp = message;
+ while (*cp) {
+ if (*cp == '\n') {
+ if (cp[1]) {
+ ++num_lines;
+ }
+ } else {
+ ++size;
+ }
+ ++cp;
+ ++total;
+ ++length;
+ if ((LOGGER_ENTRY_MAX_PAYLOAD - 4 - 1 - 4) <= length) {
+ break;
+ }
+ }
+ while (*cp) {
+ ++cp;
+ ++total;
+ }
usleep(1000000);
int count = 0;
@@ -199,7 +219,7 @@
if ((log_msg.entry.sec < (ts.tv_sec - 1))
|| ((ts.tv_sec + 1) < log_msg.entry.sec)
- || (log_msg.entry.len != (4 + 1 + 4 + sizeof(buffer) - 1))
+ || ((size_t)log_msg.entry.len != (4 + 1 + 4 + length))
|| (log_msg.id() != LOG_ID_EVENTS)) {
continue;
}
@@ -210,22 +230,22 @@
continue;
}
- int len = get4LE(eventData + 4 + 1);
- if (len == (sizeof(buffer) - 1)) {
+ size_t len = get4LE(eventData + 4 + 1);
+ if (len == total) {
++count;
AndroidLogFormat *logformat = android_log_format_new();
EXPECT_TRUE(NULL != logformat);
AndroidLogEntry entry;
char msgBuf[1024];
- EXPECT_EQ(0, android_log_processBinaryLogBuffer(&log_msg.entry_v1,
- &entry,
- NULL,
- msgBuf,
- sizeof(msgBuf)));
- fflush(stderr);
- EXPECT_EQ((int)(19 + sizeof(buffer)),
- android_log_printLogLine(logformat, fileno(stderr), &entry));
+ int processBinaryLogBuffer = android_log_processBinaryLogBuffer(
+ &log_msg.entry_v1, &entry, NULL, msgBuf, sizeof(msgBuf));
+ EXPECT_EQ((length == total) ? 0 : -1, processBinaryLogBuffer);
+ if (processBinaryLogBuffer == 0) {
+ fflush(stderr);
+ EXPECT_EQ((int)((20 * num_lines) + size),
+ android_log_printLogLine(logformat, fileno(stderr), &entry));
+ }
android_log_format_free(logformat);
}
}
@@ -235,131 +255,27 @@
android_logger_list_close(logger_list);
}
-TEST(liblog, __android_log_bswrite__empty_string) {
- struct logger_list *logger_list;
-
- pid_t pid = getpid();
-
- ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
- LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
-
- static const char buffer[] = "";
- log_time ts(android_log_clockid());
-
- ASSERT_LT(0, __android_log_bswrite(0, buffer));
- usleep(1000000);
-
- int count = 0;
-
- for (;;) {
- log_msg log_msg;
- if (android_logger_list_read(logger_list, &log_msg) <= 0) {
- break;
- }
-
- ASSERT_EQ(log_msg.entry.pid, pid);
-
- if ((log_msg.entry.sec < (ts.tv_sec - 1))
- || ((ts.tv_sec + 1) < log_msg.entry.sec)
- || (log_msg.entry.len != (4 + 1 + 4))
- || (log_msg.id() != LOG_ID_EVENTS)) {
- continue;
- }
-
- char *eventData = log_msg.msg();
-
- if (eventData[4] != EVENT_TYPE_STRING) {
- continue;
- }
-
- int len = get4LE(eventData + 4 + 1);
- if (len == (sizeof(buffer) - 1)) {
- ++count;
-
- AndroidLogFormat *logformat = android_log_format_new();
- EXPECT_TRUE(NULL != logformat);
- AndroidLogEntry entry;
- char msgBuf[1024];
- EXPECT_EQ(0, android_log_processBinaryLogBuffer(&log_msg.entry_v1,
- &entry,
- NULL,
- msgBuf,
- sizeof(msgBuf)));
- fflush(stderr);
- EXPECT_EQ((int)(19 + sizeof(buffer)),
- android_log_printLogLine(logformat, fileno(stderr), &entry));
- android_log_format_free(logformat);
- }
- }
-
- EXPECT_EQ(1, count);
-
- android_logger_list_close(logger_list);
+TEST(liblog, __android_log_bswrite_and_print) {
+ bswrite_test("Hello World");
}
-TEST(liblog, __android_log_bswrite__newline_prefix) {
- struct logger_list *logger_list;
-
- pid_t pid = getpid();
-
- ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
- LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
-
- static const char buffer[] = "\nHello World\n";
- log_time ts(android_log_clockid());
-
- ASSERT_LT(0, __android_log_bswrite(0, buffer));
- usleep(1000000);
-
- int count = 0;
-
- for (;;) {
- log_msg log_msg;
- if (android_logger_list_read(logger_list, &log_msg) <= 0) {
- break;
- }
-
- ASSERT_EQ(log_msg.entry.pid, pid);
-
- if ((log_msg.entry.sec < (ts.tv_sec - 1))
- || ((ts.tv_sec + 1) < log_msg.entry.sec)
- || (log_msg.entry.len != (4 + 1 + 4 + sizeof(buffer) - 1))
- || (log_msg.id() != LOG_ID_EVENTS)) {
- continue;
- }
-
- char *eventData = log_msg.msg();
-
- if (eventData[4] != EVENT_TYPE_STRING) {
- continue;
- }
-
- int len = get4LE(eventData + 4 + 1);
- if (len == (sizeof(buffer) - 1)) {
- ++count;
-
- AndroidLogFormat *logformat = android_log_format_new();
- EXPECT_TRUE(NULL != logformat);
- AndroidLogEntry entry;
- char msgBuf[1024];
- EXPECT_EQ(0, android_log_processBinaryLogBuffer(&log_msg.entry_v1,
- &entry,
- NULL,
- msgBuf,
- sizeof(msgBuf)));
- fflush(stderr);
- EXPECT_EQ((int)(19 + 19 - 1 + sizeof(buffer)),
- android_log_printLogLine(logformat, fileno(stderr), &entry));
- android_log_format_free(logformat);
- }
- }
-
- EXPECT_EQ(1, count);
-
- android_logger_list_close(logger_list);
+TEST(liblog, __android_log_bswrite_and_print__empty_string) {
+ bswrite_test("");
}
-TEST(liblog, __android_log_buf_write__newline_prefix) {
+TEST(liblog, __android_log_bswrite_and_print__newline_prefix) {
+ bswrite_test("\nHello World\n");
+}
+
+TEST(liblog, __android_log_bswrite_and_print__newline_space_prefix) {
+ bswrite_test("\n Hello World \n");
+}
+
+TEST(liblog, __android_log_bswrite_and_print__multiple_newline) {
+ bswrite_test("one\ntwo\nthree\nfour\nfive\nsix\nseven\neight\nnine\nten");
+}
+
+static void buf_write_test(const char *message) {
struct logger_list *logger_list;
pid_t pid = getpid();
@@ -368,11 +284,26 @@
LOG_ID_MAIN, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
static const char tag[] = "TEST__android_log_buf_write";
- static const char buffer[] = "\nHello World\n";
log_time ts(android_log_clockid());
EXPECT_LT(0, __android_log_buf_write(LOG_ID_MAIN, ANDROID_LOG_INFO,
- tag, buffer));
+ tag, message));
+ size_t num_lines = 1, size = 0, length = 0;
+ const char *cp = message;
+ while (*cp) {
+ if (*cp == '\n') {
+ if (cp[1]) {
+ ++num_lines;
+ }
+ } else {
+ ++size;
+ }
+ ++length;
+ if ((LOGGER_ENTRY_MAX_PAYLOAD - 2 - sizeof(tag)) <= length) {
+ break;
+ }
+ ++cp;
+ }
usleep(1000000);
int count = 0;
@@ -387,7 +318,7 @@
if ((log_msg.entry.sec < (ts.tv_sec - 1))
|| ((ts.tv_sec + 1) < log_msg.entry.sec)
- || (log_msg.entry.len != (sizeof(tag) + sizeof(buffer) + 1))
+ || ((size_t)log_msg.entry.len != (sizeof(tag) + length + 2))
|| (log_msg.id() != LOG_ID_MAIN)) {
continue;
}
@@ -397,11 +328,14 @@
AndroidLogFormat *logformat = android_log_format_new();
EXPECT_TRUE(NULL != logformat);
AndroidLogEntry entry;
- EXPECT_EQ(0, android_log_processLogBuffer(&log_msg.entry_v1,
- &entry));
- fflush(stderr);
- EXPECT_EQ((int)(11 + 11 + sizeof(tag) + sizeof(tag) + sizeof(buffer) - 3),
- android_log_printLogLine(logformat, fileno(stderr), &entry));
+ int processLogBuffer = android_log_processLogBuffer(&log_msg.entry_v1,
+ &entry);
+ EXPECT_EQ(0, processLogBuffer);
+ if (processLogBuffer == 0) {
+ fflush(stderr);
+ EXPECT_EQ((int)(((11 + sizeof(tag)) * num_lines) + size),
+ android_log_printLogLine(logformat, fileno(stderr), &entry));
+ }
android_log_format_free(logformat);
}
@@ -410,6 +344,18 @@
android_logger_list_close(logger_list);
}
+TEST(liblog, __android_log_buf_write_and_print__empty) {
+ buf_write_test("");
+}
+
+TEST(liblog, __android_log_buf_write_and_print__newline_prefix) {
+ buf_write_test("\nHello World\n");
+}
+
+TEST(liblog, __android_log_buf_write_and_print__newline_space_prefix) {
+ buf_write_test("\n Hello World \n");
+}
+
TEST(liblog, __security) {
static const char persist_key[] = "persist.logd.security";
static const char readonly_key[] = "ro.device_owner";
@@ -1691,6 +1637,14 @@
android_logger_list_close(logger_list);
}
+TEST(liblog, __android_log_bswrite_and_print___max) {
+ bswrite_test(max_payload_buf);
+}
+
+TEST(liblog, __android_log_buf_write_and_print__max) {
+ buf_write_test(max_payload_buf);
+}
+
TEST(liblog, android_errorWriteLog__android_logger_list_read__success) {
const int TAG = 123456785;
const char SUBTAG[] = "test-subtag";
diff --git a/libmemtrack/Android.mk b/libmemtrack/Android.mk
index 7b170f5..ffc7244 100644
--- a/libmemtrack/Android.mk
+++ b/libmemtrack/Android.mk
@@ -5,6 +5,8 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES := memtrack.c
LOCAL_MODULE := libmemtrack
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
LOCAL_C_INCLUDES += hardware/libhardware/include
LOCAL_SHARED_LIBRARIES := libhardware liblog
LOCAL_CFLAGS := -Wall -Werror
diff --git a/include/memtrack/memtrack.h b/libmemtrack/include/memtrack/memtrack.h
similarity index 98%
rename from include/memtrack/memtrack.h
rename to libmemtrack/include/memtrack/memtrack.h
index 3917300..8c0ab89 100644
--- a/include/memtrack/memtrack.h
+++ b/libmemtrack/include/memtrack/memtrack.h
@@ -19,7 +19,6 @@
#include <sys/types.h>
#include <stddef.h>
-#include <cutils/compiler.h>
#ifdef __cplusplus
extern "C" {
diff --git a/libnativeloader/Android.mk b/libnativeloader/Android.mk
index 5e65c4c..6c064c7 100644
--- a/libnativeloader/Android.mk
+++ b/libnativeloader/Android.mk
@@ -17,7 +17,8 @@
LOCAL_CPPFLAGS := -std=gnu++14 -fvisibility=hidden
LOCAL_LDFLAGS := -ldl
LOCAL_MULTILIB := both
-
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
include $(BUILD_SHARED_LIBRARY)
# Shared library for host
@@ -34,7 +35,8 @@
LOCAL_CPPFLAGS := -std=gnu++14 -fvisibility=hidden
LOCAL_LDFLAGS := -ldl
LOCAL_MULTILIB := both
-
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
include $(BUILD_HOST_SHARED_LIBRARY)
# Static library for host
@@ -50,5 +52,6 @@
LOCAL_CPPFLAGS := -std=gnu++14 -fvisibility=hidden
LOCAL_LDFLAGS := -ldl
LOCAL_MULTILIB := both
-
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
include $(BUILD_HOST_STATIC_LIBRARY)
diff --git a/include/nativeloader/native_loader.h b/libnativeloader/include/nativeloader/native_loader.h
similarity index 100%
rename from include/nativeloader/native_loader.h
rename to libnativeloader/include/nativeloader/native_loader.h
diff --git a/libnetutils/Android.mk b/libnetutils/Android.mk
index 2060df4..281b6c8 100644
--- a/libnetutils/Android.mk
+++ b/libnetutils/Android.mk
@@ -16,6 +16,9 @@
LOCAL_CFLAGS := -Werror
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
diff --git a/include/netutils/dhcp.h b/libnetutils/include/netutils/dhcp.h
similarity index 100%
rename from include/netutils/dhcp.h
rename to libnetutils/include/netutils/dhcp.h
diff --git a/include/netutils/ifc.h b/libnetutils/include/netutils/ifc.h
similarity index 100%
rename from include/netutils/ifc.h
rename to libnetutils/include/netutils/ifc.h
diff --git a/logd/Android.mk b/logd/Android.mk
index feca8d5..203943c 100644
--- a/logd/Android.mk
+++ b/logd/Android.mk
@@ -42,6 +42,10 @@
LOCAL_CFLAGS := -Werror $(event_flag)
+ifeq ($(TARGET_BUILD_VARIANT),user)
+LOCAL_CFLAGS += -DAUDITD_ENFORCE_INTEGRITY=true
+endif
+
include $(BUILD_EXECUTABLE)
include $(call first-makefiles-under,$(LOCAL_PATH))
diff --git a/logd/LogAudit.cpp b/logd/LogAudit.cpp
index 143fb04..fffc9ba 100644
--- a/logd/LogAudit.cpp
+++ b/logd/LogAudit.cpp
@@ -24,6 +24,7 @@
#include <sys/uio.h>
#include <syslog.h>
+#include <cutils/properties.h>
#include <log/logger.h>
#include <private/android_filesystem_config.h>
#include <private/android_logger.h>
@@ -32,6 +33,10 @@
#include "LogAudit.h"
#include "LogKlog.h"
+#ifndef AUDITD_ENFORCE_INTEGRITY
+#define AUDITD_ENFORCE_INTEGRITY false
+#endif
+
#define KMSG_PRIORITY(PRI) \
'<', \
'0' + LOG_MAKEPRI(LOG_AUTH, LOG_PRI(PRI)) / 10, \
@@ -43,11 +48,10 @@
logbuf(buf),
reader(reader),
fdDmesg(fdDmesg),
+ policyLoaded(false),
+ rebootToSafeMode(false),
initialized(false) {
- static const char auditd_message[] = { KMSG_PRIORITY(LOG_INFO),
- 'l', 'o', 'g', 'd', '.', 'a', 'u', 'd', 'i', 't', 'd', ':',
- ' ', 's', 't', 'a', 'r', 't', '\n' };
- write(fdDmesg, auditd_message, sizeof(auditd_message));
+ logToDmesg("start");
}
bool LogAudit::onDataAvailable(SocketClient *cli) {
@@ -73,6 +77,46 @@
return true;
}
+void LogAudit::logToDmesg(const std::string& str)
+{
+ static const char prefix[] = { KMSG_PRIORITY(LOG_INFO),
+ 'l', 'o', 'g', 'd', '.', 'a', 'u', 'd', 'i', 't', 'd', ':',
+ ' ', '\0' };
+ std::string message = prefix + str + "\n";
+ write(fdDmesg, message.c_str(), message.length());
+}
+
+std::string LogAudit::getProperty(const std::string& name)
+{
+ char value[PROP_VALUE_MAX] = {0};
+ property_get(name.c_str(), value, "");
+ return value;
+}
+
+void LogAudit::enforceIntegrity() {
+ if (!AUDITD_ENFORCE_INTEGRITY) {
+ logToDmesg("integrity enforcement suppressed; not rebooting");
+ } else if (rebootToSafeMode) {
+ if (getProperty("persist.sys.safemode") == "1") {
+ logToDmesg("integrity enforcement suppressed; in safe mode");
+ return;
+ }
+
+ logToDmesg("enforcing integrity; rebooting to safe mode");
+ property_set("persist.sys.safemode", "1");
+
+ std::string buildDate = getProperty("ro.build.date.utc");
+ if (!buildDate.empty()) {
+ property_set("persist.sys.audit_safemode", buildDate.c_str());
+ }
+
+ property_set("sys.powerctl", "reboot");
+ } else {
+ logToDmesg("enforcing integrity: rebooting to recovery");
+ property_set("sys.powerctl", "reboot,recovery");
+ }
+}
+
int LogAudit::logPrint(const char *fmt, ...) {
if (fmt == NULL) {
return -EINVAL;
@@ -94,7 +138,27 @@
memmove(cp, cp + 1, strlen(cp + 1) + 1);
}
- bool info = strstr(str, " permissive=1") || strstr(str, " policy loaded ");
+ bool loaded = strstr(str, " policy loaded ");
+
+ if (loaded) {
+ if (policyLoaded) {
+ // SELinux policy changes are not allowed
+ enforceIntegrity();
+ } else {
+ logToDmesg("policy loaded");
+ policyLoaded = true;
+ }
+ }
+
+ bool permissive = strstr(str, " enforcing=0") ||
+ strstr(str, " permissive=1");
+
+ if (permissive) {
+ // SELinux in permissive mode is not allowed
+ enforceIntegrity();
+ }
+
+ bool info = loaded || permissive;
if ((fdDmesg >= 0) && initialized) {
struct iovec iov[3];
static const char log_info[] = { KMSG_PRIORITY(LOG_INFO) };
diff --git a/logd/LogAudit.h b/logd/LogAudit.h
index 8a82630..455ed58 100644
--- a/logd/LogAudit.h
+++ b/logd/LogAudit.h
@@ -24,12 +24,15 @@
LogBuffer *logbuf;
LogReader *reader;
int fdDmesg;
+ bool policyLoaded;
+ bool rebootToSafeMode;
bool initialized;
public:
LogAudit(LogBuffer *buf, LogReader *reader, int fdDmesg);
int log(char *buf, size_t len);
bool isMonotonic() { return logbuf->isMonotonic(); }
+ void allowSafeMode(bool allow = true) { rebootToSafeMode = allow; }
protected:
virtual bool onDataAvailable(SocketClient *cli);
@@ -38,6 +41,9 @@
static int getLogSocket();
int logPrint(const char *fmt, ...)
__attribute__ ((__format__ (__printf__, 2, 3)));
+ void logToDmesg(const std::string& str);
+ std::string getProperty(const std::string& name);
+ void enforceIntegrity();
};
#endif
diff --git a/logd/README.property b/logd/README.property
index 6200d3e..4bc5541 100644
--- a/logd/README.property
+++ b/logd/README.property
@@ -1,7 +1,6 @@
The properties that logd responds to are:
name type default description
-ro.logd.auditd bool true Enable selinux audit daemon
ro.logd.auditd.dmesg bool true selinux audit messages duplicated and
sent on to dmesg log
persist.logd.security bool false Enable security buffer.
diff --git a/logd/main.cpp b/logd/main.cpp
index bef40c7..f4d7464 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -245,6 +245,7 @@
static sem_t reinit;
static bool reinit_running = false;
static LogBuffer *logBuf = NULL;
+static LogAudit *logAudit = NULL;
static bool package_list_parser_cb(pkg_info *info, void * /* userdata */) {
@@ -292,6 +293,10 @@
logBuf->init();
logBuf->initPrune(NULL);
}
+
+ if (logAudit) {
+ logAudit->allowSafeMode();
+ }
}
return NULL;
@@ -512,25 +517,19 @@
// initiated log messages. New log entries are added to LogBuffer
// and LogReader is notified to send updates to connected clients.
- bool auditd = property_get_bool("logd.auditd",
- BOOL_DEFAULT_TRUE |
- BOOL_DEFAULT_FLAG_PERSIST);
- LogAudit *al = NULL;
- if (auditd) {
- al = new LogAudit(logBuf, reader,
- property_get_bool("logd.auditd.dmesg",
- BOOL_DEFAULT_TRUE |
- BOOL_DEFAULT_FLAG_PERSIST)
- ? fdDmesg
- : -1);
- }
+ logAudit = new LogAudit(logBuf, reader,
+ property_get_bool("logd.auditd.dmesg",
+ BOOL_DEFAULT_TRUE |
+ BOOL_DEFAULT_FLAG_PERSIST)
+ ? fdDmesg
+ : -1);
LogKlog *kl = NULL;
if (klogd) {
- kl = new LogKlog(logBuf, reader, fdDmesg, fdPmesg, al != NULL);
+ kl = new LogKlog(logBuf, reader, fdDmesg, fdPmesg, logAudit != NULL);
}
- readDmesg(al, kl);
+ readDmesg(logAudit, kl);
// failure is an option ... messages are in dmesg (required by standard)
@@ -538,8 +537,9 @@
delete kl;
}
- if (al && al->startListener()) {
- delete al;
+ if (logAudit && logAudit->startListener()) {
+ delete logAudit;
+ logAudit = NULL;
}
TEMP_FAILURE_RETRY(pause());
diff --git a/logwrapper/logwrap.c b/logwrapper/logwrap.c
index 28d6de7..ccbe0bf 100644
--- a/logwrapper/logwrap.c
+++ b/logwrapper/logwrap.c
@@ -408,7 +408,7 @@
if (poll_fds[0].revents & POLLHUP) {
int ret;
- ret = waitpid(pid, &status, WNOHANG);
+ ret = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
if (ret < 0) {
rc = errno;
ALOG(LOG_ERROR, "logwrap", "waitpid failed with %s\n", strerror(errno));
diff --git a/metricsd/.clang-format b/metricsd/.clang-format
deleted file mode 100644
index c98efc2..0000000
--- a/metricsd/.clang-format
+++ /dev/null
@@ -1,10 +0,0 @@
-BasedOnStyle: Google
-AllowShortFunctionsOnASingleLine: Inline
-AllowShortIfStatementsOnASingleLine: false
-AllowShortLoopsOnASingleLine: false
-BinPackArguments: false
-BinPackParameters: false
-CommentPragmas: NOLINT:.*
-DerivePointerAlignment: false
-PointerAlignment: Left
-TabWidth: 2
diff --git a/metricsd/.clang-format b/metricsd/.clang-format
new file mode 120000
index 0000000..f9066d4
--- /dev/null
+++ b/metricsd/.clang-format
@@ -0,0 +1 @@
+../../../build/tools/brillo-clang-format
\ No newline at end of file
diff --git a/sdcard/Android.mk b/sdcard/Android.mk
index c5f3d1d..2d04a7f 100644
--- a/sdcard/Android.mk
+++ b/sdcard/Android.mk
@@ -5,6 +5,6 @@
LOCAL_SRC_FILES := sdcard.c
LOCAL_MODULE := sdcard
LOCAL_CFLAGS := -Wall -Wno-unused-parameter -Werror
-LOCAL_SHARED_LIBRARIES := libcutils libpackagelistparser
+LOCAL_SHARED_LIBRARIES := liblog libcutils libpackagelistparser
include $(BUILD_EXECUTABLE)
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index 9ade759..fc2898e 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -55,6 +55,7 @@
LOCAL_CONLYFLAGS += -std=gnu99
LOCAL_SHARED_LIBRARIES := \
+ liblog \
libcutils \
libselinux \