Merge changes I9d94e252,If4a543d3,I0af7cda9
* changes:
remount: Remove fs_mgr_overlayfs_scratch_device()
remount: Refactor fs_mgr_overlayfs_teardown
remount: Do not run the create-scratch logic on older devices.
diff --git a/adb/daemon/usb_ffs.cpp b/adb/daemon/usb_ffs.cpp
index 338d776..b19fa5d 100644
--- a/adb/daemon/usb_ffs.cpp
+++ b/adb/daemon/usb_ffs.cpp
@@ -84,7 +84,7 @@
using usb_os_desc_guid_t = usb_os_desc_ext_prop<20, 39>;
usb_os_desc_guid_t os_desc_guid = {
.bPropertyName = "DeviceInterfaceGUID",
- .bProperty = "{64379D6C-D531-4BED-BBEC-5A16FC07D6BC}",
+ .bProperty = "{F72FE0D4-CBCB-407D-8814-9ED673D0DD6B}",
};
struct usb_ext_prop_values {
diff --git a/base/include/android-base/test_utils.h b/base/include/android-base/test_utils.h
index b20f278..f3d7cb0 100644
--- a/base/include/android-base/test_utils.h
+++ b/base/include/android-base/test_utils.h
@@ -53,30 +53,34 @@
CapturedStdout() : CapturedStdFd(STDOUT_FILENO) {}
};
-#define ASSERT_MATCH(str, pattern) \
- do { \
- if (!std::regex_search((str), std::regex((pattern)))) { \
- FAIL() << "regex mismatch: expected " << (pattern) << " in:\n" << (str); \
- } \
+#define ASSERT_MATCH(str, pattern) \
+ do { \
+ auto __s = (str); \
+ if (!std::regex_search(__s, std::regex((pattern)))) { \
+ FAIL() << "regex mismatch: expected " << (pattern) << " in:\n" << __s; \
+ } \
} while (0)
-#define ASSERT_NOT_MATCH(str, pattern) \
- do { \
- if (std::regex_search((str), std::regex((pattern)))) { \
- FAIL() << "regex mismatch: expected to not find " << (pattern) << " in:\n" << (str); \
- } \
+#define ASSERT_NOT_MATCH(str, pattern) \
+ do { \
+ auto __s = (str); \
+ if (std::regex_search(__s, std::regex((pattern)))) { \
+ FAIL() << "regex mismatch: expected to not find " << (pattern) << " in:\n" << __s; \
+ } \
} while (0)
-#define EXPECT_MATCH(str, pattern) \
- do { \
- if (!std::regex_search((str), std::regex((pattern)))) { \
- ADD_FAILURE() << "regex mismatch: expected " << (pattern) << " in:\n" << (str); \
- } \
+#define EXPECT_MATCH(str, pattern) \
+ do { \
+ auto __s = (str); \
+ if (!std::regex_search(__s, std::regex((pattern)))) { \
+ ADD_FAILURE() << "regex mismatch: expected " << (pattern) << " in:\n" << __s; \
+ } \
} while (0)
-#define EXPECT_NOT_MATCH(str, pattern) \
- do { \
- if (std::regex_search((str), std::regex((pattern)))) { \
- ADD_FAILURE() << "regex mismatch: expected to not find " << (pattern) << " in:\n" << (str); \
- } \
+#define EXPECT_NOT_MATCH(str, pattern) \
+ do { \
+ auto __s = (str); \
+ if (std::regex_search(__s, std::regex((pattern)))) { \
+ ADD_FAILURE() << "regex mismatch: expected to not find " << (pattern) << " in:\n" << __s; \
+ } \
} while (0)
diff --git a/liblog/Android.bp b/liblog/Android.bp
index 656d4dd..de0c636 100644
--- a/liblog/Android.bp
+++ b/liblog/Android.bp
@@ -17,7 +17,6 @@
liblog_sources = [
"log_event_list.cpp",
"log_event_write.cpp",
- "logger_lock.cpp",
"logger_name.cpp",
"logger_read.cpp",
"logger_write.cpp",
diff --git a/liblog/fake_log_device.cpp b/liblog/fake_log_device.cpp
index 4143fa6..fb3b9bc 100644
--- a/liblog/fake_log_device.cpp
+++ b/liblog/fake_log_device.cpp
@@ -48,21 +48,16 @@
#define TRACE(...) ((void)0)
#endif
-static int FakeAvailable(log_id_t);
-static int FakeOpen();
static void FakeClose();
static int FakeWrite(log_id_t log_id, struct timespec* ts, struct iovec* vec, size_t nr);
struct android_log_transport_write fakeLoggerWrite = {
- .name = "fake",
- .logMask = 0,
- .available = FakeAvailable,
- .open = FakeOpen,
.close = FakeClose,
.write = FakeWrite,
};
typedef struct LogState {
+ bool initialized = false;
/* global minimum priority */
int global_min_priority;
@@ -76,19 +71,8 @@
} tagSet[kTagSetSize];
} LogState;
-/*
- * Locking. Since we're emulating a device, we need to be prepared
- * to have multiple callers at the same time. This lock is used
- * to both protect the fd list and to prevent LogStates from being
- * freed out from under a user.
- */
-std::mutex mutex;
-
static LogState log_state;
-
-static int FakeAvailable(log_id_t) {
- return 0;
-}
+static std::mutex fake_log_mutex;
/*
* Configure logging based on ANDROID_LOG_TAGS environment variable. We
@@ -103,8 +87,8 @@
* We also want to check ANDROID_PRINTF_LOG to determine how the output
* will look.
*/
-int FakeOpen() {
- std::lock_guard guard{mutex};
+void InitializeLogStateLocked() {
+ log_state.initialized = true;
/* global min priority defaults to "info" level */
log_state.global_min_priority = ANDROID_LOG_INFO;
@@ -129,7 +113,7 @@
}
if (i == kMaxTagLen) {
TRACE("ERROR: env tag too long (%d chars max)\n", kMaxTagLen - 1);
- return 0;
+ return;
}
tagName[i] = '\0';
@@ -180,7 +164,7 @@
if (*tags != '\0' && !isspace(*tags)) {
TRACE("ERROR: garbage in tag env; expected whitespace\n");
TRACE(" env='%s'\n", tags);
- return 0;
+ return;
}
}
@@ -224,7 +208,6 @@
}
log_state.output_format = format;
- return 0;
}
/*
@@ -474,7 +457,11 @@
* Also guarantees that only one thread is in showLog() at a given
* time (if it matters).
*/
- std::lock_guard guard{mutex};
+ auto lock = std::lock_guard{fake_log_mutex};
+
+ if (!log_state.initialized) {
+ InitializeLogStateLocked();
+ }
if (log_id == LOG_ID_EVENTS || log_id == LOG_ID_STATS || log_id == LOG_ID_SECURITY) {
TRACE("%s: ignoring binary log\n", android_log_id_to_name(log_id));
@@ -532,7 +519,7 @@
* help debug HOST tools ...
*/
static void FakeClose() {
- std::lock_guard guard{mutex};
+ auto lock = std::lock_guard{fake_log_mutex};
memset(&log_state, 0, sizeof(log_state));
}
diff --git a/liblog/logd_writer.cpp b/liblog/logd_writer.cpp
index a22c3be..3c6eb69 100644
--- a/liblog/logd_writer.cpp
+++ b/liblog/logd_writer.cpp
@@ -30,97 +30,76 @@
#include <time.h>
#include <unistd.h>
+#include <shared_mutex>
+
#include <cutils/sockets.h>
#include <private/android_filesystem_config.h>
#include <private/android_logger.h>
#include "log_portability.h"
#include "logger.h"
+#include "rwlock.h"
#include "uio.h"
-static int logdAvailable(log_id_t LogId);
-static int logdOpen();
-static void logdClose();
-static int logdWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr);
+static int LogdWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr);
+static void LogdClose();
struct android_log_transport_write logdLoggerWrite = {
- .name = "logd",
- .logMask = 0,
- .context.sock = -EBADF,
- .available = logdAvailable,
- .open = logdOpen,
- .close = logdClose,
- .write = logdWrite,
+ .close = LogdClose,
+ .write = LogdWrite,
};
-/* log_init_lock assumed */
-static int logdOpen() {
- int i, ret = 0;
+static int logd_socket;
+static RwLock logd_socket_lock;
- i = atomic_load(&logdLoggerWrite.context.sock);
- if (i < 0) {
- int sock = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0));
- if (sock < 0) {
- ret = -errno;
- } else {
- struct sockaddr_un un;
- memset(&un, 0, sizeof(struct sockaddr_un));
- un.sun_family = AF_UNIX;
- strcpy(un.sun_path, "/dev/socket/logdw");
-
- if (TEMP_FAILURE_RETRY(connect(sock, (struct sockaddr*)&un, sizeof(struct sockaddr_un))) <
- 0) {
- ret = -errno;
- switch (ret) {
- case -ENOTCONN:
- case -ECONNREFUSED:
- case -ENOENT:
- i = atomic_exchange(&logdLoggerWrite.context.sock, ret);
- [[fallthrough]];
- default:
- break;
- }
- close(sock);
- } else {
- ret = atomic_exchange(&logdLoggerWrite.context.sock, sock);
- if ((ret >= 0) && (ret != sock)) {
- close(ret);
- }
- ret = 0;
- }
- }
+static void OpenSocketLocked() {
+ logd_socket = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0));
+ if (logd_socket <= 0) {
+ return;
}
- return ret;
-}
+ sockaddr_un un = {};
+ un.sun_family = AF_UNIX;
+ strcpy(un.sun_path, "/dev/socket/logdw");
-static void __logdClose(int negative_errno) {
- int sock = atomic_exchange(&logdLoggerWrite.context.sock, negative_errno);
- if (sock >= 0) {
- close(sock);
+ if (TEMP_FAILURE_RETRY(
+ connect(logd_socket, reinterpret_cast<sockaddr*>(&un), sizeof(sockaddr_un))) < 0) {
+ close(logd_socket);
+ logd_socket = 0;
}
}
-static void logdClose() {
- __logdClose(-EBADF);
+static void OpenSocket() {
+ auto lock = std::unique_lock{logd_socket_lock};
+ if (logd_socket > 0) {
+ // Someone raced us and opened the socket already.
+ return;
+ }
+
+ OpenSocketLocked();
}
-static int logdAvailable(log_id_t logId) {
- if (logId >= LOG_ID_MAX || logId == LOG_ID_KERNEL) {
- return -EINVAL;
+static void ResetSocket(int old_socket) {
+ auto lock = std::unique_lock{logd_socket_lock};
+ if (old_socket != logd_socket) {
+ // Someone raced us and reset the socket already.
+ return;
}
- if (atomic_load(&logdLoggerWrite.context.sock) < 0) {
- if (access("/dev/socket/logdw", W_OK) == 0) {
- return 0;
- }
- return -EBADF;
- }
- return 1;
+ close(logd_socket);
+ logd_socket = 0;
+ OpenSocketLocked();
}
-static int logdWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr) {
+static void LogdClose() {
+ auto lock = std::unique_lock{logd_socket_lock};
+ if (logd_socket > 0) {
+ close(logd_socket);
+ }
+ logd_socket = 0;
+}
+
+static int LogdWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr) {
ssize_t ret;
- int sock;
static const unsigned headerLength = 1;
struct iovec newVec[nr + headerLength];
android_log_header_t header;
@@ -128,15 +107,16 @@
static atomic_int dropped;
static atomic_int droppedSecurity;
- sock = atomic_load(&logdLoggerWrite.context.sock);
- if (sock < 0) switch (sock) {
- case -ENOTCONN:
- case -ECONNREFUSED:
- case -ENOENT:
- break;
- default:
- return -EBADF;
- }
+ auto lock = std::shared_lock{logd_socket_lock};
+ if (logd_socket <= 0) {
+ lock.unlock();
+ OpenSocket();
+ lock.lock();
+ }
+
+ if (logd_socket <= 0) {
+ return -EBADF;
+ }
/* logd, after initialization and priv drop */
if (__android_log_uid() == AID_LOGD) {
@@ -155,41 +135,39 @@
newVec[0].iov_base = (unsigned char*)&header;
newVec[0].iov_len = sizeof(header);
- if (sock >= 0) {
- int32_t snapshot = atomic_exchange_explicit(&droppedSecurity, 0, memory_order_relaxed);
- if (snapshot) {
- android_log_event_int_t buffer;
+ int32_t snapshot = atomic_exchange_explicit(&droppedSecurity, 0, memory_order_relaxed);
+ if (snapshot) {
+ android_log_event_int_t buffer;
- header.id = LOG_ID_SECURITY;
- buffer.header.tag = LIBLOG_LOG_TAG;
- buffer.payload.type = EVENT_TYPE_INT;
- buffer.payload.data = snapshot;
+ header.id = LOG_ID_SECURITY;
+ buffer.header.tag = LIBLOG_LOG_TAG;
+ buffer.payload.type = EVENT_TYPE_INT;
+ buffer.payload.data = snapshot;
- newVec[headerLength].iov_base = &buffer;
- newVec[headerLength].iov_len = sizeof(buffer);
+ newVec[headerLength].iov_base = &buffer;
+ newVec[headerLength].iov_len = sizeof(buffer);
- ret = TEMP_FAILURE_RETRY(writev(sock, newVec, 2));
- if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
- atomic_fetch_add_explicit(&droppedSecurity, snapshot, memory_order_relaxed);
- }
+ ret = TEMP_FAILURE_RETRY(writev(logd_socket, newVec, 2));
+ if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
+ atomic_fetch_add_explicit(&droppedSecurity, snapshot, memory_order_relaxed);
}
- snapshot = atomic_exchange_explicit(&dropped, 0, memory_order_relaxed);
- if (snapshot && __android_log_is_loggable_len(ANDROID_LOG_INFO, "liblog", strlen("liblog"),
- ANDROID_LOG_VERBOSE)) {
- android_log_event_int_t buffer;
+ }
+ snapshot = atomic_exchange_explicit(&dropped, 0, memory_order_relaxed);
+ if (snapshot && __android_log_is_loggable_len(ANDROID_LOG_INFO, "liblog", strlen("liblog"),
+ ANDROID_LOG_VERBOSE)) {
+ android_log_event_int_t buffer;
- header.id = LOG_ID_EVENTS;
- buffer.header.tag = LIBLOG_LOG_TAG;
- buffer.payload.type = EVENT_TYPE_INT;
- buffer.payload.data = snapshot;
+ header.id = LOG_ID_EVENTS;
+ buffer.header.tag = LIBLOG_LOG_TAG;
+ buffer.payload.type = EVENT_TYPE_INT;
+ buffer.payload.data = snapshot;
- newVec[headerLength].iov_base = &buffer;
- newVec[headerLength].iov_len = sizeof(buffer);
+ newVec[headerLength].iov_base = &buffer;
+ newVec[headerLength].iov_len = sizeof(buffer);
- ret = TEMP_FAILURE_RETRY(writev(sock, newVec, 2));
- if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
- atomic_fetch_add_explicit(&dropped, snapshot, memory_order_relaxed);
- }
+ ret = TEMP_FAILURE_RETRY(writev(logd_socket, newVec, 2));
+ if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
+ atomic_fetch_add_explicit(&dropped, snapshot, memory_order_relaxed);
}
}
@@ -208,49 +186,26 @@
}
}
- /*
- * The write below could be lost, but will never block.
- *
- * ENOTCONN occurs if logd has died.
- * ENOENT occurs if logd is not running and socket is missing.
- * ECONNREFUSED occurs if we can not reconnect to logd.
- * EAGAIN occurs if logd is overloaded.
- */
- if (sock < 0) {
- ret = sock;
- } else {
- ret = TEMP_FAILURE_RETRY(writev(sock, newVec, i));
- if (ret < 0) {
- ret = -errno;
- }
+ // The write below could be lost, but will never block.
+ // EAGAIN occurs if logd is overloaded, other errors indicate that something went wrong with
+ // the connection, so we reset it and try again.
+ ret = TEMP_FAILURE_RETRY(writev(logd_socket, newVec, i));
+ if (ret < 0 && errno != EAGAIN) {
+ int old_socket = logd_socket;
+ lock.unlock();
+ ResetSocket(old_socket);
+ lock.lock();
+
+ ret = TEMP_FAILURE_RETRY(writev(logd_socket, newVec, i));
}
- switch (ret) {
- case -ENOTCONN:
- case -ECONNREFUSED:
- case -ENOENT:
- if (__android_log_trylock()) {
- return ret; /* in a signal handler? try again when less stressed */
- }
- __logdClose(ret);
- ret = logdOpen();
- __android_log_unlock();
- if (ret < 0) {
- return ret;
- }
-
- ret = TEMP_FAILURE_RETRY(writev(atomic_load(&logdLoggerWrite.context.sock), newVec, i));
- if (ret < 0) {
- ret = -errno;
- }
- [[fallthrough]];
- default:
- break;
+ if (ret < 0) {
+ ret = -errno;
}
if (ret > (ssize_t)sizeof(header)) {
ret -= sizeof(header);
- } else if (ret == -EAGAIN) {
+ } else if (ret < 0) {
atomic_fetch_add_explicit(&dropped, 1, memory_order_relaxed);
if (logId == LOG_ID_SECURITY) {
atomic_fetch_add_explicit(&droppedSecurity, 1, memory_order_relaxed);
diff --git a/liblog/logger.h b/liblog/logger.h
index 9d74d29..40d5fe5 100644
--- a/liblog/logger.h
+++ b/liblog/logger.h
@@ -26,20 +26,7 @@
__BEGIN_DECLS
-/* Union, sock or fd of zero is not allowed unless static initialized */
-union android_log_context_union {
- void* priv;
- atomic_int sock;
- atomic_int fd;
-};
-
struct android_log_transport_write {
- const char* name; /* human name to describe the transport */
- unsigned logMask; /* mask cache of available() success */
- union android_log_context_union context; /* Initialized by static allocation */
-
- int (*available)(log_id_t logId); /* Does not cause resources to be taken */
- int (*open)(); /* can be called multiple times, reusing current resources */
void (*close)(); /* free up resources */
/* write log to transport, returns number of bytes propagated, or -errno */
int (*write)(log_id_t logId, struct timespec* ts, struct iovec* vec,
@@ -83,8 +70,4 @@
}
#endif
-void __android_log_lock();
-int __android_log_trylock();
-void __android_log_unlock();
-
__END_DECLS
diff --git a/liblog/logger_lock.cpp b/liblog/logger_lock.cpp
deleted file mode 100644
index 4636b00..0000000
--- a/liblog/logger_lock.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2007-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.
- * 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.
- */
-
-/*
- * Some OS specific dribs and drabs (locking etc).
- */
-
-#if !defined(_WIN32)
-#include <pthread.h>
-#endif
-
-#include "logger.h"
-
-#if !defined(_WIN32)
-static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER;
-#endif
-
-void __android_log_lock() {
-#if !defined(_WIN32)
- /*
- * If we trigger a signal handler in the middle of locked activity and the
- * signal handler logs a message, we could get into a deadlock state.
- */
- pthread_mutex_lock(&log_init_lock);
-#endif
-}
-
-int __android_log_trylock() {
-#if !defined(_WIN32)
- return pthread_mutex_trylock(&log_init_lock);
-#else
- return 0;
-#endif
-}
-
-void __android_log_unlock() {
-#if !defined(_WIN32)
- pthread_mutex_unlock(&log_init_lock);
-#endif
-}
diff --git a/liblog/logger_write.cpp b/liblog/logger_write.cpp
index 85475ec..d38b402 100644
--- a/liblog/logger_write.cpp
+++ b/liblog/logger_write.cpp
@@ -46,11 +46,8 @@
android_log_transport_write* android_log_persist_write = nullptr;
#endif
-static int __write_to_log_init(log_id_t, struct iovec* vec, size_t nr);
-static int (*write_to_log)(log_id_t, struct iovec* vec, size_t nr) = __write_to_log_init;
-
-static int check_log_uid_permissions() {
#if defined(__ANDROID__)
+static int check_log_uid_permissions() {
uid_t uid = __android_log_uid();
/* Matches clientHasLogCredentials() in logd */
@@ -87,43 +84,14 @@
}
}
}
-#endif
return 0;
}
-
-static void __android_log_cache_available(struct android_log_transport_write* node) {
- uint32_t i;
-
- if (node->logMask) {
- return;
- }
-
- for (i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
- if (i != LOG_ID_KERNEL && (i != LOG_ID_SECURITY || check_log_uid_permissions() == 0) &&
- (*node->available)(static_cast<log_id_t>(i)) >= 0) {
- node->logMask |= 1 << i;
- }
- }
-}
+#endif
/*
* Release any logger resources. A new log write will immediately re-acquire.
*/
void __android_log_close() {
- __android_log_lock();
-
- write_to_log = __write_to_log_init;
-
- /*
- * Threads that are actively writing at this point are not held back
- * by a lock and are at risk of dropping the messages with a return code
- * -EBADF. Prefer to return error code than add the overhead of a lock to
- * each log writing call to guarantee delivery. In addition, anyone
- * calling this is doing so to release the logging resources and shut down,
- * for them to do so with outstanding log requests in other threads is a
- * disengenuous use of this function.
- */
-
if (android_log_write != nullptr) {
android_log_write->close();
}
@@ -132,44 +100,18 @@
android_log_persist_write->close();
}
- __android_log_unlock();
}
-static bool transport_initialize(android_log_transport_write* transport) {
- if (transport == nullptr) {
- return false;
- }
-
- __android_log_cache_available(transport);
- if (!transport->logMask) {
- return false;
- }
-
- // TODO: Do we actually need to call close() if open() fails?
- if (transport->open() < 0) {
- transport->close();
- return false;
- }
-
- return true;
-}
-
-/* log_init_lock assumed */
-static int __write_to_log_initialize() {
- if (!transport_initialize(android_log_write)) {
- return -ENODEV;
- }
-
- transport_initialize(android_log_persist_write);
-
- return 1;
-}
-
-static int __write_to_log_daemon(log_id_t log_id, struct iovec* vec, size_t nr) {
+static int write_to_log(log_id_t log_id, struct iovec* vec, size_t nr) {
int ret, save_errno;
struct timespec ts;
save_errno = errno;
+
+ if (log_id == LOG_ID_KERNEL) {
+ return -EINVAL;
+ }
+
#if defined(__ANDROID__)
clock_gettime(android_log_clockid(), &ts);
@@ -215,9 +157,8 @@
#endif
ret = 0;
- size_t i = 1 << log_id;
- if (android_log_write != nullptr && (android_log_write->logMask & i)) {
+ if (android_log_write != nullptr) {
ssize_t retval;
retval = android_log_write->write(log_id, &ts, vec, nr);
if (ret >= 0) {
@@ -225,7 +166,7 @@
}
}
- if (android_log_persist_write != nullptr && (android_log_persist_write->logMask & i)) {
+ if (android_log_persist_write != nullptr) {
android_log_persist_write->write(log_id, &ts, vec, nr);
}
@@ -233,29 +174,6 @@
return ret;
}
-static int __write_to_log_init(log_id_t log_id, struct iovec* vec, size_t nr) {
- int ret, save_errno = errno;
-
- __android_log_lock();
-
- if (write_to_log == __write_to_log_init) {
- ret = __write_to_log_initialize();
- if (ret < 0) {
- __android_log_unlock();
- errno = save_errno;
- return ret;
- }
-
- write_to_log = __write_to_log_daemon;
- }
-
- __android_log_unlock();
-
- ret = write_to_log(log_id, vec, nr);
- errno = save_errno;
- return ret;
-}
-
int __android_log_write(int prio, const char* tag, const char* msg) {
return __android_log_buf_write(LOG_ID_MAIN, prio, tag, msg);
}
diff --git a/liblog/pmsg_writer.cpp b/liblog/pmsg_writer.cpp
index 54980d9..4f45780 100644
--- a/liblog/pmsg_writer.cpp
+++ b/liblog/pmsg_writer.cpp
@@ -25,68 +25,47 @@
#include <sys/types.h>
#include <time.h>
+#include <shared_mutex>
+
#include <log/log_properties.h>
#include <private/android_filesystem_config.h>
#include <private/android_logger.h>
#include "log_portability.h"
#include "logger.h"
+#include "rwlock.h"
#include "uio.h"
-static int pmsgOpen();
-static void pmsgClose();
-static int pmsgAvailable(log_id_t logId);
-static int pmsgWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr);
+static void PmsgClose();
+static int PmsgWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr);
struct android_log_transport_write pmsgLoggerWrite = {
- .name = "pmsg",
- .logMask = 0,
- .context.fd = -1,
- .available = pmsgAvailable,
- .open = pmsgOpen,
- .close = pmsgClose,
- .write = pmsgWrite,
+ .close = PmsgClose,
+ .write = PmsgWrite,
};
-static int pmsgOpen() {
- int fd = atomic_load(&pmsgLoggerWrite.context.fd);
- if (fd < 0) {
- int i;
+static int pmsg_fd;
+static RwLock pmsg_fd_lock;
- fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY | O_CLOEXEC));
- i = atomic_exchange(&pmsgLoggerWrite.context.fd, fd);
- if ((i >= 0) && (i != fd)) {
- close(i);
- }
+static void PmsgOpen() {
+ auto lock = std::unique_lock{pmsg_fd_lock};
+ if (pmsg_fd > 0) {
+ // Someone raced us and opened the socket already.
+ return;
}
- return fd;
+ pmsg_fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY | O_CLOEXEC));
}
-static void pmsgClose() {
- int fd = atomic_exchange(&pmsgLoggerWrite.context.fd, -1);
- if (fd >= 0) {
- close(fd);
+static void PmsgClose() {
+ auto lock = std::unique_lock{pmsg_fd_lock};
+ if (pmsg_fd > 0) {
+ close(pmsg_fd);
}
+ pmsg_fd = 0;
}
-static int pmsgAvailable(log_id_t logId) {
- if (logId > LOG_ID_SECURITY) {
- return -EINVAL;
- }
- if ((logId != LOG_ID_SECURITY) && (logId != LOG_ID_EVENTS) && !__android_log_is_debuggable()) {
- return -EINVAL;
- }
- if (atomic_load(&pmsgLoggerWrite.context.fd) < 0) {
- if (access("/dev/pmsg0", W_OK) == 0) {
- return 0;
- }
- return -EBADF;
- }
- return 1;
-}
-
-static int pmsgWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr) {
+static int PmsgWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr) {
static const unsigned headerLength = 2;
struct iovec newVec[nr + headerLength];
android_log_header_t header;
@@ -94,17 +73,31 @@
size_t i, payloadSize;
ssize_t ret;
- if ((logId == LOG_ID_EVENTS) && !__android_log_is_debuggable()) {
- if (vec[0].iov_len < 4) {
- return -EINVAL;
+ if (!__android_log_is_debuggable()) {
+ if (logId != LOG_ID_EVENTS && logId != LOG_ID_SECURITY) {
+ return -1;
}
- if (SNET_EVENT_LOG_TAG != *static_cast<uint32_t*>(vec[0].iov_base)) {
- return -EPERM;
+ if (logId == LOG_ID_EVENTS) {
+ if (vec[0].iov_len < 4) {
+ return -EINVAL;
+ }
+
+ if (SNET_EVENT_LOG_TAG != *static_cast<uint32_t*>(vec[0].iov_base)) {
+ return -EPERM;
+ }
}
}
- if (atomic_load(&pmsgLoggerWrite.context.fd) < 0) {
+ auto lock = std::shared_lock{pmsg_fd_lock};
+
+ if (pmsg_fd <= 0) {
+ lock.unlock();
+ PmsgOpen();
+ lock.lock();
+ }
+
+ if (pmsg_fd <= 0) {
return -EBADF;
}
@@ -158,7 +151,7 @@
}
pmsgHeader.len += payloadSize;
- ret = TEMP_FAILURE_RETRY(writev(atomic_load(&pmsgLoggerWrite.context.fd), newVec, i));
+ ret = TEMP_FAILURE_RETRY(writev(pmsg_fd, newVec, i));
if (ret < 0) {
ret = errno ? -errno : -ENOTCONN;
}
@@ -193,7 +186,6 @@
/* Write a buffer as filename references (tag = <basedir>:<basename>) */
ssize_t __android_log_pmsg_file_write(log_id_t logId, char prio, const char* filename,
const char* buf, size_t len) {
- bool weOpened;
size_t length, packet_len;
const char* tag;
char *cp, *slash;
@@ -233,7 +225,6 @@
vec[1].iov_base = (unsigned char*)tag;
vec[1].iov_len = length;
- weOpened = false;
for (ts.tv_nsec = 0, length = len; length; ts.tv_nsec += ANDROID_LOG_PMSG_FILE_SEQUENCE) {
ssize_t ret;
size_t transfer;
@@ -254,37 +245,15 @@
vec[2].iov_base = (unsigned char*)buf;
vec[2].iov_len = transfer;
- if (atomic_load(&pmsgLoggerWrite.context.fd) < 0) {
- if (!weOpened) { /* Impossible for weOpened = true here */
- __android_log_lock();
- }
- weOpened = atomic_load(&pmsgLoggerWrite.context.fd) < 0;
- if (!weOpened) {
- __android_log_unlock();
- } else if (pmsgOpen() < 0) {
- __android_log_unlock();
- free(cp);
- return -EBADF;
- }
- }
-
- ret = pmsgWrite(logId, &ts, vec, sizeof(vec) / sizeof(vec[0]));
+ ret = PmsgWrite(logId, &ts, vec, sizeof(vec) / sizeof(vec[0]));
if (ret <= 0) {
- if (weOpened) {
- pmsgClose();
- __android_log_unlock();
- }
free(cp);
return ret ? ret : (len - length);
}
length -= transfer;
buf += transfer;
}
- if (weOpened) {
- pmsgClose();
- __android_log_unlock();
- }
free(cp);
return len;
}
diff --git a/liblog/rwlock.h b/liblog/rwlock.h
new file mode 100644
index 0000000..00f1806
--- /dev/null
+++ b/liblog/rwlock.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#pragma once
+
+#include <pthread.h>
+
+// As of the end of Dec 2019, std::shared_mutex is *not* simply a pthread_rwlock, but rather a
+// combination of std::mutex and std::condition variable, which is obviously less efficient. This
+// immitates what std::shared_mutex should be doing and is compatible with std::shared_lock and
+// std::unique_lock.
+
+class RwLock {
+ public:
+ RwLock() {}
+ ~RwLock() {}
+
+ void lock() { pthread_rwlock_wrlock(&rwlock_); }
+ void unlock() { pthread_rwlock_unlock(&rwlock_); }
+
+ void lock_shared() { pthread_rwlock_rdlock(&rwlock_); }
+ void unlock_shared() { pthread_rwlock_unlock(&rwlock_); }
+
+ private:
+ pthread_rwlock_t rwlock_ = PTHREAD_RWLOCK_INITIALIZER;
+};
diff --git a/liblog/tests/Android.bp b/liblog/tests/Android.bp
index 99df4ca..f58c524 100644
--- a/liblog/tests/Android.bp
+++ b/liblog/tests/Android.bp
@@ -62,6 +62,7 @@
"log_time_test.cpp",
"log_wrap_test.cpp",
"logprint_test.cpp",
+ "rwlock_test.cpp",
],
shared_libs: [
"libcutils",
diff --git a/liblog/tests/rwlock_test.cpp b/liblog/tests/rwlock_test.cpp
new file mode 100644
index 0000000..617d5c4
--- /dev/null
+++ b/liblog/tests/rwlock_test.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2019 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 "../rwlock.h"
+
+#include <chrono>
+#include <shared_mutex>
+#include <thread>
+
+#include <gtest/gtest.h>
+
+using namespace std::literals;
+
+TEST(rwlock, reader_then_reader_lock) {
+ RwLock lock;
+
+ bool thread_ran = false;
+ auto read_guard = std::shared_lock{lock};
+
+ auto reader_thread = std::thread([&] {
+ auto read_guard = std::shared_lock{lock};
+ thread_ran = true;
+ });
+
+ auto end_time = std::chrono::steady_clock::now() + 1s;
+
+ while (std::chrono::steady_clock::now() < end_time) {
+ if (thread_ran) {
+ break;
+ }
+ }
+
+ EXPECT_EQ(true, thread_ran);
+
+ // Unlock the lock in case something went wrong, to ensure that we can still join() the thread.
+ read_guard.unlock();
+ reader_thread.join();
+}
+
+template <template <typename> typename L1, template <typename> typename L2>
+void TestBlockingLocks() {
+ RwLock lock;
+
+ bool thread_ran = false;
+ auto read_guard = L1{lock};
+
+ auto reader_thread = std::thread([&] {
+ auto read_guard = L2{lock};
+ thread_ran = true;
+ });
+
+ auto end_time = std::chrono::steady_clock::now() + 1s;
+
+ while (std::chrono::steady_clock::now() < end_time) {
+ if (thread_ran) {
+ break;
+ }
+ }
+
+ EXPECT_EQ(false, thread_ran);
+
+ read_guard.unlock();
+ reader_thread.join();
+
+ EXPECT_EQ(true, thread_ran);
+}
+
+TEST(rwlock, reader_then_writer_lock) {
+ TestBlockingLocks<std::shared_lock, std::unique_lock>();
+}
+
+TEST(rwlock, writer_then_reader_lock) {
+ TestBlockingLocks<std::unique_lock, std::shared_lock>();
+}
+
+TEST(rwlock, writer_then_writer_lock) {
+ TestBlockingLocks<std::unique_lock, std::unique_lock>();
+}
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index ebc0cde..2dbdb60 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -72,7 +72,7 @@
#
# create some directories (some are mount points) and symlinks
LOCAL_POST_INSTALL_CMD := mkdir -p $(addprefix $(TARGET_ROOT_OUT)/, \
- dev proc sys system data odm oem acct config storage mnt apex debug_ramdisk \
+ dev proc sys system data data_mirror odm oem acct config storage mnt apex debug_ramdisk \
linkerconfig $(BOARD_ROOT_EXTRA_FOLDERS)); \
ln -sf /system/bin $(TARGET_ROOT_OUT)/bin; \
ln -sf /system/etc $(TARGET_ROOT_OUT)/etc; \
diff --git a/rootdir/avb/Android.mk b/rootdir/avb/Android.mk
index 5dc019c..80573fb 100644
--- a/rootdir/avb/Android.mk
+++ b/rootdir/avb/Android.mk
@@ -16,6 +16,21 @@
include $(BUILD_PREBUILT)
#######################################
+# q-developer-gsi.avbpubkey
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := q-developer-gsi.avbpubkey
+LOCAL_MODULE_CLASS := ETC
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
+LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/first_stage_ramdisk/avb
+else
+LOCAL_MODULE_PATH := $(TARGET_RAMDISK_OUT)/avb
+endif
+
+include $(BUILD_PREBUILT)
+
+#######################################
# r-gsi.avbpubkey
include $(CLEAR_VARS)
diff --git a/rootdir/avb/q-developer-gsi.avbpubkey b/rootdir/avb/q-developer-gsi.avbpubkey
new file mode 100644
index 0000000..0ace69d
--- /dev/null
+++ b/rootdir/avb/q-developer-gsi.avbpubkey
Binary files differ
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 2ec0669..b89c45e 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -650,12 +650,35 @@
mkdir /data/user 0711 system system encryption=None
mkdir /data/user_de 0711 system system encryption=None
- symlink /data/data /data/user/0
+
+ # Unlink /data/user/0 if we previously symlink it to /data/data
+ rm /data/user/0
+
+ # Bind mount /data/user/0 to /data/data
+ mkdir /data/user/0 0700 system system encryption=None
+ mount none /data/data /data/user/0 bind rec
# Special-case /data/media/obb per b/64566063
mkdir /data/media 0770 media_rw media_rw encryption=None
mkdir /data/media/obb 0770 media_rw media_rw encryption=Attempt
+ # A tmpfs directory, which will contain all apps CE DE data directory that
+ # bind mount from the original source.
+ chown root root /data_mirror
+ chmod 0700 /data_mirror
+ mount tmpfs tmpfs /data_mirror mode=0700,uid=0,gid=1000 nodev noexec nosuid
+ restorecon /data_mirror
+ mkdir /data_mirror/data_ce 0700 root root
+ mkdir /data_mirror/data_de 0700 root root
+
+ # Create CE and DE data directory for default volume
+ mkdir /data_mirror/data_ce/null 0700 root root
+ mkdir /data_mirror/data_de/null 0700 root root
+
+ # Bind mount CE and DE data directory to mirror's default volume directory
+ mount none /data/user /data_mirror/data_ce/null bind rec
+ mount none /data/user_de /data_mirror/data_de/null bind rec
+
mkdir /data/cache 0770 system cache encryption=Require
mkdir /data/cache/recovery 0770 system cache
mkdir /data/cache/backup_stage 0700 system system