Add mDNS device discovery for adb client
am: 13a269ea24
Change-Id: Ib5f80b3ccc9db7c6fe6f5c989e82083d734ce4df
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..fc4eb1b
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,13 @@
+BasedOnStyle: Google
+AllowShortBlocksOnASingleLine: false
+AllowShortFunctionsOnASingleLine: false
+
+AccessModifierOffset: -2
+ColumnLimit: 100
+CommentPragmas: NOLINT:.*
+DerivePointerAlignment: false
+IndentWidth: 4
+PointerAlignment: Left
+TabWidth: 4
+UseTab: Never
+PenaltyExcessCharacter: 32
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
new file mode 100644
index 0000000..c8dbf77
--- /dev/null
+++ b/PREUPLOAD.cfg
@@ -0,0 +1,5 @@
+[Builtin Hooks]
+clang_format = true
+
+[Builtin Hooks Options]
+clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
diff --git a/adb/Android.mk b/adb/Android.mk
index ef29695..b5b03ea 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -124,12 +124,11 @@
adbd_auth.cpp \
jdwp_service.cpp \
-LOCAL_C_INCLUDES := system/core/qemu_pipe/include
LOCAL_SANITIZE := $(adb_target_sanitize)
# Even though we're building a static library (and thus there's no link step for
# this to take effect), this adds the includes to our path.
-LOCAL_STATIC_LIBRARIES := libcrypto_utils libcrypto libqemu_pipe libbase
+LOCAL_STATIC_LIBRARIES := libcrypto_utils libcrypto libbase
LOCAL_WHOLE_STATIC_LIBRARIES := libadbd_usb
@@ -362,7 +361,6 @@
LOCAL_STATIC_LIBRARIES := \
libadbd \
libbase \
- libqemu_pipe \
libbootloader_message \
libfs_mgr \
libfec \
diff --git a/adb/NOTICE b/adb/NOTICE
index 9ffcc08..ff47c95 100644
--- a/adb/NOTICE
+++ b/adb/NOTICE
@@ -189,3 +189,63 @@
END OF TERMS AND CONDITIONS
+------------------------------------------------------------
+libwinpthread license:
+------------------------------------------------------------
+Copyright (c) 2011 mingw-w64 project
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+
+/*
+ * Parts of this library are derived by:
+ *
+ * Posix Threads library for Microsoft Windows
+ *
+ * Use at own risk, there is no implied warranty to this code.
+ * It uses undocumented features of Microsoft Windows that can change
+ * at any time in the future.
+ *
+ * (C) 2010 Lockless Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Lockless Inc. nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AN
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
diff --git a/adb/daemon/usb.cpp b/adb/daemon/usb.cpp
index c08b922..92e9039 100644
--- a/adb/daemon/usb.cpp
+++ b/adb/daemon/usb.cpp
@@ -283,6 +283,8 @@
D("[ %s: writing strings failed: errno=%d]", USB_FFS_ADB_EP0, errno);
goto err;
}
+ //Signal only when writing the descriptors to ffs
+ android::base::SetProperty("sys.usb.ffs.ready", "1");
}
h->bulk_out = adb_open(USB_FFS_ADB_OUT, O_RDWR);
@@ -358,7 +360,6 @@
}
std::this_thread::sleep_for(1s);
}
- android::base::SetProperty("sys.usb.ffs.ready", "1");
D("[ usb_thread - registering device ]");
register_usb_transport(usb, 0, 0, 1);
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index 12b98ba..4198a52 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -289,7 +289,7 @@
#define open adb_open
#define read adb_read
#define write adb_write
-#include <qemu_pipe.h>
+#include <system/qemu_pipe.h>
#undef open
#undef read
#undef write
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index 8d2ea68..af84be9 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -8,17 +8,35 @@
"-Os",
],
+ // util.cpp gets async signal safe logging via libc_logging,
+ // which defines its interface in bionic private headers.
+ include_dirs: ["bionic/libc"],
+
local_include_dirs: ["include"],
}
+// Utility library to tombstoned and get an output fd.
+cc_library_static {
+ name: "libtombstoned_client",
+ defaults: ["debuggerd_defaults"],
+ srcs: [
+ "tombstoned_client.cpp",
+ "util.cpp",
+ ],
+
+ whole_static_libs: [
+ "libc_logging",
+ "libcutils",
+ "libbase",
+ ],
+}
+
+// Core implementation, linked into libdebuggerd_handler and the dynamic linker.
cc_library_static {
name: "libdebuggerd_handler_core",
defaults: ["debuggerd_defaults"],
srcs: ["handler/debuggerd_handler.cpp"],
- // libdebuggerd_handler gets async signal safe logging via libc_logging,
- // which defines its interface in bionic private headers.
- include_dirs: ["bionic/libc"],
whole_static_libs: [
"libc_logging",
"libdebuggerd",
@@ -27,6 +45,7 @@
export_include_dirs: ["include"],
}
+// Implementation with a no-op fallback.
cc_library_static {
name: "libdebuggerd_handler",
defaults: ["debuggerd_defaults"],
@@ -39,15 +58,18 @@
export_include_dirs: ["include"],
}
+// Fallback implementation.
cc_library_static {
name: "libdebuggerd_handler_fallback",
defaults: ["debuggerd_defaults"],
- srcs: ["handler/debuggerd_fallback.cpp"],
+ srcs: [
+ "handler/debuggerd_fallback.cpp",
+ ],
- // libdebuggerd_handler gets async signal safe logging via libc_logging,
- // which defines its interface in bionic private headers.
- include_dirs: ["bionic/libc"],
- static_libs: [
+ whole_static_libs: [
+ "libdebuggerd_handler_core",
+ "libtombstoned_client",
+ "libbase",
"libdebuggerd",
"libbacktrace",
"libunwind",
@@ -70,6 +92,7 @@
"libbase",
"libcutils",
],
+
export_include_dirs: ["include"],
}
@@ -187,6 +210,7 @@
},
static_libs: [
+ "libtombstoned_client",
"libdebuggerd",
"libcutils",
],
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index 0e15472..6585424 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -48,6 +48,7 @@
#include "debuggerd/handler.h"
#include "debuggerd/protocol.h"
+#include "debuggerd/tombstoned.h"
#include "debuggerd/util.h"
using android::base::unique_fd;
@@ -128,55 +129,6 @@
return true;
}
-static bool tombstoned_connect(pid_t pid, unique_fd* tombstoned_socket, unique_fd* output_fd) {
- unique_fd sockfd(socket_local_client(kTombstonedCrashSocketName,
- ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET));
- if (sockfd == -1) {
- PLOG(ERROR) << "failed to connect to tombstoned";
- return false;
- }
-
- TombstonedCrashPacket packet = {};
- packet.packet_type = CrashPacketType::kDumpRequest;
- packet.packet.dump_request.pid = pid;
- if (TEMP_FAILURE_RETRY(write(sockfd, &packet, sizeof(packet))) != sizeof(packet)) {
- PLOG(ERROR) << "failed to write DumpRequest packet";
- return false;
- }
-
- unique_fd tmp_output_fd;
- ssize_t rc = recv_fd(sockfd, &packet, sizeof(packet), &tmp_output_fd);
- if (rc == -1) {
- PLOG(ERROR) << "failed to read response to DumpRequest packet";
- return false;
- } else if (rc != sizeof(packet)) {
- LOG(ERROR) << "read DumpRequest response packet of incorrect length (expected "
- << sizeof(packet) << ", got " << rc << ")";
- return false;
- }
-
- // Make the fd O_APPEND so that our output is guaranteed to be at the end of a file.
- // (This also makes selinux rules consistent, because selinux distinguishes between writing to
- // a regular fd, and writing to an fd with O_APPEND).
- int flags = fcntl(tmp_output_fd.get(), F_GETFL);
- if (fcntl(tmp_output_fd.get(), F_SETFL, flags | O_APPEND) != 0) {
- PLOG(WARNING) << "failed to set output fd flags";
- }
-
- *tombstoned_socket = std::move(sockfd);
- *output_fd = std::move(tmp_output_fd);
- return true;
-}
-
-static bool tombstoned_notify_completion(int tombstoned_socket) {
- TombstonedCrashPacket packet = {};
- packet.packet_type = CrashPacketType::kCompletedDump;
- if (TEMP_FAILURE_RETRY(write(tombstoned_socket, &packet, sizeof(packet))) != sizeof(packet)) {
- return false;
- }
- return true;
-}
-
static void signal_handler(int) {
// We can't log easily, because the heap might be corrupt.
// Just die and let the surrounding log context explain things.
diff --git a/debuggerd/handler/debuggerd_fallback.cpp b/debuggerd/handler/debuggerd_fallback.cpp
index 77ad6ac..5c6c59c 100644
--- a/debuggerd/handler/debuggerd_fallback.cpp
+++ b/debuggerd/handler/debuggerd_fallback.cpp
@@ -26,23 +26,206 @@
* SUCH DAMAGE.
*/
+#include <dirent.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <pthread.h>
#include <stddef.h>
#include <sys/ucontext.h>
+#include <syscall.h>
#include <unistd.h>
+#include <atomic>
+
+#include <android-base/file.h>
+#include <android-base/unique_fd.h>
+
+#include "debuggerd/handler.h"
+#include "debuggerd/tombstoned.h"
+#include "debuggerd/util.h"
+
+#include "backtrace.h"
#include "tombstone.h"
-extern "C" void __linker_use_fallback_allocator();
+#include "private/libc_logging.h"
-extern "C" bool debuggerd_fallback(ucontext_t* ucontext, siginfo_t* siginfo, void* abort_message) {
- // This is incredibly sketchy to do inside of a signal handler, especially when libbacktrace
- // uses the C++ standard library throughout, but this code runs in the linker, so we'll be using
- // the linker's malloc instead of the libc one. Switch it out for a replacement, just in case.
- //
- // This isn't the default method of dumping because it can fail in cases such as memory space
- // exhaustion.
- __linker_use_fallback_allocator();
- engrave_tombstone_ucontext(-1, getpid(), gettid(), reinterpret_cast<uintptr_t>(abort_message),
- siginfo, ucontext);
- return true;
+using android::base::unique_fd;
+
+extern "C" void __linker_enable_fallback_allocator();
+extern "C" void __linker_disable_fallback_allocator();
+
+// This is incredibly sketchy to do inside of a signal handler, especially when libbacktrace
+// uses the C++ standard library throughout, but this code runs in the linker, so we'll be using
+// the linker's malloc instead of the libc one. Switch it out for a replacement, just in case.
+//
+// This isn't the default method of dumping because it can fail in cases such as address space
+// exhaustion.
+static void debuggerd_fallback_trace(int output_fd, ucontext_t* ucontext) {
+ __linker_enable_fallback_allocator();
+ dump_backtrace_ucontext(output_fd, ucontext);
+ __linker_disable_fallback_allocator();
+}
+
+static void debuggerd_fallback_tombstone(int output_fd, ucontext_t* ucontext, siginfo_t* siginfo,
+ void* abort_message) {
+ __linker_enable_fallback_allocator();
+ engrave_tombstone_ucontext(output_fd, reinterpret_cast<uintptr_t>(abort_message), siginfo,
+ ucontext);
+ __linker_disable_fallback_allocator();
+}
+
+static void iterate_siblings(bool (*callback)(pid_t, int), int output_fd) {
+ pid_t current_tid = gettid();
+ char buf[BUFSIZ];
+ snprintf(buf, sizeof(buf), "/proc/%d/task", current_tid);
+ DIR* dir = opendir(buf);
+
+ if (!dir) {
+ __libc_format_log(ANDROID_LOG_ERROR, "libc", "failed to open %s: %s", buf, strerror(errno));
+ return;
+ }
+
+ struct dirent* ent;
+ while ((ent = readdir(dir))) {
+ char* end;
+ long tid = strtol(ent->d_name, &end, 10);
+ if (end == ent->d_name || *end != '\0') {
+ continue;
+ }
+
+ if (tid != current_tid) {
+ callback(tid, output_fd);
+ }
+ }
+ closedir(dir);
+}
+
+static bool forward_output(int src_fd, int dst_fd) {
+ // Make sure the thread actually got the signal.
+ struct pollfd pfd = {
+ .fd = src_fd, .events = POLLIN,
+ };
+
+ // Wait for up to a second for output to start flowing.
+ if (poll(&pfd, 1, 1000) != 1) {
+ return false;
+ }
+
+ while (true) {
+ char buf[512];
+ ssize_t rc = TEMP_FAILURE_RETRY(read(src_fd, buf, sizeof(buf)));
+ if (rc == 0) {
+ return true;
+ } else if (rc < 0) {
+ return false;
+ }
+
+ if (!android::base::WriteFully(dst_fd, buf, rc)) {
+ // We failed to write to tombstoned, but there's not much we can do.
+ // Keep reading from src_fd to keep things going.
+ continue;
+ }
+ }
+}
+
+static void trace_handler(siginfo_t* info, ucontext_t* ucontext) {
+ static std::atomic<int> trace_output_fd(-1);
+
+ if (info->si_value.sival_int == ~0) {
+ // Asked to dump by the original signal recipient.
+ debuggerd_fallback_trace(trace_output_fd, ucontext);
+
+ int tmp = trace_output_fd.load();
+ trace_output_fd.store(-1);
+ close(tmp);
+ return;
+ }
+
+ // Only allow one thread to perform a trace at a time.
+ static pthread_mutex_t trace_mutex = PTHREAD_MUTEX_INITIALIZER;
+ int ret = pthread_mutex_trylock(&trace_mutex);
+ if (ret != 0) {
+ __libc_format_log(ANDROID_LOG_INFO, "libc", "pthread_mutex_try_lock failed: %s", strerror(ret));
+ return;
+ }
+
+ // Fetch output fd from tombstoned.
+ unique_fd tombstone_socket, output_fd;
+ if (!tombstoned_connect(getpid(), &tombstone_socket, &output_fd)) {
+ goto exit;
+ }
+
+ dump_backtrace_header(output_fd.get());
+
+ // Dump our own stack.
+ debuggerd_fallback_trace(output_fd.get(), ucontext);
+
+ // Send a signal to all of our siblings, asking them to dump their stack.
+ iterate_siblings(
+ [](pid_t tid, int output_fd) {
+ // Use a pipe, to be able to detect situations where the thread gracefully exits before
+ // receiving our signal.
+ unique_fd pipe_read, pipe_write;
+ if (!Pipe(&pipe_read, &pipe_write)) {
+ __libc_format_log(ANDROID_LOG_ERROR, "libc", "failed to create pipe: %s", strerror(errno));
+ return false;
+ }
+
+ trace_output_fd.store(pipe_write.get());
+
+ siginfo_t siginfo = {};
+ siginfo.si_code = SI_QUEUE;
+ siginfo.si_value.sival_int = ~0;
+ siginfo.si_pid = getpid();
+ siginfo.si_uid = getuid();
+
+ if (syscall(__NR_rt_tgsigqueueinfo, getpid(), tid, DEBUGGER_SIGNAL, &siginfo) != 0) {
+ __libc_format_log(ANDROID_LOG_ERROR, "libc", "failed to send trace signal to %d: %s", tid,
+ strerror(errno));
+ return false;
+ }
+
+ bool success = forward_output(pipe_read.get(), output_fd);
+ if (success) {
+ // The signaled thread has closed trace_output_fd already.
+ (void)pipe_write.release();
+ } else {
+ trace_output_fd.store(-1);
+ }
+
+ return true;
+ },
+ output_fd.get());
+
+ dump_backtrace_footer(output_fd.get());
+ tombstoned_notify_completion(tombstone_socket.get());
+
+exit:
+ pthread_mutex_unlock(&trace_mutex);
+}
+
+static void crash_handler(siginfo_t* info, ucontext_t* ucontext, void* abort_message) {
+ // Only allow one thread to handle a crash.
+ static pthread_mutex_t crash_mutex = PTHREAD_MUTEX_INITIALIZER;
+ int ret = pthread_mutex_lock(&crash_mutex);
+ if (ret != 0) {
+ __libc_format_log(ANDROID_LOG_INFO, "libc", "pthread_mutex_lock failed: %s", strerror(ret));
+ return;
+ }
+
+ unique_fd tombstone_socket, output_fd;
+ bool tombstoned_connected = tombstoned_connect(getpid(), &tombstone_socket, &output_fd);
+ debuggerd_fallback_tombstone(output_fd.get(), ucontext, info, abort_message);
+ if (tombstoned_connected) {
+ tombstoned_notify_completion(tombstone_socket.get());
+ }
+}
+
+extern "C" void debuggerd_fallback_handler(siginfo_t* info, ucontext_t* ucontext,
+ void* abort_message) {
+ if (info->si_signo == DEBUGGER_SIGNAL) {
+ return trace_handler(info, ucontext);
+ } else {
+ return crash_handler(info, ucontext, abort_message);
+ }
}
diff --git a/debuggerd/handler/debuggerd_fallback_nop.cpp b/debuggerd/handler/debuggerd_fallback_nop.cpp
index 9b3053f..331301f 100644
--- a/debuggerd/handler/debuggerd_fallback_nop.cpp
+++ b/debuggerd/handler/debuggerd_fallback_nop.cpp
@@ -26,10 +26,5 @@
* SUCH DAMAGE.
*/
-#include <stddef.h>
-#include <sys/ucontext.h>
-#include <unistd.h>
-
-extern "C" bool debuggerd_fallback(ucontext_t*, siginfo_t*, void*) {
- return false;
+extern "C" void debuggerd_fallback_handler(struct siginfo_t*, struct ucontext_t*, void*) {
}
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index 67c26e2..c09c2f3 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -62,7 +62,7 @@
#define CRASH_DUMP_PATH "/system/bin/" CRASH_DUMP_NAME
-extern "C" bool debuggerd_fallback(ucontext_t*, siginfo_t*, void*);
+extern "C" void debuggerd_fallback_handler(siginfo_t*, ucontext_t*, void*);
static debuggerd_callbacks_t g_callbacks;
@@ -323,21 +323,11 @@
fatal_errno("failed to resend signal during crash");
}
}
-
- if (info->si_signo == DEBUGGER_SIGNAL) {
- pthread_mutex_unlock(&crash_mutex);
- }
}
// Handler that does crash dumping by forking and doing the processing in the child.
// Do this by ptracing the relevant thread, and then execing debuggerd to do the actual dump.
static void debuggerd_signal_handler(int signal_number, siginfo_t* info, void* context) {
- int ret = pthread_mutex_lock(&crash_mutex);
- if (ret != 0) {
- __libc_format_log(ANDROID_LOG_INFO, "libc", "pthread_mutex_lock failed: %s", strerror(ret));
- return;
- }
-
// It's possible somebody cleared the SA_SIGINFO flag, which would mean
// our "info" arg holds an undefined value.
if (!have_siginfo(signal_number)) {
@@ -359,24 +349,29 @@
// check to allow all si_code values in calls coming from inside the house.
}
- log_signal_summary(signal_number, info);
-
void* abort_message = nullptr;
if (g_callbacks.get_abort_message) {
abort_message = g_callbacks.get_abort_message();
}
if (prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0) == 1) {
- ucontext_t* ucontext = static_cast<ucontext_t*>(context);
- if (signal_number == DEBUGGER_SIGNAL || !debuggerd_fallback(ucontext, info, abort_message)) {
- // The process has NO_NEW_PRIVS enabled, so we can't transition to the crash_dump context.
- __libc_format_log(ANDROID_LOG_INFO, "libc",
- "Suppressing debuggerd output because prctl(PR_GET_NO_NEW_PRIVS)==1");
- }
+ // This check might be racy if another thread sets NO_NEW_PRIVS, but this should be unlikely,
+ // you can only set NO_NEW_PRIVS to 1, and the effect should be at worst a single missing
+ // ANR trace.
+ debuggerd_fallback_handler(info, static_cast<ucontext_t*>(context), abort_message);
resend_signal(info, false);
return;
}
+ // Only allow one thread to handle a signal at a time.
+ int ret = pthread_mutex_lock(&crash_mutex);
+ if (ret != 0) {
+ __libc_format_log(ANDROID_LOG_INFO, "libc", "pthread_mutex_lock failed: %s", strerror(ret));
+ return;
+ }
+
+ log_signal_summary(signal_number, info);
+
// Populate si_value with the abort message address, if found.
if (abort_message) {
info->si_value.sival_ptr = abort_message;
@@ -427,6 +422,11 @@
}
resend_signal(info, thread_info.crash_dump_started);
+ if (info->si_signo == DEBUGGER_SIGNAL) {
+ // If the signal is fatal, don't unlock the mutex to prevent other crashing threads from
+ // starting to dump right before our death.
+ pthread_mutex_unlock(&crash_mutex);
+ }
}
void debuggerd_init(debuggerd_callbacks_t* callbacks) {
diff --git a/debuggerd/include/debuggerd/tombstoned.h b/debuggerd/include/debuggerd/tombstoned.h
new file mode 100644
index 0000000..d158d50
--- /dev/null
+++ b/debuggerd/include/debuggerd/tombstoned.h
@@ -0,0 +1,26 @@
+#pragma once
+
+/*
+ * Copyright 2017, 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 <sys/types.h>
+
+#include <android-base/unique_fd.h>
+
+bool tombstoned_connect(pid_t pid, android::base::unique_fd* tombstoned_socket,
+ android::base::unique_fd* output_fd);
+
+bool tombstoned_notify_completion(int tombstoned_socket);
diff --git a/debuggerd/libdebuggerd/backtrace.cpp b/debuggerd/libdebuggerd/backtrace.cpp
index 0664442..df49aef 100644
--- a/debuggerd/libdebuggerd/backtrace.cpp
+++ b/debuggerd/libdebuggerd/backtrace.cpp
@@ -67,15 +67,15 @@
_LOG(log, logtype::BACKTRACE, "\n----- end %d -----\n", pid);
}
-static void dump_thread(log_t* log, BacktraceMap* map, pid_t pid, pid_t tid) {
- char path[PATH_MAX];
- char threadnamebuf[1024];
- char* threadname = NULL;
+static void log_thread_name(log_t* log, pid_t tid) {
FILE* fp;
+ char buf[1024];
+ char path[PATH_MAX];
+ char* threadname = NULL;
snprintf(path, sizeof(path), "/proc/%d/comm", tid);
if ((fp = fopen(path, "r"))) {
- threadname = fgets(threadnamebuf, sizeof(threadnamebuf), fp);
+ threadname = fgets(buf, sizeof(buf), fp);
fclose(fp);
if (threadname) {
size_t len = strlen(threadname);
@@ -84,8 +84,11 @@
}
}
}
-
_LOG(log, logtype::BACKTRACE, "\n\"%s\" sysTid=%d\n", threadname ? threadname : "<unknown>", tid);
+}
+
+static void dump_thread(log_t* log, BacktraceMap* map, pid_t pid, pid_t tid) {
+ log_thread_name(log, tid);
std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, tid, map));
if (backtrace->Unwind(0)) {
@@ -112,6 +115,41 @@
dump_process_footer(&log, pid);
}
+void dump_backtrace_ucontext(int output_fd, ucontext_t* ucontext) {
+ pid_t pid = getpid();
+ pid_t tid = gettid();
+
+ log_t log;
+ log.tfd = output_fd;
+ log.amfd_data = nullptr;
+
+ log_thread_name(&log, tid);
+
+ std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, tid));
+ if (backtrace->Unwind(0, ucontext)) {
+ dump_backtrace_to_log(backtrace.get(), &log, " ");
+ } else {
+ ALOGE("Unwind failed: tid = %d: %s", tid,
+ backtrace->GetErrorString(backtrace->GetError()).c_str());
+ }
+}
+
+void dump_backtrace_header(int output_fd) {
+ log_t log;
+ log.tfd = output_fd;
+ log.amfd_data = nullptr;
+
+ dump_process_header(&log, getpid());
+}
+
+void dump_backtrace_footer(int output_fd) {
+ log_t log;
+ log.tfd = output_fd;
+ log.amfd_data = nullptr;
+
+ dump_process_footer(&log, getpid());
+}
+
void dump_backtrace_to_log(Backtrace* backtrace, log_t* log, const char* prefix) {
for (size_t i = 0; i < backtrace->NumFrames(); i++) {
_LOG(log, logtype::BACKTRACE, "%s%s\n", prefix, backtrace->FormatFrameData(i).c_str());
diff --git a/debuggerd/libdebuggerd/include/backtrace.h b/debuggerd/libdebuggerd/include/backtrace.h
index acd5eaa..5bfdac8 100644
--- a/debuggerd/libdebuggerd/include/backtrace.h
+++ b/debuggerd/libdebuggerd/include/backtrace.h
@@ -18,6 +18,7 @@
#define _DEBUGGERD_BACKTRACE_H
#include <sys/types.h>
+#include <sys/ucontext.h>
#include <set>
#include <string>
@@ -35,4 +36,8 @@
/* Dumps the backtrace in the backtrace data structure to the log. */
void dump_backtrace_to_log(Backtrace* backtrace, log_t* log, const char* prefix);
+void dump_backtrace_ucontext(int output_fd, ucontext_t* ucontext);
+void dump_backtrace_header(int output_fd);
+void dump_backtrace_footer(int output_fd);
+
#endif // _DEBUGGERD_BACKTRACE_H
diff --git a/debuggerd/libdebuggerd/include/tombstone.h b/debuggerd/libdebuggerd/include/tombstone.h
index aed71de..8e60278 100644
--- a/debuggerd/libdebuggerd/include/tombstone.h
+++ b/debuggerd/libdebuggerd/include/tombstone.h
@@ -39,7 +39,13 @@
const std::set<pid_t>* siblings, uintptr_t abort_msg_address,
std::string* amfd_data);
-void engrave_tombstone_ucontext(int tombstone_fd, pid_t pid, pid_t tid, uintptr_t abort_msg_address,
- siginfo_t* siginfo, ucontext_t* ucontext);
+void engrave_tombstone_ucontext(int tombstone_fd, uintptr_t abort_msg_address, siginfo_t* siginfo,
+ ucontext_t* ucontext);
+
+// Compatibility shim.
+static void engrave_tombstone_ucontext(int tombstone_fd, pid_t, pid_t, uintptr_t abort_msg_address,
+ siginfo_t* siginfo, ucontext_t* ucontext) {
+ engrave_tombstone_ucontext(tombstone_fd, abort_msg_address, siginfo, ucontext);
+}
#endif // _DEBUGGERD_TOMBSTONE_H
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index 4686bfd..c05ccc3 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -751,8 +751,11 @@
dump_crash(&log, map, open_files, pid, tid, siblings, abort_msg_address);
}
-void engrave_tombstone_ucontext(int tombstone_fd, pid_t pid, pid_t tid, uintptr_t abort_msg_address,
- siginfo_t* siginfo, ucontext_t* ucontext) {
+void engrave_tombstone_ucontext(int tombstone_fd, uintptr_t abort_msg_address, siginfo_t* siginfo,
+ ucontext_t* ucontext) {
+ pid_t pid = getpid();
+ pid_t tid = gettid();
+
log_t log;
log.current_tid = tid;
log.crashed_tid = tid;
diff --git a/debuggerd/tombstoned_client.cpp b/debuggerd/tombstoned_client.cpp
new file mode 100644
index 0000000..03b4a20
--- /dev/null
+++ b/debuggerd/tombstoned_client.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2017, 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 "debuggerd/tombstoned.h"
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <utility>
+
+#include <android-base/unique_fd.h>
+#include <cutils/sockets.h>
+
+#include "debuggerd/protocol.h"
+#include "debuggerd/util.h"
+#include "private/libc_logging.h"
+
+using android::base::unique_fd;
+
+bool tombstoned_connect(pid_t pid, unique_fd* tombstoned_socket, unique_fd* output_fd) {
+ unique_fd sockfd(socket_local_client(kTombstonedCrashSocketName,
+ ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET));
+ if (sockfd == -1) {
+ __libc_format_log(ANDROID_LOG_ERROR, "libc", "failed to connect to tombstoned: %s",
+ strerror(errno));
+ return false;
+ }
+
+ TombstonedCrashPacket packet = {};
+ packet.packet_type = CrashPacketType::kDumpRequest;
+ packet.packet.dump_request.pid = pid;
+ if (TEMP_FAILURE_RETRY(write(sockfd, &packet, sizeof(packet))) != sizeof(packet)) {
+ __libc_format_log(ANDROID_LOG_ERROR, "libc", "failed to write DumpRequest packet: %s",
+ strerror(errno));
+ return false;
+ }
+
+ unique_fd tmp_output_fd;
+ ssize_t rc = recv_fd(sockfd, &packet, sizeof(packet), &tmp_output_fd);
+ if (rc == -1) {
+ __libc_format_log(ANDROID_LOG_ERROR, "libc",
+ "failed to read response to DumpRequest packet: %s", strerror(errno));
+ return false;
+ } else if (rc != sizeof(packet)) {
+ __libc_format_log(
+ ANDROID_LOG_ERROR, "libc",
+ "received DumpRequest response packet of incorrect length (expected %zu, got %zd)",
+ sizeof(packet), rc);
+ return false;
+ }
+
+ // Make the fd O_APPEND so that our output is guaranteed to be at the end of a file.
+ // (This also makes selinux rules consistent, because selinux distinguishes between writing to
+ // a regular fd, and writing to an fd with O_APPEND).
+ int flags = fcntl(tmp_output_fd.get(), F_GETFL);
+ if (fcntl(tmp_output_fd.get(), F_SETFL, flags | O_APPEND) != 0) {
+ __libc_format_log(ANDROID_LOG_WARN, "libc", "failed to set output fd flags: %s",
+ strerror(errno));
+ }
+
+ *tombstoned_socket = std::move(sockfd);
+ *output_fd = std::move(tmp_output_fd);
+ return true;
+}
+
+bool tombstoned_notify_completion(int tombstoned_socket) {
+ TombstonedCrashPacket packet = {};
+ packet.packet_type = CrashPacketType::kCompletedDump;
+ if (TEMP_FAILURE_RETRY(write(tombstoned_socket, &packet, sizeof(packet))) != sizeof(packet)) {
+ return false;
+ }
+ return true;
+}
diff --git a/debuggerd/util.cpp b/debuggerd/util.cpp
index 738abdf..4c015d7 100644
--- a/debuggerd/util.cpp
+++ b/debuggerd/util.cpp
@@ -22,8 +22,13 @@
#include <android-base/unique_fd.h>
#include <cutils/sockets.h>
+#include <debuggerd/protocol.h>
-ssize_t send_fd(int sockfd, const void* data, size_t len, android::base::unique_fd fd) {
+#include "private/libc_logging.h"
+
+using android::base::unique_fd;
+
+ssize_t send_fd(int sockfd, const void* data, size_t len, unique_fd fd) {
char cmsg_buf[CMSG_SPACE(sizeof(int))];
iovec iov = { .iov_base = const_cast<void*>(data), .iov_len = len };
@@ -39,8 +44,7 @@
return TEMP_FAILURE_RETRY(sendmsg(sockfd, &msg, 0));
}
-ssize_t recv_fd(int sockfd, void* _Nonnull data, size_t len,
- android::base::unique_fd* _Nullable out_fd) {
+ssize_t recv_fd(int sockfd, void* _Nonnull data, size_t len, unique_fd* _Nullable out_fd) {
char cmsg_buf[CMSG_SPACE(sizeof(int))];
iovec iov = { .iov_base = const_cast<void*>(data), .iov_len = len };
@@ -61,7 +65,7 @@
return -1;
}
- android::base::unique_fd fd;
+ unique_fd fd;
bool received_fd = msg.msg_controllen == sizeof(cmsg_buf);
if (received_fd) {
fd.reset(*reinterpret_cast<int*>(CMSG_DATA(cmsg)));
@@ -85,7 +89,7 @@
return result;
}
-bool Pipe(android::base::unique_fd* read, android::base::unique_fd* write) {
+bool Pipe(unique_fd* read, unique_fd* write) {
int pipefds[2];
if (pipe(pipefds) != 0) {
return false;
diff --git a/fingerprintd/FingerprintDaemonProxy.cpp b/fingerprintd/FingerprintDaemonProxy.cpp
index 1c7da30..b3c0cd7 100644
--- a/fingerprintd/FingerprintDaemonProxy.cpp
+++ b/fingerprintd/FingerprintDaemonProxy.cpp
@@ -31,7 +31,7 @@
FingerprintDaemonProxy* FingerprintDaemonProxy::sInstance = NULL;
// Supported fingerprint HAL version
-static const uint16_t kVersion = HARDWARE_MODULE_API_VERSION(2, 0);
+static const uint16_t kVersion = HARDWARE_MODULE_API_VERSION(2, 1);
FingerprintDaemonProxy::FingerprintDaemonProxy() : mModule(NULL), mDevice(NULL), mCallback(NULL) {
diff --git a/gatekeeperd/gatekeeperd.cpp b/gatekeeperd/gatekeeperd.cpp
index d4a92e5..96bda07 100644
--- a/gatekeeperd/gatekeeperd.cpp
+++ b/gatekeeperd/gatekeeperd.cpp
@@ -166,7 +166,14 @@
enrolled_password_handle, enrolled_password_handle_length);
}
- if (ret == 0) {
+ if (ret == GATEKEEPER_RESPONSE_OK && (*enrolled_password_handle == nullptr ||
+ *enrolled_password_handle_length != sizeof(password_handle_t))) {
+ ret = GATEKEEPER_RESPONSE_ERROR;
+ ALOGE("HAL: password_handle=%p size_of_handle=%" PRIu32 "\n",
+ *enrolled_password_handle, *enrolled_password_handle_length);
+ }
+
+ if (ret == GATEKEEPER_RESPONSE_OK) {
gatekeeper::password_handle_t *handle =
reinterpret_cast<gatekeeper::password_handle_t *>(*enrolled_password_handle);
store_sid(uid, handle->user_id);
diff --git a/healthd/Android.mk b/healthd/Android.mk
index 7c5e35b..b292725 100644
--- a/healthd/Android.mk
+++ b/healthd/Android.mk
@@ -21,6 +21,10 @@
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
+ifeq ($(strip $(BOARD_CHARGER_ENABLE_SUSPEND)),true)
+LOCAL_CFLAGS += -DCHARGER_ENABLE_SUSPEND
+LOCAL_SHARED_LIBRARIES += libsuspend
+endif
LOCAL_SRC_FILES := \
healthd_mode_android.cpp \
healthd_mode_charger.cpp \
@@ -90,6 +94,14 @@
LOCAL_C_INCLUDES := bootable/recovery $(LOCAL_PATH)/include
+ifneq ($(BOARD_PERIODIC_CHORES_INTERVAL_FAST),)
+LOCAL_CFLAGS += -DBOARD_PERIODIC_CHORES_INTERVAL_FAST=$(BOARD_PERIODIC_CHORES_INTERVAL_FAST)
+endif
+
+ifneq ($(BOARD_PERIODIC_CHORES_INTERVAL_SLOW),)
+LOCAL_CFLAGS += -DBOARD_PERIODIC_CHORES_INTERVAL_SLOW=$(BOARD_PERIODIC_CHORES_INTERVAL_SLOW)
+endif
+
LOCAL_STATIC_LIBRARIES := \
libhealthd_internal \
libbatterymonitor \
diff --git a/healthd/healthd.cpp b/healthd/healthd.cpp
index 20a6bf6..aa6735d 100644
--- a/healthd/healthd.cpp
+++ b/healthd/healthd.cpp
@@ -35,9 +35,19 @@
using namespace android;
-// Periodic chores intervals in seconds
-#define DEFAULT_PERIODIC_CHORES_INTERVAL_FAST (60 * 1)
-#define DEFAULT_PERIODIC_CHORES_INTERVAL_SLOW (60 * 10)
+#ifndef BOARD_PERIODIC_CHORES_INTERVAL_FAST
+ // Periodic chores fast interval in seconds
+ #define DEFAULT_PERIODIC_CHORES_INTERVAL_FAST (60 * 1)
+#else
+ #define DEFAULT_PERIODIC_CHORES_INTERVAL_FAST (BOARD_PERIODIC_CHORES_INTERVAL_FAST)
+#endif
+
+#ifndef BOARD_PERIODIC_CHORES_INTERVAL_SLOW
+ // Periodic chores fast interval in seconds
+ #define DEFAULT_PERIODIC_CHORES_INTERVAL_SLOW (60 * 10)
+#else
+ #define DEFAULT_PERIODIC_CHORES_INTERVAL_SLOW (BOARD_PERIODIC_CHORES_INTERVAL_SLOW)
+#endif
static struct healthd_config healthd_config = {
.periodic_chores_interval_fast = DEFAULT_PERIODIC_CHORES_INTERVAL_FAST,
@@ -143,10 +153,14 @@
struct android::BatteryProperties* /*props*/) {
}
-int healthd_register_event(int fd, void (*handler)(uint32_t)) {
+int healthd_register_event(int fd, void (*handler)(uint32_t), EventWakeup wakeup) {
struct epoll_event ev;
- ev.events = EPOLLIN | EPOLLWAKEUP;
+ ev.events = EPOLLIN;
+
+ if (wakeup == EVENT_WAKEUP_FD)
+ ev.events |= EPOLLWAKEUP;
+
ev.data.ptr = (void *)handler;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
KLOG_ERROR(LOG_TAG,
@@ -252,7 +266,7 @@
}
fcntl(uevent_fd, F_SETFL, O_NONBLOCK);
- if (healthd_register_event(uevent_fd, uevent_event))
+ if (healthd_register_event(uevent_fd, uevent_event, EVENT_WAKEUP_FD))
KLOG_ERROR(LOG_TAG,
"register for uevent events failed\n");
}
@@ -275,7 +289,7 @@
return;
}
- if (healthd_register_event(wakealarm_fd, wakealarm_event))
+ if (healthd_register_event(wakealarm_fd, wakealarm_event, EVENT_WAKEUP_FD))
KLOG_ERROR(LOG_TAG,
"Registration of wakealarm event failed\n");
@@ -283,17 +297,22 @@
}
static void healthd_mainloop(void) {
+ int nevents = 0;
while (1) {
struct epoll_event events[eventct];
- int nevents;
int timeout = awake_poll_interval;
int mode_timeout;
+ /* Don't wait for first timer timeout to run periodic chores */
+ if (!nevents)
+ periodic_chores();
+
+ healthd_mode_ops->heartbeat();
+
mode_timeout = healthd_mode_ops->preparetowait();
if (timeout < 0 || (mode_timeout > 0 && mode_timeout < timeout))
timeout = mode_timeout;
nevents = epoll_wait(epollfd, events, eventct, timeout);
-
if (nevents == -1) {
if (errno == EINTR)
continue;
@@ -305,11 +324,6 @@
if (events[n].data.ptr)
(*(void (*)(int))events[n].data.ptr)(events[n].events);
}
-
- if (!nevents)
- periodic_chores();
-
- healthd_mode_ops->heartbeat();
}
return;
diff --git a/healthd/healthd_mode_charger.cpp b/healthd/healthd_mode_charger.cpp
index 2f69372..91774c6 100644
--- a/healthd/healthd_mode_charger.cpp
+++ b/healthd/healthd_mode_charger.cpp
@@ -343,14 +343,19 @@
static void draw_percent(const animation& anim)
{
- if (anim.cur_level <= 0 || anim.cur_status != BATTERY_STATUS_CHARGING) return;
+ int cur_level = anim.cur_level;
+ if (anim.cur_status == BATTERY_STATUS_FULL) {
+ cur_level = 100;
+ }
+
+ if (cur_level <= 0) return;
const animation::text_field& field = anim.text_percent;
if (field.font == nullptr || field.font->char_width == 0 || field.font->char_height == 0) {
return;
}
- std::string str = base::StringPrintf("%d%%", anim.cur_level);
+ std::string str = base::StringPrintf("%d%%", cur_level);
int x, y;
determine_xy(field, str.size(), &x, &y);
@@ -840,7 +845,7 @@
std::placeholders::_2));
if (!ret) {
epollfd = ev_get_epollfd();
- healthd_register_event(epollfd, charger_event_handler);
+ healthd_register_event(epollfd, charger_event_handler, EVENT_WAKEUP_FD);
}
struct animation* anim = init_animation();
diff --git a/healthd/include/healthd/healthd.h b/healthd/include/healthd/healthd.h
index 34ea55f..17efbd6 100644
--- a/healthd/include/healthd/healthd.h
+++ b/healthd/include/healthd/healthd.h
@@ -73,9 +73,14 @@
bool (*screen_on)(android::BatteryProperties *props);
};
+enum EventWakeup {
+ EVENT_NO_WAKEUP_FD,
+ EVENT_WAKEUP_FD,
+};
+
// Global helper functions
-int healthd_register_event(int fd, void (*handler)(uint32_t));
+int healthd_register_event(int fd, void (*handler)(uint32_t), EventWakeup wakeup = EVENT_NO_WAKEUP_FD);
void healthd_battery_update();
android::status_t healthd_get_property(int id,
struct android::BatteryProperty *val);
diff --git a/include/system/qemu_pipe.h b/include/system/qemu_pipe.h
new file mode 100644
index 0000000..af25079
--- /dev/null
+++ b/include/system/qemu_pipe.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+#ifndef ANDROID_INCLUDE_SYSTEM_QEMU_PIPE_H
+#define ANDROID_INCLUDE_SYSTEM_QEMU_PIPE_H
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+
+// Define QEMU_PIPE_DEBUG if you want to print error messages when an error
+// occurs during pipe operations. The macro should simply take a printf-style
+// formatting string followed by optional arguments.
+#ifndef QEMU_PIPE_DEBUG
+# define QEMU_PIPE_DEBUG(...) (void)0
+#endif
+
+// Try to open a new Qemu fast-pipe. This function returns a file descriptor
+// that can be used to communicate with a named service managed by the
+// emulator.
+//
+// This file descriptor can be used as a standard pipe/socket descriptor.
+//
+// 'pipeName' is the name of the emulator service you want to connect to,
+// and must begin with 'pipe:' (e.g. 'pipe:camera' or 'pipe:opengles').
+//
+// On success, return a valid file descriptor, or -1/errno on failure. E.g.:
+//
+// EINVAL -> unknown/unsupported pipeName
+// ENOSYS -> fast pipes not available in this system.
+//
+// ENOSYS should never happen, except if you're trying to run within a
+// misconfigured emulator.
+//
+// You should be able to open several pipes to the same pipe service,
+// except for a few special cases (e.g. GSM modem), where EBUSY will be
+// returned if more than one client tries to connect to it.
+static __inline__ int qemu_pipe_open(const char* pipeName) {
+ // Sanity check.
+ if (!pipeName || memcmp(pipeName, "pipe:", 5) != 0) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ int fd = TEMP_FAILURE_RETRY(open("/dev/qemu_pipe", O_RDWR));
+ if (fd < 0) {
+ QEMU_PIPE_DEBUG("%s: Could not open /dev/qemu_pipe: %s", __FUNCTION__,
+ strerror(errno));
+ return -1;
+ }
+
+ // Write the pipe name, *including* the trailing zero which is necessary.
+ size_t pipeNameLen = strlen(pipeName);
+ ssize_t ret = TEMP_FAILURE_RETRY(write(fd, pipeName, pipeNameLen + 1U));
+ if (ret != (ssize_t)pipeNameLen + 1) {
+ QEMU_PIPE_DEBUG("%s: Could not connect to %s pipe service: %s",
+ __FUNCTION__, pipeName, strerror(errno));
+ if (ret == 0) {
+ errno = ECONNRESET;
+ } else if (ret > 0) {
+ errno = EINVAL;
+ }
+ return -1;
+ }
+ return fd;
+}
+
+// Send a framed message |buff| of |len| bytes through the |fd| descriptor.
+// This really adds a 4-hexchar prefix describing the payload size.
+// Returns 0 on success, and -1 on error.
+static int __inline__ qemu_pipe_frame_send(int fd,
+ const void* buff,
+ size_t len) {
+ char header[5];
+ snprintf(header, sizeof(header), "%04zx", len);
+ ssize_t ret = TEMP_FAILURE_RETRY(write(fd, header, 4));
+ if (ret != 4) {
+ QEMU_PIPE_DEBUG("Can't write qemud frame header: %s", strerror(errno));
+ return -1;
+ }
+ ret = TEMP_FAILURE_RETRY(write(fd, buff, len));
+ if (ret != (ssize_t)len) {
+ QEMU_PIPE_DEBUG("Can't write qemud frame payload: %s", strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+
+// Read a frame message from |fd|, and store it into |buff| of |len| bytes.
+// If the framed message is larger than |len|, then this returns -1 and the
+// content is lost. Otherwise, this returns the size of the message. NOTE:
+// empty messages are possible in a framed wire protocol and do not mean
+// end-of-stream.
+static int __inline__ qemu_pipe_frame_recv(int fd, void* buff, size_t len) {
+ char header[5];
+ ssize_t ret = TEMP_FAILURE_RETRY(read(fd, header, 4));
+ if (ret != 4) {
+ QEMU_PIPE_DEBUG("Can't read qemud frame header: %s", strerror(errno));
+ return -1;
+ }
+ header[4] = '\0';
+ size_t size;
+ if (sscanf(header, "%04zx", &size) != 1) {
+ QEMU_PIPE_DEBUG("Malformed qemud frame header: [%.*s]", 4, header);
+ return -1;
+ }
+ if (size > len) {
+ QEMU_PIPE_DEBUG("Oversized qemud frame (% bytes, expected <= %)", size,
+ len);
+ return -1;
+ }
+ ret = TEMP_FAILURE_RETRY(read(fd, buff, size));
+ if (ret != (ssize_t)size) {
+ QEMU_PIPE_DEBUG("Could not read qemud frame payload: %s",
+ strerror(errno));
+ return -1;
+ }
+ return size;
+}
+
+#endif /* ANDROID_INCLUDE_HARDWARE_QEMUD_PIPE_H */
diff --git a/init/Android.mk b/init/Android.mk
index 2fc6f19..5bcfb7b 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -119,7 +119,14 @@
mapping_sepolicy.cil \
nonplat_sepolicy.cil \
plat_sepolicy.cil \
+ plat_sepolicy.cil.sha256 \
secilc
+
+# Include precompiled policy, unless told otherwise
+ifneq ($(PRODUCT_PRECOMPILED_SEPOLICY),false)
+LOCAL_REQUIRED_MODULES += precompiled_sepolicy precompiled_sepolicy.plat.sha256
+endif
+
else
# Use monolithic SELinux policy
LOCAL_REQUIRED_MODULES += sepolicy
diff --git a/init/init.cpp b/init/init.cpp
index 81f228c..5ab421b 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -715,6 +715,44 @@
}
}
+static bool read_first_line(const char* file, std::string* line) {
+ line->clear();
+
+ std::string contents;
+ if (!android::base::ReadFileToString(file, &contents, true /* follow symlinks */)) {
+ return false;
+ }
+ std::istringstream in(contents);
+ std::getline(in, *line);
+ return true;
+}
+
+static bool selinux_find_precompiled_split_policy(std::string* file) {
+ file->clear();
+
+ static constexpr const char precompiled_sepolicy[] = "/vendor/etc/selinux/precompiled_sepolicy";
+ if (access(precompiled_sepolicy, R_OK) == -1) {
+ return false;
+ }
+ std::string actual_plat_id;
+ if (!read_first_line("/system/etc/selinux/plat_sepolicy.cil.sha256", &actual_plat_id)) {
+ PLOG(INFO) << "Failed to read /system/etc/selinux/plat_sepolicy.cil.sha256";
+ return false;
+ }
+ std::string precompiled_plat_id;
+ if (!read_first_line("/vendor/etc/selinux/precompiled_sepolicy.plat.sha256",
+ &precompiled_plat_id)) {
+ PLOG(INFO) << "Failed to read /vendor/etc/selinux/precompiled_sepolicy.plat.sha256";
+ return false;
+ }
+ if ((actual_plat_id.empty()) || (actual_plat_id != precompiled_plat_id)) {
+ return false;
+ }
+
+ *file = precompiled_sepolicy;
+ return true;
+}
+
static constexpr const char plat_policy_cil_file[] = "/system/etc/selinux/plat_sepolicy.cil";
static bool selinux_is_split_policy_device() { return access(plat_policy_cil_file, R_OK) != -1; }
@@ -734,8 +772,32 @@
// secilc is invoked to compile the above three policy files into a single monolithic policy
// file. This file is then loaded into the kernel.
+ // Load precompiled policy from vendor image, if a matching policy is found there. The policy
+ // must match the platform policy on the system image.
+ std::string precompiled_sepolicy_file;
+ if (selinux_find_precompiled_split_policy(&precompiled_sepolicy_file)) {
+ android::base::unique_fd fd(
+ open(precompiled_sepolicy_file.c_str(), O_RDONLY | O_CLOEXEC | O_BINARY));
+ if (fd != -1) {
+ if (selinux_android_load_policy_from_fd(fd, precompiled_sepolicy_file.c_str()) < 0) {
+ LOG(ERROR) << "Failed to load SELinux policy from " << precompiled_sepolicy_file;
+ return false;
+ }
+ return true;
+ }
+ }
+ // No suitable precompiled policy could be loaded
+
LOG(INFO) << "Compiling SELinux policy";
+ // Determine the highest policy language version supported by the kernel
+ set_selinuxmnt("/sys/fs/selinux");
+ int max_policy_version = security_policyvers();
+ if (max_policy_version == -1) {
+ PLOG(ERROR) << "Failed to determine highest policy version supported by kernel";
+ return false;
+ }
+
// We store the output of the compilation on /dev because this is the most convenient tmpfs
// storage mount available this early in the boot sequence.
char compiled_sepolicy[] = "/dev/sepolicy.XXXXXX";
@@ -745,14 +807,20 @@
return false;
}
- const char* compile_args[] = {"/system/bin/secilc", plat_policy_cil_file, "-M", "true", "-c",
- "30", // TODO: pass in SELinux policy version from build system
- "/vendor/etc/selinux/mapping_sepolicy.cil",
- "/vendor/etc/selinux/nonplat_sepolicy.cil", "-o",
- compiled_sepolicy,
- // We don't care about file_contexts output by the compiler
- "-f", "/sys/fs/selinux/null", // /dev/null is not yet available
- nullptr};
+ // clang-format off
+ const char* compile_args[] = {
+ "/system/bin/secilc",
+ plat_policy_cil_file,
+ "-M", "true",
+ // Target the highest policy language version supported by the kernel
+ "-c", std::to_string(max_policy_version).c_str(),
+ "/vendor/etc/selinux/mapping_sepolicy.cil",
+ "/vendor/etc/selinux/nonplat_sepolicy.cil",
+ "-o", compiled_sepolicy,
+ // We don't care about file_contexts output by the compiler
+ "-f", "/sys/fs/selinux/null", // /dev/null is not yet available
+ nullptr};
+ // clang-format on
if (!fork_execve_and_wait_for_completion(compile_args[0], (char**)compile_args, (char**)ENV)) {
unlink(compiled_sepolicy);
diff --git a/liblog/Android.bp b/liblog/Android.bp
index 310dbf4..bb8c3af 100644
--- a/liblog/Android.bp
+++ b/liblog/Android.bp
@@ -26,6 +26,7 @@
"logger_read.c",
"logger_write.c",
"logprint.c",
+ "stderr_write.c",
]
liblog_host_sources = [
"fake_log_device.c",
diff --git a/liblog/config_write.c b/liblog/config_write.c
index 583dcff..6a6c220 100644
--- a/liblog/config_write.c
+++ b/liblog/config_write.c
@@ -78,6 +78,29 @@
&fakeLoggerWrite);
#endif
}
+
+ if (__android_log_frontend & LOGGER_STDERR) {
+ extern struct android_log_transport_write stderrLoggerWrite;
+
+ /*
+ * stderr logger should be primary if we can be the only one, or if
+ * already in the primary list. Otherwise land in the persist list.
+ * Remember we can be called here if we are already initialized.
+ */
+ if (list_empty(&__android_log_transport_write)) {
+ __android_log_add_transport(&__android_log_transport_write,
+ &stderrLoggerWrite);
+ } else {
+ struct android_log_transport_write *transp;
+ write_transport_for_each(transp, &__android_log_transport_write) {
+ if (transp == &stderrLoggerWrite) {
+ return;
+ }
+ }
+ __android_log_add_transport(&__android_log_persist_write,
+ &stderrLoggerWrite);
+ }
+ }
}
LIBLOG_HIDDEN void __android_log_config_write_close() {
diff --git a/liblog/include/log/log_frontend.h b/liblog/include/log/log_frontend.h
index 9527779..5efa548 100644
--- a/liblog/include/log/log_frontend.h
+++ b/liblog/include/log/log_frontend.h
@@ -17,11 +17,12 @@
/*
* Logging frontends, bit mask to select features. Function returns selection.
*/
-#define LOGGER_DEFAULT 0x0
-#define LOGGER_LOGD 0x1
-#define LOGGER_KERNEL 0x2 /* Reserved/Deprecated */
-#define LOGGER_NULL 0x4 /* Does not release resources of other selections */
-#define LOGGER_LOCAL 0x8 /* logs sent to local memory */
+#define LOGGER_DEFAULT 0x00
+#define LOGGER_LOGD 0x01
+#define LOGGER_KERNEL 0x02 /* Reserved/Deprecated */
+#define LOGGER_NULL 0x04 /* Does not release resources of other selections */
+#define LOGGER_LOCAL 0x08 /* logs sent to local memory */
+#define LOGGER_STDERR 0x10 /* logs sent to stderr */
/* Both return the selected frontend flag mask, or negative errno */
int android_set_log_frontend(int frontend_flag);
diff --git a/liblog/logger_write.c b/liblog/logger_write.c
index e149e68..2a97101 100644
--- a/liblog/logger_write.c
+++ b/liblog/logger_write.c
@@ -664,9 +664,9 @@
return retval;
}
- __android_log_frontend &= LOGGER_LOCAL | LOGGER_LOGD;
+ __android_log_frontend &= LOGGER_LOCAL | LOGGER_LOGD | LOGGER_STDERR;
- frontend_flag &= LOGGER_LOCAL | LOGGER_LOGD;
+ frontend_flag &= LOGGER_LOCAL | LOGGER_LOGD | LOGGER_STDERR;
if (__android_log_frontend != frontend_flag) {
__android_log_frontend = frontend_flag;
@@ -695,7 +695,7 @@
if (write_to_log == __write_to_log_null) {
ret = LOGGER_NULL;
} else {
- __android_log_frontend &= LOGGER_LOCAL | LOGGER_LOGD;
+ __android_log_frontend &= LOGGER_LOCAL | LOGGER_LOGD | LOGGER_STDERR;
ret = __android_log_frontend;
if ((write_to_log != __write_to_log_init) &&
(write_to_log != __write_to_log_daemon)) {
diff --git a/liblog/stderr_write.c b/liblog/stderr_write.c
new file mode 100644
index 0000000..b739299
--- /dev/null
+++ b/liblog/stderr_write.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*
+ * stderr write handler. Output is logcat-like, and responds to
+ * logcat's environment variables ANDROID_PRINTF_LOG and
+ * ANDROID_LOG_TAGS to filter output.
+ *
+ * This transport only provides a writer, that means that it does not
+ * provide an End-To-End capability as the logs are effectively _lost_
+ * to the stderr file stream. The purpose of this transport is to
+ * supply a means for command line tools to report their logging
+ * to the stderr stream, in line with all other activities.
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <log/event_tag_map.h>
+#include <log/log.h>
+#include <log/logprint.h>
+#include <log/uio.h>
+
+#include "log_portability.h"
+#include "logger.h"
+
+static int stderrOpen();
+static void stderrClose();
+static int stderrAvailable(log_id_t logId);
+static int stderrWrite(log_id_t logId, struct timespec* ts,
+ struct iovec* vec, size_t nr);
+
+struct stderrContext {
+ AndroidLogFormat* logformat;
+#if defined(__ANDROID__)
+ EventTagMap* eventTagMap;
+#endif
+};
+
+LIBLOG_HIDDEN struct android_log_transport_write stderrLoggerWrite = {
+ .node = { &stderrLoggerWrite.node, &stderrLoggerWrite.node },
+ .context.private = NULL,
+ .name = "stderr",
+ .available = stderrAvailable,
+ .open = stderrOpen,
+ .close = stderrClose,
+ .write = stderrWrite,
+};
+
+static int stderrOpen()
+{
+ struct stderrContext* ctx;
+ const char* envStr;
+ bool setFormat;
+
+ if (!stderr || (fileno(stderr) < 0)) {
+ return -EBADF;
+ }
+
+ if (stderrLoggerWrite.context.private) {
+ return fileno(stderr);
+ }
+
+ ctx = calloc(1, sizeof(struct stderrContext));
+ if (!ctx) {
+ return -ENOMEM;
+ }
+
+ ctx->logformat = android_log_format_new();
+ if (!ctx->logformat) {
+ free(ctx);
+ return -ENOMEM;
+ }
+
+ envStr = getenv("ANDROID_PRINTF_LOG");
+ setFormat = false;
+
+ if (envStr) {
+ char* formats = strdup(envStr);
+ char* sv = NULL;
+ char* arg = formats;
+ while (!!(arg = strtok_r(arg, ",:; \t\n\r\f", &sv))) {
+ AndroidLogPrintFormat format = android_log_formatFromString(arg);
+ arg = NULL;
+ if (format == FORMAT_OFF) {
+ continue;
+ }
+ if (android_log_setPrintFormat(ctx->logformat, format) <= 0) {
+ continue;
+ }
+ setFormat = true;
+ }
+ free(formats);
+ }
+ if (!setFormat) {
+ AndroidLogPrintFormat format = android_log_formatFromString(
+ "threadtime");
+ android_log_setPrintFormat(ctx->logformat, format);
+ }
+ envStr = getenv("ANDROID_LOG_TAGS");
+ if (envStr) {
+ android_log_addFilterString(ctx->logformat, envStr);
+ }
+ stderrLoggerWrite.context.private = ctx;
+
+ return fileno(stderr);
+}
+
+static void stderrClose()
+{
+ struct stderrContext* ctx = stderrLoggerWrite.context.private;
+
+ if (ctx) {
+ stderrLoggerWrite.context.private = NULL;
+ if (ctx->logformat) {
+ android_log_format_free(ctx->logformat);
+ ctx->logformat = NULL;
+ }
+#if defined(__ANDROID__)
+ if (ctx->eventTagMap) {
+ android_closeEventTagMap(ctx->eventTagMap);
+ ctx->eventTagMap = NULL;
+ }
+#endif
+ }
+}
+
+static int stderrAvailable(log_id_t logId)
+{
+ if ((logId >= LOG_ID_MAX) || (logId == LOG_ID_KERNEL)) {
+ return -EINVAL;
+ }
+ return 1;
+}
+
+static int stderrWrite(log_id_t logId, struct timespec* ts,
+ struct iovec* vec, size_t nr)
+{
+ struct log_msg log_msg;
+ AndroidLogEntry entry;
+ char binaryMsgBuf[1024];
+ int err;
+ size_t i;
+ struct stderrContext* ctx = stderrLoggerWrite.context.private;
+
+ if (!ctx) return -EBADF;
+ if (!vec || !nr) return -EINVAL;
+
+ log_msg.entry.len = 0;
+ log_msg.entry.hdr_size = sizeof(log_msg.entry);
+ log_msg.entry.pid = getpid();
+#ifdef __BIONIC__
+ log_msg.entry.tid = gettid();
+#else
+ log_msg.entry.tid = getpid();
+#endif
+ log_msg.entry.sec = ts->tv_sec;
+ log_msg.entry.nsec = ts->tv_nsec;
+ log_msg.entry.lid = logId;
+ log_msg.entry.uid = __android_log_uid();
+
+ for (i = 0; i < nr; ++i) {
+ size_t len = vec[i].iov_len;
+ if ((log_msg.entry.len + len) > LOGGER_ENTRY_MAX_PAYLOAD) {
+ len = LOGGER_ENTRY_MAX_PAYLOAD - log_msg.entry.len;
+ }
+ if (!len) continue;
+ memcpy(log_msg.entry.msg + log_msg.entry.len, vec[i].iov_base, len);
+ log_msg.entry.len += len;
+ }
+
+ if ((logId == LOG_ID_EVENTS) || (logId == LOG_ID_SECURITY)) {
+#if defined(__ANDROID__)
+ if (!ctx->eventTagMap) {
+ ctx->eventTagMap = android_openEventTagMap(NULL);
+ }
+#endif
+ err = android_log_processBinaryLogBuffer(&log_msg.entry_v1,
+ &entry,
+#if defined(__ANDROID__)
+ ctx->eventTagMap,
+#else
+ NULL,
+#endif
+ binaryMsgBuf,
+ sizeof(binaryMsgBuf));
+ } else {
+ err = android_log_processLogBuffer(&log_msg.entry_v1, &entry);
+ }
+
+ /* print known truncated data, in essence logcat --debug */
+ if ((err < 0) && !entry.message) return -EINVAL;
+
+ if (!android_log_shouldPrintLine(ctx->logformat, entry.tag, entry.priority)) {
+ return log_msg.entry.len;
+ }
+
+ err = android_log_printLogLine(ctx->logformat, fileno(stderr), &entry);
+ if (err < 0) return errno ? -errno : -EINVAL;
+ return log_msg.entry.len;
+}
diff --git a/liblog/tests/Android.mk b/liblog/tests/Android.mk
index cfea452..0e6432c 100644
--- a/liblog/tests/Android.mk
+++ b/liblog/tests/Android.mk
@@ -57,6 +57,8 @@
test_src_files := \
liblog_test_default.cpp \
liblog_test_local.cpp \
+ liblog_test_stderr.cpp \
+ liblog_test_stderr_local.cpp \
log_id_test.cpp \
log_radio_test.cpp \
log_read_test.cpp \
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index bc0ea4c..2537fac 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -47,7 +47,7 @@
#endif
#endif
-#if (!defined(USING_LOGGER_DEFAULT) || !defined(USING_LOGGER_LOCAL))
+#if (!defined(USING_LOGGER_DEFAULT) || !defined(USING_LOGGER_LOCAL) || !defined(USING_LOGGER_STDERR))
#ifdef liblog // a binary clue that we are overriding the test names
// Does not support log reading blocking feature yet
// Does not support LOG_ID_SECURITY (unless we set LOGGER_LOCAL | LOGGER_LOGD)
@@ -62,6 +62,11 @@
#define USING_LOGGER_DEFAULT
#endif
#endif
+#ifdef USING_LOGGER_STDERR
+# define SUPPORTS_END_TO_END 0
+#else
+# define SUPPORTS_END_TO_END 1
+#endif
// enhanced version of LOG_FAILURE_RETRY to add support for EAGAIN and
// non-syscall libs. Since we are only using this in the emergency of
@@ -98,7 +103,7 @@
usleep(1000);
}
-#if (defined(__ANDROID__) && !defined(USING_LOGGER_LOCAL))
+#if (defined(__ANDROID__) && defined(USING_LOGGER_DEFAULT))
static std::string popenToString(std::string command) {
std::string ret;
@@ -176,8 +181,8 @@
LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
log_time ts(CLOCK_MONOTONIC);
- ASSERT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
-#ifndef USING_LOGGER_LOCAL
+ EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
+#ifdef USING_LOGGER_DEFAULT
// Check that we can close and reopen the logger
bool pmsgActiveAfter__android_log_btwrite;
bool logdwActiveAfter__android_log_btwrite;
@@ -200,8 +205,8 @@
#endif
log_time ts1(CLOCK_MONOTONIC);
- ASSERT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts1, sizeof(ts1)));
-#ifndef USING_LOGGER_LOCAL
+ EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts1, sizeof(ts1)));
+#ifdef USING_LOGGER_DEFAULT
if (getuid() == AID_ROOT) {
pmsgActiveAfter__android_log_btwrite = isPmsgActive();
logdwActiveAfter__android_log_btwrite = isLogdwActive();
@@ -220,7 +225,7 @@
break;
}
- ASSERT_EQ(log_msg.entry.pid, pid);
+ EXPECT_EQ(log_msg.entry.pid, pid);
if ((log_msg.entry.len != sizeof(android_log_event_long_t))
|| (log_msg.id() != LOG_ID_EVENTS)) {
@@ -242,8 +247,8 @@
}
}
- EXPECT_EQ(1, count);
- EXPECT_EQ(1, second_count);
+ EXPECT_EQ(SUPPORTS_END_TO_END, count);
+ EXPECT_EQ(SUPPORTS_END_TO_END, second_count);
android_logger_list_close(logger_list);
#else
@@ -251,6 +256,54 @@
#endif
}
+#if (defined(__ANDROID__) || defined(USING_LOGGER_LOCAL))
+static void print_frontend(const char* prefix, int logger) {
+ static const char orstr[] = " | ";
+
+ if (!prefix) {
+ prefix = "";
+ }
+ if (logger < 0) {
+ fprintf(stderr, "%s%s\n", prefix, strerror(-logger));
+ return;
+ }
+
+ if (logger == LOGGER_DEFAULT) {
+ fprintf(stderr, "%sLOGGER_DEFAULT", prefix);
+ prefix = orstr;
+ }
+ if (logger & LOGGER_LOGD) {
+ fprintf(stderr, "%sLOGGER_LOGD", prefix);
+ prefix = orstr;
+ }
+ if (logger & LOGGER_KERNEL) {
+ fprintf(stderr, "%sLOGGER_KERNEL", prefix);
+ prefix = orstr;
+ }
+ if (logger & LOGGER_NULL) {
+ fprintf(stderr, "%sLOGGER_NULL", prefix);
+ prefix = orstr;
+ }
+ if (logger & LOGGER_LOCAL) {
+ fprintf(stderr, "%sLOGGER_LOCAL", prefix);
+ prefix = orstr;
+ }
+ if (logger & LOGGER_STDERR) {
+ fprintf(stderr, "%sLOGGER_STDERR", prefix);
+ prefix = orstr;
+ }
+ logger &= ~(LOGGER_LOGD | LOGGER_KERNEL | LOGGER_NULL | LOGGER_LOCAL |
+ LOGGER_STDERR);
+ if (logger) {
+ fprintf(stderr, "%s0x%x", prefix, logger);
+ prefix = orstr;
+ }
+ if (prefix == orstr) {
+ fprintf(stderr, "\n");
+ }
+}
+#endif
+
// This test makes little sense standalone, and requires the tests ahead
// and behind us, to make us whole. We could incorporate a prefix and
// suffix test to make this standalone, but opted to not complicate this.
@@ -261,10 +314,14 @@
#endif
int logger = android_get_log_frontend();
+ print_frontend("android_get_log_frontend = ", logger);
EXPECT_NE(LOGGER_NULL, logger);
- EXPECT_EQ(LOGGER_NULL, android_set_log_frontend(LOGGER_NULL));
- EXPECT_EQ(LOGGER_NULL, android_get_log_frontend());
+ int ret;
+ EXPECT_EQ(LOGGER_NULL, ret = android_set_log_frontend(LOGGER_NULL));
+ print_frontend("android_set_log_frontend = ", ret);
+ EXPECT_EQ(LOGGER_NULL, ret = android_get_log_frontend());
+ print_frontend("android_get_log_frontend = ", ret);
pid_t pid = getpid();
@@ -273,7 +330,7 @@
LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
log_time ts(CLOCK_MONOTONIC);
- ASSERT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
+ EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
usleep(1000000);
@@ -285,7 +342,7 @@
break;
}
- ASSERT_EQ(log_msg.entry.pid, pid);
+ EXPECT_EQ(log_msg.entry.pid, pid);
if ((log_msg.entry.len != sizeof(android_log_event_long_t))
|| (log_msg.id() != LOG_ID_EVENTS)) {
@@ -307,8 +364,10 @@
android_logger_list_close(logger_list);
- EXPECT_EQ(logger, android_set_log_frontend(logger));
- EXPECT_EQ(logger, android_get_log_frontend());
+ EXPECT_EQ(logger, ret = android_set_log_frontend(logger));
+ print_frontend("android_set_log_frontend = ", ret);
+ EXPECT_EQ(logger, ret = android_get_log_frontend());
+ print_frontend("android_get_log_frontend = ", ret);
// False negative if liblog.__android_log_btwrite__android_logger_list_read
// fails above, so we will likely succeed. But we will have so many
@@ -350,7 +409,7 @@
log_time ts(CLOCK_REALTIME);
#endif
- ASSERT_LT(0, __android_log_bswrite(0, message));
+ EXPECT_LT(0, __android_log_bswrite(0, message));
size_t num_lines = 1, size = 0, length = 0, total = 0;
const char *cp = message;
while (*cp) {
@@ -382,7 +441,7 @@
break;
}
- ASSERT_EQ(log_msg.entry.pid, pid);
+ EXPECT_EQ(log_msg.entry.pid, pid);
if ((log_msg.entry.sec < (ts.tv_sec - 1))
|| ((ts.tv_sec + 1) < log_msg.entry.sec)
@@ -413,19 +472,26 @@
int processBinaryLogBuffer = android_log_processBinaryLogBuffer(
&log_msg.entry_v1, &entry, NULL, msgBuf, sizeof(msgBuf));
EXPECT_EQ((length == total) ? 0 : -1, processBinaryLogBuffer);
- if (processBinaryLogBuffer == 0) {
+ if ((processBinaryLogBuffer == 0) || entry.message) {
size_t line_overhead = 20;
if (pid > 99999) ++line_overhead;
if (pid > 999999) ++line_overhead;
fflush(stderr);
- EXPECT_EQ((int)((line_overhead * num_lines) + size),
- android_log_printLogLine(logformat, fileno(stderr), &entry));
+ if (processBinaryLogBuffer) {
+ EXPECT_GT((int)((line_overhead * num_lines) + size),
+ android_log_printLogLine(logformat,
+ fileno(stderr), &entry));
+ } else {
+ EXPECT_EQ((int)((line_overhead * num_lines) + size),
+ android_log_printLogLine(logformat,
+ fileno(stderr), &entry));
+ }
}
android_log_format_free(logformat);
}
}
- EXPECT_EQ(1, count);
+ EXPECT_EQ(SUPPORTS_END_TO_END, count);
android_logger_list_close(logger_list);
#else
@@ -527,7 +593,7 @@
android_log_format_free(logformat);
}
- EXPECT_EQ(1, count);
+ EXPECT_EQ(SUPPORTS_END_TO_END, count);
android_logger_list_close(logger_list);
#else
@@ -1058,10 +1124,14 @@
android_logger_list_close(logger_list);
+#if SUPPORTS_END_TO_END
EXPECT_EQ(true, matches);
EXPECT_LE(SIZEOF_MAX_PAYLOAD_BUF, static_cast<size_t>(max_len));
#else
+ EXPECT_EQ(false, matches);
+#endif
+#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
@@ -1123,7 +1193,7 @@
android_log_format_free(logformat);
}
- EXPECT_EQ(1, count);
+ EXPECT_EQ(SUPPORTS_END_TO_END, count);
android_logger_list_close(logger_list);
#else
@@ -1184,6 +1254,11 @@
android_logger_list_close(logger_list);
+#if !SUPPORTS_END_TO_END
+ max_len = max_len ?
+ max_len :
+ LOGGER_ENTRY_MAX_PAYLOAD - sizeof(big_payload_tag);
+#endif
EXPECT_LE(LOGGER_ENTRY_MAX_PAYLOAD - sizeof(big_payload_tag),
static_cast<size_t>(max_len));
@@ -1255,14 +1330,14 @@
android_logger_list_close(logger_list1);
android_logger_list_close(logger_list2);
- EXPECT_EQ(num, count1);
- EXPECT_EQ(num - 10, count2);
+ EXPECT_EQ(num * SUPPORTS_END_TO_END, count1);
+ EXPECT_EQ((num - 10) * SUPPORTS_END_TO_END, count2);
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
-#ifndef USING_LOGGER_LOCAL // Do not retest logprint
+#ifdef USING_LOGGER_DEFAULT // Do not retest logprint
static bool checkPriForTag(AndroidLogFormat *p_format, const char *tag, android_LogPriority pri) {
return android_log_shouldPrintLine(p_format, tag, pri)
&& !android_log_shouldPrintLine(p_format, tag, (android_LogPriority)(pri - 1));
@@ -1331,9 +1406,9 @@
android_log_format_free(p_format);
}
-#endif // !USING_LOGGER_LOCAL
+#endif // USING_LOGGER_DEFAULT
-#ifndef USING_LOGGER_LOCAL // Do not retest property handling
+#ifdef USING_LOGGER_DEFAULT // Do not retest property handling
TEST(liblog, is_loggable) {
#ifdef __ANDROID__
static const char tag[] = "is_loggable";
@@ -1632,12 +1707,12 @@
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
-#endif // !USING_LOGGER_LOCAL
+#endif // USING_LOGGER_DEFAULT
// Following tests the specific issues surrounding error handling wrt logd.
// Kills logd and toss all collected data, equivalent to logcat -b all -c,
// except we also return errors to the logging callers.
-#ifndef USING_LOGGER_LOCAL
+#ifdef USING_LOGGER_DEFAULT
#ifdef TEST_PREFIX
// helper to liblog.enoent to count end-to-end matching logging messages.
static int count_matching_ts(log_time ts) {
@@ -1687,7 +1762,7 @@
TEST_PREFIX
log_time ts(CLOCK_MONOTONIC);
EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
- EXPECT_EQ(1, count_matching_ts(ts));
+ EXPECT_EQ(SUPPORTS_END_TO_END, count_matching_ts(ts));
// This call will fail if we are setuid(AID_SYSTEM), beware of any
// test prior to this one playing with setuid and causing interference.
@@ -1732,18 +1807,18 @@
ts = log_time(CLOCK_MONOTONIC);
EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
- EXPECT_EQ(1, count_matching_ts(ts));
+ EXPECT_EQ(SUPPORTS_END_TO_END, count_matching_ts(ts));
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
-#endif // !USING_LOCAL_LOGGER
+#endif // USING_LOCAL_LOGD
// Below this point we run risks of setuid(AID_SYSTEM) which may affect others.
// Do not retest properties, and cannot log into LOG_ID_SECURITY
-#ifndef USING_LOGGER_LOCAL
+#ifdef USING_LOGGER_DEFAULT
TEST(liblog, __security) {
#ifdef __ANDROID__
static const char persist_key[] = "persist.logd.security";
@@ -1929,7 +2004,7 @@
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
-#endif // !USING_LOGGER_LOCAL
+#endif // USING_LOGGER_DEFAULT
#ifdef TEST_PREFIX
static void android_errorWriteWithInfoLog_helper(int TAG, const char* SUBTAG,
@@ -2047,7 +2122,7 @@
max_payload_buf,
200,
count);
- EXPECT_EQ(1, count);
+ EXPECT_EQ(SUPPORTS_END_TO_END, count);
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
@@ -2063,7 +2138,7 @@
max_payload_buf,
sizeof(max_payload_buf),
count);
- EXPECT_EQ(1, count);
+ EXPECT_EQ(SUPPORTS_END_TO_END, count);
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
@@ -2095,7 +2170,7 @@
max_payload_buf,
200,
count);
- EXPECT_EQ(1, count);
+ EXPECT_EQ(SUPPORTS_END_TO_END, count);
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
@@ -2118,6 +2193,46 @@
count = 0;
+ // Do a Before and After on the count to measure the effect. Decrement
+ // what we find in Before to set the stage.
+ ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
+ LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
+
+ for (;;) {
+ log_msg log_msg;
+ if (android_logger_list_read(logger_list, &log_msg) <= 0) break;
+
+ char *eventData = log_msg.msg();
+ if (!eventData) continue;
+
+ // Tag
+ int tag = get4LE(eventData);
+ eventData += 4;
+
+ if (tag != TAG) continue;
+
+ if (!SUBTAG) {
+ // This tag should not have been written because the data was null
+ --count;
+ break;
+ }
+
+ // List type
+ eventData++;
+ // Number of elements in list
+ eventData++;
+ // Element #1: string type for subtag
+ eventData++;
+
+ eventData +=4;
+
+ if (memcmp(SUBTAG, eventData, strlen(SUBTAG))) continue;
+ --count;
+ }
+
+ android_logger_list_close(logger_list);
+
+ // Do an After on the count to measure the effect.
ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
@@ -2184,7 +2299,7 @@
#ifdef TEST_PREFIX
int count;
android_errorWriteLog_helper(123456785, "test-subtag", count);
- EXPECT_EQ(1, count);
+ EXPECT_EQ(SUPPORTS_END_TO_END, count);
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
@@ -2703,7 +2818,7 @@
EXPECT_EQ(0, strcmp(expected_string, msgBuf));
}
- EXPECT_EQ(1, count);
+ EXPECT_EQ(SUPPORTS_END_TO_END, count);
android_logger_list_close(logger_list);
}
@@ -2789,7 +2904,7 @@
#endif
}
-#ifndef USING_LOGGER_LOCAL // Do not retest logger list handling
+#ifdef USING_LOGGER_DEFAULT // Do not retest logger list handling
TEST(liblog, create_android_logger_overflow) {
android_log_context ctx;
@@ -2829,9 +2944,9 @@
msgBuf, sizeof(msgBuf)), 0);
EXPECT_STREQ(msgBuf, "[1005,tag_def,(tag|1),(name|3),(format|3)]");
}
-#endif // !USING_LOGGER_LOCAL
+#endif // USING_LOGGER_DEFAULT
-#ifndef USING_LOGGER_LOCAL // Do not retest pmsg functionality
+#ifdef USING_LOGGER_DEFAULT // Do not retest pmsg functionality
#ifdef __ANDROID__
static const char __pmsg_file[] =
"/data/william-shakespeare/MuchAdoAboutNothing.txt";
@@ -2957,9 +3072,9 @@
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
-#endif // !USING_LOGGER_LOCAL
+#endif // USING_LOGGER_DEFAULT
-#ifndef USING_LOGGER_LOCAL // Do not retest event mapping functionality
+#ifdef USING_LOGGER_DEFAULT // Do not retest event mapping functionality
#ifdef __ANDROID__
// must be: '<needle:> 0 kB'
static bool isZero(const std::string &content, std::string::size_type pos,
@@ -3063,9 +3178,9 @@
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
-#endif // !USING_LOGGER_LOCAL
+#endif // USING_LOGGER_DEFAULT
-#ifndef USING_LOGGER_LOCAL // Do not retest ratelimit
+#ifdef USING_LOGGER_DEFAULT // Do not retest ratelimit
TEST(liblog, __android_log_ratelimit) {
time_t state = 0;
@@ -3097,9 +3212,9 @@
}
// Do not test default seconds, to allow liblog to tune freely
}
-#endif // !USING_LOGGER_LOCAL
+#endif // USING_LOGGER_DEFAULT
-#ifndef USING_LOGGER_LOCAL // Do not retest event mapping functionality
+#ifdef USING_LOGGER_DEFAULT // Do not retest event mapping functionality
TEST(liblog, android_lookupEventTagNum) {
#ifdef __ANDROID__
EventTagMap* map = android_openEventTagMap(NULL);
@@ -3115,4 +3230,4 @@
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
-#endif // !USING_LOGGER_LOCAL
+#endif // USING_LOGGER_DEFAULT
diff --git a/liblog/tests/liblog_test_stderr.cpp b/liblog/tests/liblog_test_stderr.cpp
new file mode 100644
index 0000000..f0cb192
--- /dev/null
+++ b/liblog/tests/liblog_test_stderr.cpp
@@ -0,0 +1,5 @@
+#include <log/log_frontend.h>
+#define liblog liblog_stderr
+#define TEST_PREFIX android_set_log_frontend(LOGGER_STDERR);
+#define USING_LOGGER_STDERR
+#include "liblog_test.cpp"
diff --git a/liblog/tests/liblog_test_stderr_local.cpp b/liblog/tests/liblog_test_stderr_local.cpp
new file mode 100644
index 0000000..1555b4e
--- /dev/null
+++ b/liblog/tests/liblog_test_stderr_local.cpp
@@ -0,0 +1,4 @@
+#include <log/log_frontend.h>
+#define liblog liblog_stderr_local
+#define TEST_PREFIX android_set_log_frontend(LOGGER_LOCAL | LOGGER_STDERR);
+#include "liblog_test.cpp"
diff --git a/libsuspend/autosuspend_wakeup_count.c b/libsuspend/autosuspend_wakeup_count.c
index 2da204a..4dedf7f 100644
--- a/libsuspend/autosuspend_wakeup_count.c
+++ b/libsuspend/autosuspend_wakeup_count.c
@@ -24,7 +24,6 @@
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
-#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
@@ -36,24 +35,12 @@
#define SYS_POWER_STATE "/sys/power/state"
#define SYS_POWER_WAKEUP_COUNT "/sys/power/wakeup_count"
-#define BASE_SLEEP_TIME 100000
-
static int state_fd;
static int wakeup_count_fd;
static pthread_t suspend_thread;
static sem_t suspend_lockout;
static const char *sleep_state = "mem";
static void (*wakeup_func)(bool success) = NULL;
-static int sleep_time = BASE_SLEEP_TIME;
-
-static void update_sleep_time(bool success) {
- if (success) {
- sleep_time = BASE_SLEEP_TIME;
- return;
- }
- // double sleep time after each failure up to one minute
- sleep_time = MIN(sleep_time * 2, 60000000);
-}
static void *suspend_thread_func(void *arg __attribute__((unused)))
{
@@ -61,12 +48,10 @@
char wakeup_count[20];
int wakeup_count_len;
int ret;
- bool success = true;
+ bool success;
while (1) {
- update_sleep_time(success);
- usleep(sleep_time);
- success = false;
+ usleep(100000);
ALOGV("%s: read wakeup_count\n", __func__);
lseek(wakeup_count_fd, 0, SEEK_SET);
wakeup_count_len = TEMP_FAILURE_RETRY(read(wakeup_count_fd, wakeup_count,
@@ -90,6 +75,7 @@
continue;
}
+ success = true;
ALOGV("%s: write %*s to wakeup_count\n", __func__, wakeup_count_len, wakeup_count);
ret = TEMP_FAILURE_RETRY(write(wakeup_count_fd, wakeup_count, wakeup_count_len));
if (ret < 0) {
@@ -98,8 +84,8 @@
} else {
ALOGV("%s: write %s to %s\n", __func__, sleep_state, SYS_POWER_STATE);
ret = TEMP_FAILURE_RETRY(write(state_fd, sleep_state, strlen(sleep_state)));
- if (ret >= 0) {
- success = true;
+ if (ret < 0) {
+ success = false;
}
void (*func)(bool success) = wakeup_func;
if (func != NULL) {
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 3cd36f9..4da5030 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -56,6 +56,25 @@
#define DEFAULT_MAX_ROTATED_LOGS 4
+struct log_device_t {
+ const char* device;
+ bool binary;
+ struct logger* logger;
+ struct logger_list* logger_list;
+ bool printed;
+
+ log_device_t* next;
+
+ log_device_t(const char* d, bool b) {
+ device = d;
+ binary = b;
+ next = nullptr;
+ printed = false;
+ logger = nullptr;
+ logger_list = nullptr;
+ }
+};
+
struct android_logcat_context_internal {
// status
volatile std::atomic_int retval; // valid if thread_stopped set
@@ -91,15 +110,15 @@
int printBinary;
int devCount; // >1 means multiple
pcrecpp::RE* regex;
+ log_device_t* devices;
+ EventTagMap* eventTagMap;
// 0 means "infinite"
size_t maxCount;
size_t printCount;
+
bool printItAnyways;
bool debug;
-
- // static variables
bool hasOpenedEventTagMap;
- EventTagMap* eventTagMap;
};
// Creates a context associated with this logcat instance
@@ -127,25 +146,6 @@
// logd prefixes records with a length field
#define RECORD_LENGTH_FIELD_SIZE_BYTES sizeof(uint32_t)
-struct log_device_t {
- const char* device;
- bool binary;
- struct logger* logger;
- struct logger_list* logger_list;
- bool printed;
-
- log_device_t* next;
-
- log_device_t(const char* d, bool b) {
- device = d;
- binary = b;
- next = nullptr;
- printed = false;
- logger = nullptr;
- logger_list = nullptr;
- }
-};
-
namespace android {
enum helpType { HELP_FALSE, HELP_TRUE, HELP_FORMAT };
@@ -738,7 +738,6 @@
const char* setId = nullptr;
int mode = ANDROID_LOG_RDONLY;
std::string forceFilters;
- log_device_t* devices = nullptr;
log_device_t* dev;
struct logger_list* logger_list;
size_t tail_lines = 0;
@@ -1117,7 +1116,7 @@
if (!(idMask & (1 << i))) continue;
bool found = false;
- for (dev = devices; dev; dev = dev->next) {
+ for (dev = context->devices; dev; dev = dev->next) {
if (!strcmp(name, dev->device)) {
found = true;
break;
@@ -1134,7 +1133,7 @@
dev->next = d;
dev = d;
} else {
- devices = dev = d;
+ context->devices = dev = d;
}
context->devCount++;
}
@@ -1287,8 +1286,8 @@
context->printItAnyways = false;
}
- if (!devices) {
- dev = devices = new log_device_t("main", false);
+ if (!context->devices) {
+ dev = context->devices = new log_device_t("main", false);
context->devCount = 1;
if (android_name_to_log_id("system") == LOG_ID_SYSTEM) {
dev = dev->next = new log_device_t("system", false);
@@ -1384,7 +1383,7 @@
}
}
- dev = devices;
+ dev = context->devices;
if (tail_time != log_time::EPOCH) {
logger_list = android_logger_list_alloc_time(mode, tail_time, pid);
} else {
@@ -1595,7 +1594,7 @@
}
log_device_t* d;
- for (d = devices; d; d = d->next) {
+ for (d = context->devices; d; d = d->next) {
if (android_name_to_log_id(d->device) == log_msg.id()) break;
}
if (!d) {
@@ -1617,6 +1616,11 @@
}
close:
+ // Short and sweet. Implemented generic version in android_logcat_destroy.
+ while (!!(dev = context->devices)) {
+ context->devices = dev->next;
+ delete dev;
+ }
android_logger_list_free(logger_list);
exit:
@@ -1790,6 +1794,20 @@
android_closeEventTagMap(context->eventTagMap);
+ // generic cleanup of devices list to handle all possible dirty cases
+ log_device_t* dev;
+ while (!!(dev = context->devices)) {
+ struct logger_list* logger_list = dev->logger_list;
+ if (logger_list) {
+ for (log_device_t* d = dev; d; d = d->next) {
+ if (d->logger_list == logger_list) d->logger_list = nullptr;
+ }
+ android_logger_list_free(logger_list);
+ }
+ context->devices = dev->next;
+ delete dev;
+ }
+
int retval = context->retval;
free(context);
diff --git a/qemu_pipe/Android.mk b/qemu_pipe/Android.mk
deleted file mode 100644
index 6e0144c..0000000
--- a/qemu_pipe/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright 2011 The Android Open Source Project
-
-LOCAL_PATH:= $(call my-dir)
-
-common_static_libraries := \
- libbase
-include $(CLEAR_VARS)
-LOCAL_CLANG := true
-LOCAL_SANITIZE := integer
-LOCAL_SRC_FILES:= \
- qemu_pipe.cpp
-LOCAL_C_INCLUDES := \
- $(LOCAL_PATH)/include \
- system/base/include
-LOCAL_MODULE:= libqemu_pipe
-LOCAL_STATIC_LIBRARIES := $(common_static_libraries)
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_CFLAGS := -Werror
-include $(BUILD_STATIC_LIBRARY)
diff --git a/qemu_pipe/include/qemu_pipe.h b/qemu_pipe/include/qemu_pipe.h
deleted file mode 100644
index 0987498..0000000
--- a/qemu_pipe/include/qemu_pipe.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-#ifndef ANDROID_CORE_INCLUDE_QEMU_PIPE_H
-#define ANDROID_CORE_INCLUDE_QEMU_PIPE_H
-
-#include <stddef.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-// Try to open a new Qemu fast-pipe. This function returns a file descriptor
-// that can be used to communicate with a named service managed by the
-// emulator.
-//
-// This file descriptor can be used as a standard pipe/socket descriptor.
-//
-// 'pipeName' is the name of the emulator service you want to connect to,
-// and should begin with 'pipe:' (e.g. 'pipe:camera' or 'pipe:opengles').
-// For backward compatibility, the 'pipe:' prefix can be omitted, and in
-// that case, qemu_pipe_open will add it for you.
-
-// On success, return a valid file descriptor, or -1/errno on failure. E.g.:
-//
-// EINVAL -> unknown/unsupported pipeName
-// ENOSYS -> fast pipes not available in this system.
-//
-// ENOSYS should never happen, except if you're trying to run within a
-// misconfigured emulator.
-//
-// You should be able to open several pipes to the same pipe service,
-// except for a few special cases (e.g. GSM modem), where EBUSY will be
-// returned if more than one client tries to connect to it.
-int qemu_pipe_open(const char* pipeName);
-
-// Send a framed message |buff| of |len| bytes through the |fd| descriptor.
-// This really adds a 4-hexchar prefix describing the payload size.
-// Returns 0 on success, and -1 on error.
-int qemu_pipe_frame_send(int fd, const void* buff, size_t len);
-
-// Read a frame message from |fd|, and store it into |buff| of |len| bytes.
-// If the framed message is larger than |len|, then this returns -1 and the
-// content is lost. Otherwise, this returns the size of the message. NOTE:
-// empty messages are possible in a framed wire protocol and do not mean
-// end-of-stream.
-int qemu_pipe_frame_recv(int fd, void* buff, size_t len);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* ANDROID_CORE_INCLUDE_QEMU_PIPE_H */
diff --git a/qemu_pipe/qemu_pipe.cpp b/qemu_pipe/qemu_pipe.cpp
deleted file mode 100644
index beeccb0..0000000
--- a/qemu_pipe/qemu_pipe.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2011 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 "qemu_pipe.h"
-
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <errno.h>
-#include <stdio.h>
-
-#include <android-base/file.h>
-
-using android::base::ReadFully;
-using android::base::WriteFully;
-
-// Define QEMU_PIPE_DEBUG if you want to print error messages when an error
-// occurs during pipe operations. The macro should simply take a printf-style
-// formatting string followed by optional arguments.
-#ifndef QEMU_PIPE_DEBUG
-# define QEMU_PIPE_DEBUG(...) (void)0
-#endif
-
-int qemu_pipe_open(const char* pipeName) {
- // Sanity check.
- if (!pipeName) {
- errno = EINVAL;
- return -1;
- }
-
- int fd = TEMP_FAILURE_RETRY(open("/dev/qemu_pipe", O_RDWR));
- if (fd < 0) {
- QEMU_PIPE_DEBUG("%s: Could not open /dev/qemu_pipe: %s", __FUNCTION__,
- strerror(errno));
- return -1;
- }
-
- // Write the pipe name, *including* the trailing zero which is necessary.
- size_t pipeNameLen = strlen(pipeName);
- if (WriteFully(fd, pipeName, pipeNameLen + 1U)) {
- return fd;
- }
-
- // now, add 'pipe:' prefix and try again
- // Note: host side will wait for the trailing '\0' to start
- // service lookup.
- const char pipe_prefix[] = "pipe:";
- if (WriteFully(fd, pipe_prefix, strlen(pipe_prefix)) &&
- WriteFully(fd, pipeName, pipeNameLen + 1U)) {
- return fd;
- }
- QEMU_PIPE_DEBUG("%s: Could not write to %s pipe service: %s",
- __FUNCTION__, pipeName, strerror(errno));
- close(fd);
- return -1;
-}
-
-int qemu_pipe_frame_send(int fd, const void* buff, size_t len) {
- char header[5];
- snprintf(header, sizeof(header), "%04zx", len);
- if (!WriteFully(fd, header, 4)) {
- QEMU_PIPE_DEBUG("Can't write qemud frame header: %s", strerror(errno));
- return -1;
- }
- if (!WriteFully(fd, buff, len)) {
- QEMU_PIPE_DEBUG("Can't write qemud frame payload: %s", strerror(errno));
- return -1;
- }
- return 0;
-}
-
-int qemu_pipe_frame_recv(int fd, void* buff, size_t len) {
- char header[5];
- if (!ReadFully(fd, header, 4)) {
- QEMU_PIPE_DEBUG("Can't read qemud frame header: %s", strerror(errno));
- return -1;
- }
- header[4] = '\0';
- size_t size;
- if (sscanf(header, "%04zx", &size) != 1) {
- QEMU_PIPE_DEBUG("Malformed qemud frame header: [%.*s]", 4, header);
- return -1;
- }
- if (size > len) {
- QEMU_PIPE_DEBUG("Oversized qemud frame (% bytes, expected <= %)", size,
- len);
- return -1;
- }
- if (!ReadFully(fd, buff, size)) {
- QEMU_PIPE_DEBUG("Could not read qemud frame payload: %s",
- strerror(errno));
- return -1;
- }
- return size;
-}
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 757e1ff..4a91189 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -290,6 +290,9 @@
# /data, which in turn can only be loaded when system properties are present.
trigger post-fs-data
+ # Now we can start zygote for devices with file based encryption
+ trigger zygote-start
+
# Load persist properties and override properties (if enabled) from /data.
trigger load_persist_props_action
@@ -490,6 +493,13 @@
# Set indication (checked by vold) that we have finished this action
#setprop vold.post_fs_data_done 1
+# This trigger will be triggered before 'zygote-start' since there is no zygote-start defined in
+# current init.rc. It is recommended to put unnecessary data/ initialization from post-fs-data
+# to start-zygote to unblock zygote start.
+on zygote-start && property:ro.crypto.state=encrypted && property:ro.crypto.type=file
+ start netd
+ start zygote
+
on boot
# basic network init
ifup lo
@@ -564,7 +574,6 @@
chown system system /sys/class/leds/red/device/grpfreq
chown system system /sys/class/leds/red/device/grppwm
chown system system /sys/class/leds/red/device/blink
- chown system system /sys/class/timed_output/vibrator/enable
chown system system /sys/module/sco/parameters/disable_esco
chown system system /sys/kernel/ipv4/tcp_wmem_min
chown system system /sys/kernel/ipv4/tcp_wmem_def