Merge changes I8d0c60e5,Ib8ad0ad6
* changes:
adb: boolify check_header and check_data.
adb: redirect stdout/stderr before initializing usb.
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index f49c69d..68ae4af 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -126,8 +126,9 @@
" reverse --remove-all remove all reverse socket connections from device\n"
"\n"
"file transfer:\n"
- " push LOCAL... REMOTE\n"
+ " push [--sync] LOCAL... REMOTE\n"
" copy local files/directories to device\n"
+ " --sync: only push files that are newer on the host than the device\n"
" pull [-a] REMOTE... LOCAL\n"
" copy files/dirs from device\n"
" -a: preserve file timestamp and mode\n"
@@ -1233,9 +1234,8 @@
return 0;
}
-static void parse_push_pull_args(const char** arg, int narg,
- std::vector<const char*>* srcs,
- const char** dst, bool* copy_attrs) {
+static void parse_push_pull_args(const char** arg, int narg, std::vector<const char*>* srcs,
+ const char** dst, bool* copy_attrs, bool* sync) {
*copy_attrs = false;
srcs->clear();
@@ -1248,6 +1248,10 @@
// Silently ignore for backwards compatibility.
} else if (!strcmp(*arg, "-a")) {
*copy_attrs = true;
+ } else if (!strcmp(*arg, "--sync")) {
+ if (sync != nullptr) {
+ *sync = true;
+ }
} else if (!strcmp(*arg, "--")) {
ignore_flags = true;
} else {
@@ -1654,19 +1658,20 @@
}
else if (!strcmp(argv[0], "push")) {
bool copy_attrs = false;
+ bool sync = false;
std::vector<const char*> srcs;
const char* dst = nullptr;
- parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, ©_attrs);
+ parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, ©_attrs, &sync);
if (srcs.empty() || !dst) return syntax_error("push requires an argument");
- return do_sync_push(srcs, dst) ? 0 : 1;
+ return do_sync_push(srcs, dst, sync) ? 0 : 1;
}
else if (!strcmp(argv[0], "pull")) {
bool copy_attrs = false;
std::vector<const char*> srcs;
const char* dst = ".";
- parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, ©_attrs);
+ parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, ©_attrs, nullptr);
if (srcs.empty()) return syntax_error("pull requires an argument");
return do_sync_pull(srcs, dst, copy_attrs) ? 0 : 1;
}
@@ -2086,7 +2091,7 @@
std::vector<const char*> apk_file = {argv[last_apk]};
std::string apk_dest = android::base::StringPrintf(
where, android::base::Basename(argv[last_apk]).c_str());
- if (!do_sync_push(apk_file, apk_dest.c_str())) goto cleanup_apk;
+ if (!do_sync_push(apk_file, apk_dest.c_str(), false)) goto cleanup_apk;
argv[last_apk] = apk_dest.c_str(); /* destination name, not source location */
result = pm_command(transport, serial, argc, argv);
diff --git a/adb/file_sync_client.cpp b/adb/file_sync_client.cpp
index 22bd2f2..2576fb1 100644
--- a/adb/file_sync_client.cpp
+++ b/adb/file_sync_client.cpp
@@ -674,11 +674,22 @@
return true;
}
-static bool sync_send(SyncConnection& sc, const char* lpath, const char* rpath,
- unsigned mtime, mode_t mode)
-{
+static bool sync_send(SyncConnection& sc, const char* lpath, const char* rpath, unsigned mtime,
+ mode_t mode, bool sync) {
std::string path_and_mode = android::base::StringPrintf("%s,%d", rpath, mode);
+ if (sync) {
+ struct stat st;
+ if (sync_lstat(sc, rpath, &st)) {
+ // For links, we cannot update the atime/mtime.
+ if ((S_ISREG(mode & st.st_mode) && st.st_mtime == static_cast<time_t>(mtime)) ||
+ (S_ISLNK(mode & st.st_mode) && st.st_mtime >= static_cast<time_t>(mtime))) {
+ sc.RecordFilesSkipped(1);
+ return true;
+ }
+ }
+ }
+
if (S_ISLNK(mode)) {
#if !defined(_WIN32)
char buf[PATH_MAX];
@@ -902,7 +913,7 @@
if (list_only) {
sc.Println("would push: %s -> %s", ci.lpath.c_str(), ci.rpath.c_str());
} else {
- if (!sync_send(sc, ci.lpath.c_str(), ci.rpath.c_str(), ci.time, ci.mode)) {
+ if (!sync_send(sc, ci.lpath.c_str(), ci.rpath.c_str(), ci.time, ci.mode, false)) {
return false;
}
}
@@ -916,7 +927,7 @@
return true;
}
-bool do_sync_push(const std::vector<const char*>& srcs, const char* dst) {
+bool do_sync_push(const std::vector<const char*>& srcs, const char* dst, bool sync) {
SyncConnection sc;
if (!sc.IsValid()) return false;
@@ -981,7 +992,7 @@
dst_dir.append(android::base::Basename(src_path));
}
- success &= copy_local_dir_remote(sc, src_path, dst_dir.c_str(), false, false);
+ success &= copy_local_dir_remote(sc, src_path, dst_dir.c_str(), sync, false);
continue;
} else if (!should_push_file(st.st_mode)) {
sc.Warning("skipping special file '%s' (mode = 0o%o)", src_path, st.st_mode);
@@ -1002,7 +1013,7 @@
sc.NewTransfer();
sc.SetExpectedTotalBytes(st.st_size);
- success &= sync_send(sc, src_path, dst_path, st.st_mtime, st.st_mode);
+ success &= sync_send(sc, src_path, dst_path, st.st_mtime, st.st_mode, sync);
sc.ReportTransferRate(src_path, TransferDirection::push);
}
diff --git a/adb/file_sync_service.h b/adb/file_sync_service.h
index 90f1965..6606efd 100644
--- a/adb/file_sync_service.h
+++ b/adb/file_sync_service.h
@@ -81,7 +81,7 @@
void file_sync_service(int fd, void* cookie);
bool do_sync_ls(const char* path);
-bool do_sync_push(const std::vector<const char*>& srcs, const char* dst);
+bool do_sync_push(const std::vector<const char*>& srcs, const char* dst, bool sync);
bool do_sync_pull(const std::vector<const char*>& srcs, const char* dst,
bool copy_attrs, const char* name=nullptr);
diff --git a/adb/set_verity_enable_state_service.cpp b/adb/set_verity_enable_state_service.cpp
index b2b1c18..253d14a 100644
--- a/adb/set_verity_enable_state_service.cpp
+++ b/adb/set_verity_enable_state_service.cpp
@@ -139,25 +139,36 @@
bool any_changed = false;
bool enable = (cookie != NULL);
- if (!kAllowDisableVerity) {
- WriteFdFmt(fd, "%s-verity only works for userdebug builds\n",
- enable ? "enable" : "disable");
+
+ // Figure out if we're using VB1.0 or VB2.0 (aka AVB) - by
+ // contract, androidboot.vbmeta.digest is set by the bootloader
+ // when using AVB).
+ bool using_avb = !android::base::GetProperty("ro.boot.vbmeta.digest", "").empty();
+
+ // If using AVB, dm-verity is used on any build so we want it to
+ // be possible to disable/enable on any build (except USER). For
+ // VB1.0 dm-verity is only enabled on certain builds.
+ if (!using_avb) {
+ if (!kAllowDisableVerity) {
+ WriteFdFmt(fd, "%s-verity only works for userdebug builds\n",
+ enable ? "enable" : "disable");
+ }
+
+ if (!android::base::GetBoolProperty("ro.secure", false)) {
+ WriteFdFmt(fd, "verity not enabled - ENG build\n");
+ return;
+ }
}
- if (!android::base::GetBoolProperty("ro.secure", false)) {
- WriteFdFmt(fd, "verity not enabled - ENG build\n");
- return;
- }
+ // Should never be possible to disable dm-verity on a USER build
+ // regardless of using AVB or VB1.0.
if (!__android_log_is_debuggable()) {
WriteFdFmt(fd, "verity cannot be disabled/enabled - USER build\n");
return;
}
- // Figure out if we're using VB1.0 or VB2.0 (aka AVB).
- std::string vbmeta_hash = android::base::GetProperty("ro.boot.vbmeta.digest", "");
- if (vbmeta_hash != "") {
- // Yep, the system is using AVB (by contract, androidboot.vbmeta.hash is
- // set by the bootloader when using AVB).
+ if (using_avb) {
+ // Yep, the system is using AVB.
AvbOps* ops = avb_ops_user_new();
if (ops == nullptr) {
WriteFdFmt(fd, "Error getting AVB ops\n");
diff --git a/adb/test_device.py b/adb/test_device.py
index e44cc83..737d0c2 100644
--- a/adb/test_device.py
+++ b/adb/test_device.py
@@ -1130,8 +1130,18 @@
if host_dir is not None:
shutil.rmtree(host_dir)
+ def verify_sync(self, device, temp_files, device_dir):
+ """Verifies that a list of temp files was synced to the device."""
+ # Confirm that every file on the device mirrors that on the host.
+ for temp_file in temp_files:
+ device_full_path = posixpath.join(
+ device_dir, temp_file.base_name)
+ dev_md5, _ = device.shell(
+ [get_md5_prog(self.device), device_full_path])[0].split()
+ self.assertEqual(temp_file.checksum, dev_md5)
+
def test_sync(self):
- """Sync a randomly generated directory of files to specified device."""
+ """Sync a host directory to the data partition."""
try:
base_dir = tempfile.mkdtemp()
@@ -1141,27 +1151,50 @@
os.makedirs(full_dir_path)
# Create 32 random files within the host mirror.
- temp_files = make_random_host_files(in_dir=full_dir_path, num_files=32)
+ temp_files = make_random_host_files(
+ in_dir=full_dir_path, num_files=32)
- # Clean up any trash on the device.
- device = adb.get_device(product=base_dir)
+ # Clean up any stale files on the device.
+ device = adb.get_device() # pylint: disable=no-member
device.shell(['rm', '-rf', self.DEVICE_TEMP_DIR])
+ old_product_out = os.environ.get('ANDROID_PRODUCT_OUT')
+ os.environ['ANDROID_PRODUCT_OUT'] = base_dir
device.sync('data')
+ if old_product_out is None:
+ del os.environ['ANDROID_PRODUCT_OUT']
+ else:
+ os.environ['ANDROID_PRODUCT_OUT'] = old_product_out
- # Confirm that every file on the device mirrors that on the host.
- for temp_file in temp_files:
- device_full_path = posixpath.join(self.DEVICE_TEMP_DIR,
- temp_file.base_name)
- dev_md5, _ = device.shell(
- [get_md5_prog(self.device), device_full_path])[0].split()
- self.assertEqual(temp_file.checksum, dev_md5)
+ self.verify_sync(device, temp_files, self.DEVICE_TEMP_DIR)
- self.device.shell(['rm', '-rf', self.DEVICE_TEMP_DIR])
+ #self.device.shell(['rm', '-rf', self.DEVICE_TEMP_DIR])
finally:
if base_dir is not None:
shutil.rmtree(base_dir)
+ def test_push_sync(self):
+ """Sync a host directory to a specific path."""
+
+ try:
+ temp_dir = tempfile.mkdtemp()
+ temp_files = make_random_host_files(in_dir=temp_dir, num_files=32)
+
+ device_dir = posixpath.join(self.DEVICE_TEMP_DIR, 'sync_src_dst')
+
+ # Clean up any stale files on the device.
+ device = adb.get_device() # pylint: disable=no-member
+ device.shell(['rm', '-rf', device_dir])
+
+ device.push(temp_dir, device_dir, sync=True)
+
+ self.verify_sync(device, temp_files, device_dir)
+
+ self.device.shell(['rm', '-rf', self.DEVICE_TEMP_DIR])
+ finally:
+ if temp_dir is not None:
+ shutil.rmtree(temp_dir)
+
def test_unicode_paths(self):
"""Ensure that we can support non-ASCII paths, even on Windows."""
name = u'로보카 폴리'
diff --git a/base/Android.bp b/base/Android.bp
index 81b96db..b636dc3 100644
--- a/base/Android.bp
+++ b/base/Android.bp
@@ -53,7 +53,6 @@
header_libs: [
"libbase_headers",
- "libutils_headers",
],
export_header_lib_headers: ["libbase_headers"],
diff --git a/base/file.cpp b/base/file.cpp
index 7fbebc5..a2f2887 100644
--- a/base/file.cpp
+++ b/base/file.cpp
@@ -32,13 +32,14 @@
#include "android-base/macros.h" // For TEMP_FAILURE_RETRY on Darwin.
#include "android-base/unique_fd.h"
#include "android-base/utf8.h"
-#include "utils/Compat.h"
#if defined(__APPLE__)
#include <mach-o/dyld.h>
#endif
#if defined(_WIN32)
#include <windows.h>
+#define O_CLOEXEC O_NOINHERIT
+#define O_NOFOLLOW 0
#endif
namespace android {
@@ -133,7 +134,7 @@
bool follow_symlinks) {
int flags = O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_BINARY |
(follow_symlinks ? 0 : O_NOFOLLOW);
- android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), flags, DEFFILEMODE)));
+ android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), flags, 0666)));
if (fd == -1) {
return false;
}
diff --git a/debuggerd/include/debuggerd/protocol.h b/debuggerd/include/debuggerd/protocol.h
index 0756876..144efc8 100644
--- a/debuggerd/include/debuggerd/protocol.h
+++ b/debuggerd/include/debuggerd/protocol.h
@@ -21,6 +21,7 @@
// Sockets in the ANDROID_SOCKET_NAMESPACE_RESERVED namespace.
// Both sockets are SOCK_SEQPACKET sockets, so no explicit length field is needed.
constexpr char kTombstonedCrashSocketName[] = "tombstoned_crash";
+constexpr char kTombstonedJavaTraceSocketName[] = "tombstoned_java_trace";
constexpr char kTombstonedInterceptSocketName[] = "tombstoned_intercept";
enum class CrashPacketType : uint8_t {
diff --git a/debuggerd/include/debuggerd/tombstoned.h b/debuggerd/include/debuggerd/tombstoned.h
index d158d50..908517d 100644
--- a/debuggerd/include/debuggerd/tombstoned.h
+++ b/debuggerd/include/debuggerd/tombstoned.h
@@ -21,6 +21,6 @@
#include <android-base/unique_fd.h>
bool tombstoned_connect(pid_t pid, android::base::unique_fd* tombstoned_socket,
- android::base::unique_fd* output_fd);
+ android::base::unique_fd* output_fd, bool is_native_crash = true);
bool tombstoned_notify_completion(int tombstoned_socket);
diff --git a/debuggerd/tombstoned/tombstoned.cpp b/debuggerd/tombstoned/tombstoned.cpp
index 2248a21..80dbef5 100644
--- a/debuggerd/tombstoned/tombstoned.cpp
+++ b/debuggerd/tombstoned/tombstoned.cpp
@@ -50,86 +50,154 @@
kCrashStatusQueued,
};
+struct Crash;
+
+class CrashType {
+ public:
+ CrashType(const std::string& dir_path, const std::string& file_name_prefix, size_t max_artifacts,
+ size_t max_concurrent_dumps)
+ : file_name_prefix_(file_name_prefix),
+ dir_path_(dir_path),
+ dir_fd_(open(dir_path.c_str(), O_DIRECTORY | O_RDONLY | O_CLOEXEC)),
+ max_artifacts_(max_artifacts),
+ next_artifact_(0),
+ max_concurrent_dumps_(max_concurrent_dumps),
+ num_concurrent_dumps_(0) {
+ if (dir_fd_ == -1) {
+ PLOG(FATAL) << "failed to open directory: " << dir_path;
+ }
+
+ // NOTE: If max_artifacts_ <= max_concurrent_dumps_, then theoretically the
+ // same filename could be handed out to multiple processes.
+ CHECK(max_artifacts_ > max_concurrent_dumps_);
+
+ find_oldest_artifact();
+ }
+
+ unique_fd get_output_fd() {
+ unique_fd result;
+ char buf[PATH_MAX];
+ snprintf(buf, sizeof(buf), "%s%02d", file_name_prefix_.c_str(), next_artifact_);
+ // Unlink and create the file, instead of using O_TRUNC, to avoid two processes
+ // interleaving their output in case we ever get into that situation.
+ if (unlinkat(dir_fd_, buf, 0) != 0 && errno != ENOENT) {
+ PLOG(FATAL) << "failed to unlink tombstone at " << dir_path_ << buf;
+ }
+
+ result.reset(openat(dir_fd_, buf, O_CREAT | O_EXCL | O_WRONLY | O_APPEND | O_CLOEXEC, 0640));
+ if (result == -1) {
+ PLOG(FATAL) << "failed to create tombstone at " << dir_path_ << buf;
+ }
+
+ next_artifact_ = (next_artifact_ + 1) % max_artifacts_;
+ return result;
+ }
+
+ bool maybe_enqueue_crash(Crash* crash) {
+ if (num_concurrent_dumps_ == max_concurrent_dumps_) {
+ queued_requests_.push_back(crash);
+ return true;
+ }
+
+ return false;
+ }
+
+ void maybe_dequeue_crashes(void (*handler)(Crash* crash)) {
+ while (!queued_requests_.empty() && num_concurrent_dumps_ < max_concurrent_dumps_) {
+ Crash* next_crash = queued_requests_.front();
+ queued_requests_.pop_front();
+ handler(next_crash);
+ }
+ }
+
+ void on_crash_started() { ++num_concurrent_dumps_; }
+
+ void on_crash_completed() { --num_concurrent_dumps_; }
+
+ static CrashType* const tombstone;
+ static CrashType* const java_trace;
+
+ private:
+ void find_oldest_artifact() {
+ size_t oldest_tombstone = 0;
+ time_t oldest_time = std::numeric_limits<time_t>::max();
+
+ for (size_t i = 0; i < max_artifacts_; ++i) {
+ std::string path = android::base::StringPrintf("%s/%s%02zu", dir_path_.c_str(),
+ file_name_prefix_.c_str(), i);
+ struct stat st;
+ if (stat(path.c_str(), &st) != 0) {
+ if (errno == ENOENT) {
+ oldest_tombstone = i;
+ break;
+ } else {
+ PLOG(ERROR) << "failed to stat " << path;
+ continue;
+ }
+ }
+
+ if (st.st_mtime < oldest_time) {
+ oldest_tombstone = i;
+ oldest_time = st.st_mtime;
+ }
+ }
+
+ next_artifact_ = oldest_tombstone;
+ }
+
+ const std::string file_name_prefix_;
+
+ const std::string dir_path_;
+ const int dir_fd_;
+
+ const size_t max_artifacts_;
+ int next_artifact_;
+
+ const size_t max_concurrent_dumps_;
+ size_t num_concurrent_dumps_;
+
+ std::deque<Crash*> queued_requests_;
+
+ DISALLOW_COPY_AND_ASSIGN(CrashType);
+};
+
+// Whether java trace dumps are produced via tombstoned.
+static constexpr bool kJavaTraceDumpsEnabled = false;
+
+/* static */ CrashType* const CrashType::tombstone =
+ new CrashType("/data/tombstones", "tombstone_" /* file_name_prefix */, 10 /* max_artifacts */,
+ 1 /* max_concurrent_dumps */);
+
+/* static */ CrashType* const CrashType::java_trace =
+ (kJavaTraceDumpsEnabled ? new CrashType("/data/anr", "anr_" /* file_name_prefix */,
+ 64 /* max_artifacts */, 4 /* max_concurrent_dumps */)
+ : nullptr);
+
// Ownership of Crash is a bit messy.
// It's either owned by an active event that must have a timeout, or owned by
// queued_requests, in the case that multiple crashes come in at the same time.
struct Crash {
- ~Crash() {
- event_free(crash_event);
- }
+ ~Crash() { event_free(crash_event); }
unique_fd crash_fd;
pid_t crash_pid;
event* crash_event = nullptr;
+
+ // Not owned by |Crash|.
+ CrashType* crash_type = nullptr;
};
-static constexpr char kTombstoneDirectory[] = "/data/tombstones/";
-static constexpr size_t kTombstoneCount = 10;
-static int tombstone_directory_fd = -1;
-static int next_tombstone = 0;
-
-static constexpr size_t kMaxConcurrentDumps = 1;
-static size_t num_concurrent_dumps = 0;
-
-static std::deque<Crash*> queued_requests;
-
// Forward declare the callbacks so they can be placed in a sensible order.
static void crash_accept_cb(evconnlistener* listener, evutil_socket_t sockfd, sockaddr*, int, void*);
static void crash_request_cb(evutil_socket_t sockfd, short ev, void* arg);
static void crash_completed_cb(evutil_socket_t sockfd, short ev, void* arg);
-static void find_oldest_tombstone() {
- size_t oldest_tombstone = 0;
- time_t oldest_time = std::numeric_limits<time_t>::max();
-
- for (size_t i = 0; i < kTombstoneCount; ++i) {
- std::string path = android::base::StringPrintf("%stombstone_%02zu", kTombstoneDirectory, i);
- struct stat st;
- if (stat(path.c_str(), &st) != 0) {
- if (errno == ENOENT) {
- oldest_tombstone = i;
- break;
- } else {
- PLOG(ERROR) << "failed to stat " << path;
- continue;
- }
- }
-
- if (st.st_mtime < oldest_time) {
- oldest_tombstone = i;
- oldest_time = st.st_mtime;
- }
- }
-
- next_tombstone = oldest_tombstone;
-}
-
-static unique_fd get_tombstone_fd() {
- // If kMaxConcurrentDumps is greater than 1, then theoretically the same
- // filename could be handed out to multiple processes. Unlink and create the
- // file, instead of using O_TRUNC, to avoid two processes interleaving their
- // output.
- unique_fd result;
- char buf[PATH_MAX];
- snprintf(buf, sizeof(buf), "tombstone_%02d", next_tombstone);
- if (unlinkat(tombstone_directory_fd, buf, 0) != 0 && errno != ENOENT) {
- PLOG(FATAL) << "failed to unlink tombstone at " << kTombstoneDirectory << buf;
- }
-
- result.reset(
- openat(tombstone_directory_fd, buf, O_CREAT | O_EXCL | O_WRONLY | O_APPEND | O_CLOEXEC, 0640));
- if (result == -1) {
- PLOG(FATAL) << "failed to create tombstone at " << kTombstoneDirectory << buf;
- }
-
- next_tombstone = (next_tombstone + 1) % kTombstoneCount;
- return result;
-}
-
static void perform_request(Crash* crash) {
unique_fd output_fd;
- if (!intercept_manager->GetIntercept(crash->crash_pid, &output_fd)) {
- output_fd = get_tombstone_fd();
+ // Note that java traces are not interceptible.
+ if ((crash->crash_type == CrashType::java_trace) ||
+ !intercept_manager->GetIntercept(crash->crash_pid, &output_fd)) {
+ output_fd = crash->crash_type->get_output_fd();
}
TombstonedCrashPacket response = {
@@ -152,23 +220,15 @@
event_add(crash->crash_event, &timeout);
}
- ++num_concurrent_dumps;
+ crash->crash_type->on_crash_started();
return;
fail:
delete crash;
}
-static void dequeue_requests() {
- while (!queued_requests.empty() && num_concurrent_dumps < kMaxConcurrentDumps) {
- Crash* next_crash = queued_requests.front();
- queued_requests.pop_front();
- perform_request(next_crash);
- }
-}
-
static void crash_accept_cb(evconnlistener* listener, evutil_socket_t sockfd, sockaddr*, int,
- void*) {
+ void* crash_type) {
event_base* base = evconnlistener_get_base(listener);
Crash* crash = new Crash();
@@ -176,12 +236,15 @@
event* crash_event = event_new(base, sockfd, EV_TIMEOUT | EV_READ, crash_request_cb, crash);
crash->crash_fd.reset(sockfd);
crash->crash_event = crash_event;
+ crash->crash_type = static_cast<CrashType*>(crash_type);
event_add(crash_event, &timeout);
}
static void crash_request_cb(evutil_socket_t sockfd, short ev, void* arg) {
ssize_t rc;
Crash* crash = static_cast<Crash*>(arg);
+ CrashType* type = crash->crash_type;
+
TombstonedCrashPacket request = {};
if ((ev & EV_TIMEOUT) != 0) {
@@ -208,12 +271,27 @@
goto fail;
}
- crash->crash_pid = request.packet.dump_request.pid;
+ if (type == CrashType::tombstone) {
+ crash->crash_pid = request.packet.dump_request.pid;
+ } else {
+ // Requests for java traces are sent from untrusted processes, so we
+ // must not trust the PID sent down with the request. Instead, we ask the
+ // kernel.
+ ucred cr = {};
+ socklen_t len = sizeof(cr);
+ int ret = getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &cr, &len);
+ if (ret != 0) {
+ PLOG(ERROR) << "Failed to getsockopt(..SO_PEERCRED)";
+ goto fail;
+ }
+
+ crash->crash_pid = cr.pid;
+ }
+
LOG(INFO) << "received crash request for pid " << crash->crash_pid;
- if (num_concurrent_dumps == kMaxConcurrentDumps) {
+ if (type->maybe_enqueue_crash(crash)) {
LOG(INFO) << "enqueueing crash request for pid " << crash->crash_pid;
- queued_requests.push_back(crash);
} else {
perform_request(crash);
}
@@ -229,7 +307,7 @@
Crash* crash = static_cast<Crash*>(arg);
TombstonedCrashPacket request = {};
- --num_concurrent_dumps;
+ crash->crash_type->on_crash_completed();
if ((ev & EV_READ) == 0) {
goto fail;
@@ -252,10 +330,11 @@
}
fail:
+ CrashType* type = crash->crash_type;
delete crash;
// If there's something queued up, let them proceed.
- dequeue_requests();
+ type->maybe_dequeue_crashes(perform_request);
}
int main(int, char* []) {
@@ -269,13 +348,6 @@
};
debuggerd_register_handlers(&action);
- tombstone_directory_fd = open(kTombstoneDirectory, O_DIRECTORY | O_RDONLY | O_CLOEXEC);
- if (tombstone_directory_fd == -1) {
- PLOG(FATAL) << "failed to open tombstone directory";
- }
-
- find_oldest_tombstone();
-
int intercept_socket = android_get_control_socket(kTombstonedInterceptSocketName);
int crash_socket = android_get_control_socket(kTombstonedCrashSocketName);
@@ -293,10 +365,24 @@
intercept_manager = new InterceptManager(base, intercept_socket);
- evconnlistener* listener =
- evconnlistener_new(base, crash_accept_cb, nullptr, -1, LEV_OPT_CLOSE_ON_FREE, crash_socket);
- if (!listener) {
- LOG(FATAL) << "failed to create evconnlistener";
+ evconnlistener* tombstone_listener = evconnlistener_new(
+ base, crash_accept_cb, CrashType::tombstone, -1, LEV_OPT_CLOSE_ON_FREE, crash_socket);
+ if (!tombstone_listener) {
+ LOG(FATAL) << "failed to create evconnlistener for tombstones.";
+ }
+
+ if (kJavaTraceDumpsEnabled) {
+ const int java_trace_socket = android_get_control_socket(kTombstonedJavaTraceSocketName);
+ if (java_trace_socket == -1) {
+ PLOG(FATAL) << "failed to get socket from init";
+ }
+
+ evutil_make_socket_nonblocking(java_trace_socket);
+ evconnlistener* java_trace_listener = evconnlistener_new(
+ base, crash_accept_cb, CrashType::java_trace, -1, LEV_OPT_CLOSE_ON_FREE, java_trace_socket);
+ if (!java_trace_listener) {
+ LOG(FATAL) << "failed to create evconnlistener for java traces.";
+ }
}
LOG(INFO) << "tombstoned successfully initialized";
diff --git a/debuggerd/tombstoned/tombstoned.rc b/debuggerd/tombstoned/tombstoned.rc
index b8345ca..53ef01c 100644
--- a/debuggerd/tombstoned/tombstoned.rc
+++ b/debuggerd/tombstoned/tombstoned.rc
@@ -7,4 +7,5 @@
socket tombstoned_crash seqpacket 0666 system system
socket tombstoned_intercept seqpacket 0666 system system
+ socket tombstoned_java_trace seqpacket 0666 system system
writepid /dev/cpuset/system-background/tasks
diff --git a/debuggerd/tombstoned_client.cpp b/debuggerd/tombstoned_client.cpp
index 4741fa6..e878b6a 100644
--- a/debuggerd/tombstoned_client.cpp
+++ b/debuggerd/tombstoned_client.cpp
@@ -30,9 +30,11 @@
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));
+bool tombstoned_connect(pid_t pid, unique_fd* tombstoned_socket, unique_fd* output_fd,
+ bool is_native_crash) {
+ unique_fd sockfd(socket_local_client(
+ (is_native_crash ? kTombstonedCrashSocketName : kTombstonedJavaTraceSocketName),
+ ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET));
if (sockfd == -1) {
async_safe_format_log(ANDROID_LOG_ERROR, "libc", "failed to connect to tombstoned: %s",
strerror(errno));
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index e1f289a..3e890c7 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -1260,10 +1260,10 @@
fb_queue_command("flashing unlock_bootloader", "unlocking bootloader");
}
-static void do_oem_command(std::vector<std::string>* args) {
+static void do_oem_command(const std::string& cmd, std::vector<std::string>* args) {
if (args->empty()) syntax_error("empty oem command");
- std::string command("oem");
+ std::string command(cmd);
while (!args->empty()) {
command += " " + next_arg(args);
}
@@ -1766,7 +1766,7 @@
std::string filename = next_arg(&args);
fb_queue_upload(filename.c_str());
} else if (command == "oem") {
- do_oem_command(&args);
+ do_oem_command("oem", &args);
} else if (command == "flashing") {
if (args.empty()) {
syntax_error("missing 'flashing' command");
@@ -1776,7 +1776,7 @@
args[0] == "get_unlock_ability" ||
args[0] == "get_unlock_bootloader_nonce" ||
args[0] == "lock_bootloader")) {
- do_oem_command(&args);
+ do_oem_command("flashing", &args);
} else if (args.size() == 2 && args[0] == "unlock_bootloader") {
do_bypass_unlock_command(&args);
} else {
diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp
new file mode 100644
index 0000000..0af6159
--- /dev/null
+++ b/fs_mgr/Android.bp
@@ -0,0 +1,62 @@
+//
+// 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.
+//
+
+cc_defaults {
+ name: "fs_mgr_defaults",
+ sanitize: {
+ misc_undefined: ["integer"],
+ },
+ local_include_dirs: ["include/"],
+ cppflags: ["-Werror"],
+ static_libs: [
+ "liblogwrap",
+ "libfec",
+ "libfec_rs",
+ "libbase",
+ "libcrypto_utils",
+ "libcrypto",
+ "libext4_utils",
+ "libsquashfs_utils",
+ "libselinux",
+ "libavb",
+ ],
+}
+
+cc_library_static {
+ name: "libfs_mgr",
+ defaults: ["fs_mgr_defaults"],
+ export_include_dirs: ["include"],
+ include_dirs: ["system/vold"],
+ srcs: [
+ "fs_mgr.cpp",
+ "fs_mgr_dm_ioctl.cpp",
+ "fs_mgr_format.cpp",
+ "fs_mgr_fstab.cpp",
+ "fs_mgr_slotselect.cpp",
+ "fs_mgr_verity.cpp",
+ "fs_mgr_avb.cpp",
+ "fs_mgr_avb_ops.cpp",
+ "fs_mgr_boot_config.cpp",
+ ],
+ product_variables: {
+ debuggable: {
+ cppflags: ["-DALLOW_ADBD_DISABLE_VERITY=1"],
+ },
+ eng: {
+ cppflags: ["-DALLOW_SKIP_SECURE_CHECK=1"],
+ },
+ },
+}
diff --git a/fs_mgr/Android.mk b/fs_mgr/Android.mk
index 2863a26..f3ca724 100644
--- a/fs_mgr/Android.mk
+++ b/fs_mgr/Android.mk
@@ -17,35 +17,6 @@
include $(CLEAR_VARS)
LOCAL_CLANG := true
LOCAL_SANITIZE := integer
-LOCAL_SRC_FILES:= \
- fs_mgr.cpp \
- fs_mgr_dm_ioctl.cpp \
- fs_mgr_format.cpp \
- fs_mgr_fstab.cpp \
- fs_mgr_slotselect.cpp \
- fs_mgr_verity.cpp \
- fs_mgr_avb.cpp \
- fs_mgr_avb_ops.cpp \
- fs_mgr_boot_config.cpp
-LOCAL_C_INCLUDES := \
- $(LOCAL_PATH)/include \
- system/vold \
- system/extras/ext4_utils
-LOCAL_MODULE:= libfs_mgr
-LOCAL_STATIC_LIBRARIES := $(common_static_libraries)
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_CFLAGS := -Werror
-ifneq (,$(filter userdebug,$(TARGET_BUILD_VARIANT)))
-LOCAL_CFLAGS += -DALLOW_ADBD_DISABLE_VERITY=1
-endif
-ifneq (,$(filter eng,$(TARGET_BUILD_VARIANT)))
-LOCAL_CFLAGS += -DALLOW_SKIP_SECURE_CHECK=1
-endif
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_CLANG := true
-LOCAL_SANITIZE := integer
LOCAL_SRC_FILES:= fs_mgr_main.cpp
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_MODULE:= fs_mgr
diff --git a/fs_mgr/fs_mgr_avb.cpp b/fs_mgr/fs_mgr_avb.cpp
index 2b32201..6618003 100644
--- a/fs_mgr/fs_mgr_avb.cpp
+++ b/fs_mgr/fs_mgr_avb.cpp
@@ -16,15 +16,14 @@
#include "fs_mgr_avb.h"
-#include <errno.h>
#include <fcntl.h>
-#include <inttypes.h>
#include <libgen.h>
-#include <stdio.h>
#include <string.h>
-#include <sys/stat.h>
+#include <sys/ioctl.h>
#include <sys/types.h>
-#include <unistd.h>
+
+#include <sstream>
+#include <string>
#include <vector>
#include <android-base/file.h>
@@ -33,11 +32,7 @@
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
-#include <cutils/properties.h>
#include <libavb/libavb.h>
-#include <openssl/sha.h>
-#include <sys/ioctl.h>
-#include <utils/Compat.h>
#include "fs_mgr.h"
#include "fs_mgr_priv.h"
@@ -45,48 +40,6 @@
#include "fs_mgr_priv_dm_ioctl.h"
#include "fs_mgr_priv_sha.h"
-/* The format of dm-verity construction parameters:
- * <version> <dev> <hash_dev> <data_block_size> <hash_block_size>
- * <num_data_blocks> <hash_start_block> <algorithm> <digest> <salt>
- */
-#define VERITY_TABLE_FORMAT \
- "%u %s %s %u %u " \
- "%" PRIu64 " %" PRIu64 " %s %s %s "
-
-#define VERITY_TABLE_PARAMS(hashtree_desc, blk_device, digest, salt) \
- hashtree_desc.dm_verity_version, blk_device, blk_device, hashtree_desc.data_block_size, \
- hashtree_desc.hash_block_size, \
- hashtree_desc.image_size / hashtree_desc.data_block_size, /* num_data_blocks. */ \
- hashtree_desc.tree_offset / hashtree_desc.hash_block_size, /* hash_start_block. */ \
- (char*)hashtree_desc.hash_algorithm, digest, salt
-
-#define VERITY_TABLE_OPT_RESTART "restart_on_corruption"
-#define VERITY_TABLE_OPT_IGNZERO "ignore_zero_blocks"
-
-/* The default format of dm-verity optional parameters:
- * <#opt_params> ignore_zero_blocks restart_on_corruption
- */
-#define VERITY_TABLE_OPT_DEFAULT_FORMAT "2 %s %s"
-#define VERITY_TABLE_OPT_DEFAULT_PARAMS VERITY_TABLE_OPT_IGNZERO, VERITY_TABLE_OPT_RESTART
-
-/* The FEC (forward error correction) format of dm-verity optional parameters:
- * <#opt_params> use_fec_from_device <fec_dev>
- * fec_roots <num> fec_blocks <num> fec_start <offset>
- * ignore_zero_blocks restart_on_corruption
- */
-#define VERITY_TABLE_OPT_FEC_FORMAT \
- "10 use_fec_from_device %s fec_roots %u fec_blocks %" PRIu64 " fec_start %" PRIu64 " %s %s"
-
-/* Note that fec_blocks is the size that FEC covers, *not* the
- * size of the FEC data. Since we use FEC for everything up until
- * the FEC data, it's the same as the offset (fec_start).
- */
-#define VERITY_TABLE_OPT_FEC_PARAMS(hashtree_desc, blk_device) \
- blk_device, hashtree_desc.fec_num_roots, \
- hashtree_desc.fec_offset / hashtree_desc.data_block_size, /* fec_blocks */ \
- hashtree_desc.fec_offset / hashtree_desc.data_block_size, /* fec_start */ \
- VERITY_TABLE_OPT_IGNZERO, VERITY_TABLE_OPT_RESTART
-
static inline bool nibble_value(const char& c, uint8_t* value) {
FS_MGR_CHECK(value != nullptr);
@@ -280,10 +233,81 @@
return true;
}
-static bool hashtree_load_verity_table(struct dm_ioctl* io, const std::string& dm_device_name,
- int fd, const std::string& blk_device,
- const AvbHashtreeDescriptor& hashtree_desc,
- const std::string& salt, const std::string& root_digest) {
+// Constructs dm-verity arguments for sending DM_TABLE_LOAD ioctl to kernel.
+// See the following link for more details:
+// https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity
+static std::string construct_verity_table(const AvbHashtreeDescriptor& hashtree_desc,
+ const std::string& salt, const std::string& root_digest,
+ const std::string& blk_device) {
+ // Loads androidboot.veritymode from kernel cmdline.
+ std::string verity_mode;
+ if (!fs_mgr_get_boot_config("veritymode", &verity_mode)) {
+ verity_mode = "enforcing"; // Defaults to enforcing when it's absent.
+ }
+
+ // Converts veritymode to the format used in kernel.
+ std::string dm_verity_mode;
+ if (verity_mode == "enforcing") {
+ dm_verity_mode = "restart_on_corruption";
+ } else if (verity_mode == "logging") {
+ dm_verity_mode = "ignore_corruption";
+ } else if (verity_mode != "eio") { // Default dm_verity_mode is eio.
+ LERROR << "Unknown androidboot.veritymode: " << verity_mode;
+ return "";
+ }
+
+ // dm-verity construction parameters:
+ // <version> <dev> <hash_dev>
+ // <data_block_size> <hash_block_size>
+ // <num_data_blocks> <hash_start_block>
+ // <algorithm> <digest> <salt>
+ // [<#opt_params> <opt_params>]
+ std::ostringstream verity_table;
+ verity_table << hashtree_desc.dm_verity_version << " " << blk_device << " " << blk_device << " "
+ << hashtree_desc.data_block_size << " " << hashtree_desc.hash_block_size << " "
+ << hashtree_desc.image_size / hashtree_desc.data_block_size << " "
+ << hashtree_desc.tree_offset / hashtree_desc.hash_block_size << " "
+ << hashtree_desc.hash_algorithm << " " << root_digest << " " << salt;
+
+ // Continued from the above optional parameters:
+ // [<#opt_params> <opt_params>]
+ int optional_argc = 0;
+ std::ostringstream optional_args;
+
+ // dm-verity optional parameters for FEC (forward error correction):
+ // use_fec_from_device <fec_dev>
+ // fec_roots <num>
+ // fec_blocks <num>
+ // fec_start <offset>
+ if (hashtree_desc.fec_size > 0) {
+ // Note that fec_blocks is the size that FEC covers, *NOT* the
+ // size of the FEC data. Since we use FEC for everything up until
+ // the FEC data, it's the same as the offset (fec_start).
+ optional_argc += 8;
+ // clang-format off
+ optional_args << "use_fec_from_device " << blk_device
+ << " fec_roots " << hashtree_desc.fec_num_roots
+ << " fec_blocks " << hashtree_desc.fec_offset / hashtree_desc.data_block_size
+ << " fec_start " << hashtree_desc.fec_offset / hashtree_desc.data_block_size
+ << " ";
+ // clang-format on
+ }
+
+ if (!dm_verity_mode.empty()) {
+ optional_argc += 1;
+ optional_args << dm_verity_mode << " ";
+ }
+
+ // Always use ignore_zero_blocks.
+ optional_argc += 1;
+ optional_args << "ignore_zero_blocks";
+
+ verity_table << " " << optional_argc << " " << optional_args.str();
+ return verity_table.str();
+}
+
+static bool load_verity_table(struct dm_ioctl* io, const std::string& dm_device_name, int fd,
+ uint64_t image_size, const std::string& verity_table) {
fs_mgr_verity_ioctl_init(io, dm_device_name, DM_STATUS_TABLE_FLAG);
// The buffer consists of [dm_ioctl][dm_target_spec][verity_params].
@@ -294,35 +318,25 @@
io->target_count = 1;
dm_target->status = 0;
dm_target->sector_start = 0;
- dm_target->length = hashtree_desc.image_size / 512;
+ dm_target->length = image_size / 512;
strcpy(dm_target->target_type, "verity");
// Builds the verity params.
char* verity_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec);
size_t bufsize = DM_BUF_SIZE - (verity_params - buffer);
- int res = 0;
- if (hashtree_desc.fec_size > 0) {
- res = snprintf(verity_params, bufsize, VERITY_TABLE_FORMAT VERITY_TABLE_OPT_FEC_FORMAT,
- VERITY_TABLE_PARAMS(hashtree_desc, blk_device.c_str(), root_digest.c_str(),
- salt.c_str()),
- VERITY_TABLE_OPT_FEC_PARAMS(hashtree_desc, blk_device.c_str()));
- } else {
- res = snprintf(verity_params, bufsize, VERITY_TABLE_FORMAT VERITY_TABLE_OPT_DEFAULT_FORMAT,
- VERITY_TABLE_PARAMS(hashtree_desc, blk_device.c_str(), root_digest.c_str(),
- salt.c_str()),
- VERITY_TABLE_OPT_DEFAULT_PARAMS);
- }
+ LINFO << "Loading verity table: '" << verity_table << "'";
- if (res < 0 || (size_t)res >= bufsize) {
- LERROR << "Error building verity table; insufficient buffer size?";
+ // Copies verity_table to verity_params (including the terminating null byte).
+ if (verity_table.size() > bufsize - 1) {
+ LERROR << "Verity table size too large: " << verity_table.size()
+ << " (max allowable size: " << bufsize - 1 << ")";
return false;
}
-
- LINFO << "Loading verity table: '" << verity_params << "'";
+ memcpy(verity_params, verity_table.c_str(), verity_table.size() + 1);
// Sets ext target boundary.
- verity_params += strlen(verity_params) + 1;
+ verity_params += verity_table.size() + 1;
verity_params = (char*)(((unsigned long)verity_params + 7) & ~7);
dm_target->next = verity_params - buffer;
@@ -362,9 +376,15 @@
return false;
}
+ std::string verity_table =
+ construct_verity_table(hashtree_desc, salt, root_digest, fstab_entry->blk_device);
+ if (verity_table.empty()) {
+ LERROR << "Failed to construct verity table.";
+ return false;
+ }
+
// Loads the verity mapping table.
- if (!hashtree_load_verity_table(io, mount_point, fd, std::string(fstab_entry->blk_device),
- hashtree_desc, salt, root_digest)) {
+ if (!load_verity_table(io, mount_point, fd, hashtree_desc.image_size, verity_table)) {
LERROR << "Couldn't load verity table!";
return false;
}
diff --git a/init/Android.bp b/init/Android.bp
new file mode 100644
index 0000000..80d5c42
--- /dev/null
+++ b/init/Android.bp
@@ -0,0 +1,164 @@
+//
+// 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.
+//
+
+cc_defaults {
+ name: "init_defaults",
+ cpp_std: "experimental",
+ sanitize: {
+ misc_undefined: ["integer"],
+ },
+ tidy_checks: ["-misc-forwarding-reference-overload"],
+ cppflags: [
+ "-DLOG_UEVENTS=0",
+ "-Wall",
+ "-Wextra",
+ "-Wno-unused-parameter",
+ "-Werror",
+ "-DALLOW_LOCAL_PROP_OVERRIDE=0",
+ "-DALLOW_PERMISSIVE_SELINUX=0",
+ "-DREBOOT_BOOTLOADER_ON_PANIC=0",
+ "-DWORLD_WRITABLE_KMSG=0",
+ "-DDUMP_ON_UMOUNT_FAILURE=0",
+ "-DSHUTDOWN_ZERO_TIMEOUT=0",
+ ],
+ product_variables: {
+ debuggable: {
+ cppflags: [
+ "-UALLOW_LOCAL_PROP_OVERRIDE",
+ "-DALLOW_LOCAL_PROP_OVERRIDE=1",
+ "-UALLOW_PERMISSIVE_SELINUX",
+ "-DALLOW_PERMISSIVE_SELINUX=1",
+ "-UREBOOT_BOOTLOADER_ON_PANIC",
+ "-DREBOOT_BOOTLOADER_ON_PANIC=1",
+ "-UWORLD_WRITABLE_KMSG",
+ "-DWORLD_WRITABLE_KMSG=1",
+ "-UDUMP_ON_UMOUNT_FAILURE",
+ "-DDUMP_ON_UMOUNT_FAILURE=1",
+ ],
+ },
+ eng: {
+ cppflags: [
+ "-USHUTDOWN_ZERO_TIMEOUT",
+ "-DSHUTDOWN_ZERO_TIMEOUT=1",
+ ],
+ },
+ },
+}
+
+cc_library_static {
+ name: "libinit",
+ defaults: ["init_defaults"],
+ srcs: [
+ "action.cpp",
+ "capabilities.cpp",
+ "descriptors.cpp",
+ "devices.cpp",
+ "import_parser.cpp",
+ "init_parser.cpp",
+ "log.cpp",
+ "parser.cpp",
+ "service.cpp",
+ "util.cpp",
+ ],
+ whole_static_libs: ["libcap"],
+ static_libs: [
+ "libbase",
+ "libselinux",
+ "liblog",
+ "libprocessgroup",
+ ],
+}
+
+/*
+This is not yet ready, see the below TODOs for what is missing
+
+cc_binary {
+ // TODO: Missing,
+ //LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)
+ //LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED)
+
+ name: "init",
+ defaults: ["init_defaults"],
+ static_executable: true,
+ srcs: [
+ "bootchart.cpp",
+ "builtins.cpp",
+ "init.cpp",
+ "init_first_stage.cpp",
+ "keychords.cpp",
+ "property_service.cpp",
+ "reboot.cpp",
+ "signal_handler.cpp",
+ "ueventd.cpp",
+ "watchdogd.cpp",
+ ],
+ include_dirs: [
+ "system/core/mkbootimg"
+ ],
+ static_libs: [
+ "libinit",
+ "libbootloader_message",
+ "libfs_mgr",
+ "libfec",
+ "libfec_rs",
+ "libsquashfs_utils",
+ "liblogwrap",
+ "libext4_utils",
+ "libcutils",
+ "libbase",
+ "libc",
+ "libselinux",
+ "liblog",
+ "libcrypto_utils",
+ "libcrypto",
+ "libc++_static",
+ "libdl",
+ "libsparse",
+ "libz",
+ "libprocessgroup",
+ "libavb",
+ "libkeyutils",
+ ],
+ symlinks: [
+ "sbin/ueventd",
+ "sbin/watchdogd",
+ ],
+}
+*/
+
+// Tests
+// ------------------------------------------------------------------------------
+
+cc_test {
+ name: "init_tests",
+ defaults: ["init_defaults"],
+ srcs: [
+ "devices_test.cpp",
+ "init_parser_test.cpp",
+ "init_test.cpp",
+ "property_service_test.cpp",
+ "service_test.cpp",
+ "util_test.cpp",
+ ],
+ shared_libs: [
+ "libbase",
+ "libcutils",
+ "libselinux",
+ ],
+ static_libs: ["libinit"],
+}
+
+subdirs = ["*"]
diff --git a/init/Android.mk b/init/Android.mk
index 0db65cb..489d076 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -39,50 +39,6 @@
# --
-# If building on Linux, then build unit test for the host.
-ifeq ($(HOST_OS),linux)
-include $(CLEAR_VARS)
-LOCAL_CPPFLAGS := $(init_cflags)
-LOCAL_SRC_FILES:= \
- parser/tokenizer.cpp \
-
-LOCAL_MODULE := libinit_parser
-LOCAL_CLANG := true
-include $(BUILD_HOST_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := init_parser_tests
-LOCAL_SRC_FILES := \
- parser/tokenizer_test.cpp \
-
-LOCAL_STATIC_LIBRARIES := libinit_parser
-LOCAL_CLANG := true
-include $(BUILD_HOST_NATIVE_TEST)
-endif
-
-include $(CLEAR_VARS)
-# b/38002385, work around clang-tidy segmentation fault.
-LOCAL_TIDY_CHECKS := -misc-forwarding-reference-overload
-LOCAL_CPPFLAGS := $(init_cflags)
-LOCAL_SRC_FILES:= \
- action.cpp \
- capabilities.cpp \
- descriptors.cpp \
- devices.cpp \
- import_parser.cpp \
- init_parser.cpp \
- log.cpp \
- parser.cpp \
- service.cpp \
- util.cpp \
-
-LOCAL_STATIC_LIBRARIES := libbase libselinux liblog libprocessgroup
-LOCAL_WHOLE_STATIC_LIBRARIES := libcap
-LOCAL_MODULE := libinit
-LOCAL_SANITIZE := integer
-LOCAL_CLANG := true
-include $(BUILD_STATIC_LIBRARY)
-
include $(CLEAR_VARS)
# b/38002385, work around clang-tidy segmentation fault.
LOCAL_TIDY_CHECKS := -misc-forwarding-reference-overload
@@ -139,34 +95,3 @@
LOCAL_SANITIZE := integer
LOCAL_CLANG := true
include $(BUILD_EXECUTABLE)
-
-
-# Unit tests.
-# =========================================================
-include $(CLEAR_VARS)
-# b/38002385, work around clang-tidy segmentation fault.
-LOCAL_TIDY_CHECKS := -misc-forwarding-reference-overload
-LOCAL_MODULE := init_tests
-LOCAL_SRC_FILES := \
- devices_test.cpp \
- init_parser_test.cpp \
- init_test.cpp \
- property_service_test.cpp \
- service_test.cpp \
- util_test.cpp \
-
-LOCAL_SHARED_LIBRARIES += \
- libbase \
- libcutils \
- libselinux \
-
-LOCAL_STATIC_LIBRARIES := libinit
-LOCAL_SANITIZE := integer
-LOCAL_CLANG := true
-LOCAL_CPPFLAGS := -Wall -Wextra -Werror -std=gnu++1z
-include $(BUILD_NATIVE_TEST)
-
-
-# Include targets in subdirs.
-# =========================================================
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/init/devices.cpp b/init/devices.cpp
index d8258cf..e0351a3 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -30,6 +30,7 @@
#include <string.h>
#include <sys/sendfile.h>
#include <sys/socket.h>
+#include <sys/sysmacros.h>
#include <sys/time.h>
#include <sys/un.h>
#include <sys/wait.h>
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 838406d..cdfc698 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -331,7 +331,7 @@
// keep debugging tools until non critical ones are all gone.
const std::set<std::string> kill_after_apps{"tombstoned", "logd", "adbd"};
// watchdogd is a vendor specific component but should be alive to complete shutdown safely.
- const std::set<std::string> to_starts{"watchdogd", "vold"};
+ const std::set<std::string> to_starts{"watchdogd", "vold", "ueventd"};
ServiceManager::GetInstance().ForEachService([&kill_after_apps, &to_starts](Service* s) {
if (kill_after_apps.count(s->name())) {
s->SetShutdownCritical();
diff --git a/init/test_service/Android.bp b/init/test_service/Android.bp
new file mode 100644
index 0000000..9bd6f27
--- /dev/null
+++ b/init/test_service/Android.bp
@@ -0,0 +1,22 @@
+//
+// 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.
+//
+
+cc_binary {
+ name: "test_service",
+ srcs: ["test_service.cpp"],
+ shared_libs: ["libbase"],
+ init_rc: ["test_service.rc"],
+}
diff --git a/init/test_service/Android.mk b/init/test_service/Android.mk
deleted file mode 100644
index 30c9e9d..0000000
--- a/init/test_service/Android.mk
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# 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.
-
-LOCAL_PATH := $(call my-dir)
-
-# Sample service for testing.
-# =========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := test_service
-LOCAL_SRC_FILES := test_service.cpp
-
-LOCAL_SHARED_LIBRARIES += libbase
-
-LOCAL_INIT_RC := test_service.rc
-
-include $(BUILD_EXECUTABLE)
diff --git a/libcutils/ashmem-dev.c b/libcutils/ashmem-dev.c
index 92717c0..b4abb79 100644
--- a/libcutils/ashmem-dev.c
+++ b/libcutils/ashmem-dev.c
@@ -28,6 +28,7 @@
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
+#include <sys/sysmacros.h>
#include <sys/types.h>
#include <unistd.h>
diff --git a/libcutils/fs_config.cpp b/libcutils/fs_config.cpp
index 2b3443f..919b65b 100644
--- a/libcutils/fs_config.cpp
+++ b/libcutils/fs_config.cpp
@@ -139,14 +139,8 @@
{ 00600, AID_ROOT, AID_ROOT, 0, "odm/default.prop" },
{ 00444, AID_ROOT, AID_ROOT, 0, odm_conf_dir + 1 },
{ 00444, AID_ROOT, AID_ROOT, 0, odm_conf_file + 1 },
- { 00600, AID_ROOT, AID_ROOT, 0, "system/odm/build.prop" },
- { 00600, AID_ROOT, AID_ROOT, 0, "system/odm/default.prop" },
- { 00444, AID_ROOT, AID_ROOT, 0, "system/odm/etc/fs_config_dirs" },
- { 00444, AID_ROOT, AID_ROOT, 0, "system/odm/etc/fs_config_files" },
{ 00444, AID_ROOT, AID_ROOT, 0, oem_conf_dir + 1 },
{ 00444, AID_ROOT, AID_ROOT, 0, oem_conf_file + 1 },
- { 00444, AID_ROOT, AID_ROOT, 0, "system/oem/etc/fs_config_dirs" },
- { 00444, AID_ROOT, AID_ROOT, 0, "system/oem/etc/fs_config_files" },
{ 00750, AID_ROOT, AID_SHELL, 0, "sbin/fs_mgr" },
{ 00755, AID_ROOT, AID_SHELL, 0, "system/bin/crash_dump32" },
{ 00755, AID_ROOT, AID_SHELL, 0, "system/bin/crash_dump64" },
@@ -163,10 +157,6 @@
{ 00555, AID_ROOT, AID_ROOT, 0, "system/etc/ppp/*" },
{ 00555, AID_ROOT, AID_ROOT, 0, "system/etc/rc.*" },
{ 00440, AID_ROOT, AID_ROOT, 0, "system/etc/recovery.img" },
- { 00600, AID_ROOT, AID_ROOT, 0, "system/vendor/build.prop" },
- { 00600, AID_ROOT, AID_ROOT, 0, "system/vendor/default.prop" },
- { 00444, AID_ROOT, AID_ROOT, 0, "system/vendor/etc/fs_config_dirs" },
- { 00444, AID_ROOT, AID_ROOT, 0, "system/vendor/etc/fs_config_files" },
{ 00600, AID_ROOT, AID_ROOT, 0, "vendor/build.prop" },
{ 00600, AID_ROOT, AID_ROOT, 0, "vendor/default.prop" },
{ 00444, AID_ROOT, AID_ROOT, 0, ven_conf_dir + 1 },
@@ -202,17 +192,11 @@
// Support RT scheduling in Bluetooth
{ 00700, AID_BLUETOOTH, AID_BLUETOOTH, CAP_MASK_LONG(CAP_NET_ADMIN) |
CAP_MASK_LONG(CAP_SYS_NICE),
- "system/vendor/bin/hw/android.hardware.bluetooth@1.0-service" },
- { 00700, AID_BLUETOOTH, AID_BLUETOOTH, CAP_MASK_LONG(CAP_NET_ADMIN) |
- CAP_MASK_LONG(CAP_SYS_NICE),
"vendor/bin/hw/android.hardware.bluetooth@1.0-service" },
// Support wifi_hal_legacy administering a network interface.
{ 00755, AID_WIFI, AID_WIFI, CAP_MASK_LONG(CAP_NET_ADMIN) |
CAP_MASK_LONG(CAP_NET_RAW),
- "system/vendor/bin/hw/android.hardware.wifi@1.0-service" },
- { 00755, AID_WIFI, AID_WIFI, CAP_MASK_LONG(CAP_NET_ADMIN) |
- CAP_MASK_LONG(CAP_NET_RAW),
"vendor/bin/hw/android.hardware.wifi@1.0-service" },
// A non-privileged zygote that spawns isolated processes for web rendering.
@@ -233,8 +217,6 @@
{ 00755, AID_ROOT, AID_SHELL, 0, "system/bin/*" },
{ 00755, AID_ROOT, AID_ROOT, 0, "system/lib/valgrind/*" },
{ 00755, AID_ROOT, AID_ROOT, 0, "system/lib64/valgrind/*" },
- { 00755, AID_ROOT, AID_SHELL, 0, "system/vendor/bin/*" },
- { 00755, AID_ROOT, AID_SHELL, 0, "system/vendor/xbin/*" },
{ 00755, AID_ROOT, AID_SHELL, 0, "system/xbin/*" },
{ 00755, AID_ROOT, AID_SHELL, 0, "vendor/bin/*" },
{ 00755, AID_ROOT, AID_SHELL, 0, "vendor/xbin/*" },
@@ -273,6 +255,36 @@
return fd;
}
+// if path is "vendor/<stuff>", "oem/<stuff>" or "odm/<stuff>"
+static bool is_partition(const char* path, size_t len) {
+ static const char* partitions[] = {"vendor/", "oem/", "odm/"};
+ for (size_t i = 0; i < (sizeof(partitions) / sizeof(partitions[0])); ++i) {
+ size_t plen = strlen(partitions[i]);
+ if (len <= plen) continue;
+ if (!strncmp(path, partitions[i], plen)) return true;
+ }
+ return false;
+}
+
+// alias prefixes of "<partition>/<stuff>" to "system/<partition>/<stuff>" or
+// "system/<partition>/<stuff>" to "<partition>/<stuff>"
+static bool prefix_cmp(const char* prefix, const char* path, size_t len) {
+ if (!strncmp(prefix, path, len)) return true;
+
+ static const char system[] = "system/";
+ if (!strncmp(path, system, strlen(system))) {
+ path += strlen(system);
+ } else if (len <= strlen(system)) {
+ return false;
+ } else if (strncmp(prefix, system, strlen(system))) {
+ return false;
+ } else {
+ prefix += strlen(system);
+ len -= strlen(system);
+ }
+ return is_partition(prefix, len) && !strncmp(prefix, path, len);
+}
+
static bool fs_config_cmp(bool dir, const char* prefix, size_t len, const char* path, size_t plen) {
if (dir) {
if (plen < len) {
@@ -281,13 +293,13 @@
} else {
// If name ends in * then allow partial matches.
if (prefix[len - 1] == '*') {
- return !strncmp(prefix, path, len - 1);
+ return prefix_cmp(prefix, path, len - 1);
}
if (plen != len) {
return false;
}
}
- return !strncmp(prefix, path, len);
+ return prefix_cmp(prefix, path, len);
}
void fs_config(const char* path, int dir, const char* target_out_path, unsigned* uid, unsigned* gid,
diff --git a/libcutils/tests/fs_config.cpp b/libcutils/tests/fs_config.cpp
index 3917a0b..a62cd51 100644
--- a/libcutils/tests/fs_config.cpp
+++ b/libcutils/tests/fs_config.cpp
@@ -14,63 +14,188 @@
* limitations under the License.
*/
+#include <inttypes.h>
+
#include <string>
#include <gtest/gtest.h>
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <private/android_filesystem_config.h>
+#include <private/fs_config.h>
-extern const struct fs_path_config* __for_testing_only__android_dirs;
-extern const struct fs_path_config* __for_testing_only__android_files;
+extern const fs_path_config* __for_testing_only__android_dirs;
+extern const fs_path_config* __for_testing_only__android_files;
-static void check_one(const struct fs_path_config* paths, const std::string& prefix,
- const std::string& alternate) {
- for (size_t idx = 0; paths[idx].prefix; ++idx) {
- std::string path(paths[idx].prefix);
- if (android::base::StartsWith(path, prefix.c_str())) {
- path = alternate + path.substr(prefix.length());
- size_t second;
- for (second = 0; paths[second].prefix; ++second) {
- if (path == paths[second].prefix) break;
+// Maximum entries in system/core/libcutils/fs_config.cpp:android_* before we
+// hit a nullptr termination, before we declare the list is just too big or
+// could be missing the nullptr.
+static constexpr size_t max_idx = 4096;
+
+static bool check_unique(std::vector<const char*>& paths, const std::string& config_name,
+ const std::string& prefix) {
+ bool retval = false;
+
+ std::string alternate = "system/" + prefix;
+
+ for (size_t idx = 0; idx < paths.size(); ++idx) {
+ size_t second;
+ std::string path(paths[idx]);
+ // check if there are multiple identical paths
+ for (second = idx + 1; second < paths.size(); ++second) {
+ if (path == paths[second]) {
+ GTEST_LOG_(ERROR) << "duplicate paths in " << config_name << ": " << paths[idx];
+ retval = true;
+ break;
}
- if (!paths[second].prefix) {
- // guaranteed to fail expectations, trigger test failure with
- // a message that reports the violation as an inequality.
- EXPECT_STREQ((prefix + path.substr(alternate.length())).c_str(), path.c_str());
+ }
+
+ // check if path is <partition>/
+ if (android::base::StartsWith(path, prefix.c_str())) {
+ // rebuild path to be system/<partition>/... to check for alias
+ path = alternate + path.substr(prefix.size());
+ for (second = 0; second < paths.size(); ++second) {
+ if (path == paths[second]) {
+ GTEST_LOG_(ERROR) << "duplicate alias paths in " << config_name << ": "
+ << paths[idx] << " and " << paths[second]
+ << " (remove latter)";
+ retval = true;
+ break;
+ }
+ }
+ continue;
+ }
+
+ // check if path is system/<partition>/
+ if (android::base::StartsWith(path, alternate.c_str())) {
+ // rebuild path to be <partition>/... to check for alias
+ path = prefix + path.substr(alternate.size());
+ for (second = 0; second < paths.size(); ++second) {
+ if (path == paths[second]) break;
+ }
+ if (second >= paths.size()) {
+ GTEST_LOG_(ERROR) << "replace path in " << config_name << ": " << paths[idx]
+ << " with " << path;
+ retval = true;
}
}
}
+ return retval;
}
-static void check_two(const struct fs_path_config* paths, const std::string& prefix) {
+static bool check_unique(const fs_path_config* paths, const char* type_name,
+ const std::string& prefix) {
+ std::string config("system/core/libcutils/fs_config.cpp:android_");
+ config += type_name;
+ config += "[]";
+
+ bool retval = false;
+ std::vector<const char*> paths_tmp;
+ for (size_t idx = 0; paths[idx].prefix; ++idx) {
+ if (idx > max_idx) {
+ GTEST_LOG_(WARNING) << config << ": has no end (missing null prefix)";
+ retval = true;
+ break;
+ }
+ paths_tmp.push_back(paths[idx].prefix);
+ }
+
+ return check_unique(paths_tmp, config, prefix) || retval;
+}
+
+#define endof(pointer, field) (offsetof(typeof(*(pointer)), field) + sizeof((pointer)->field))
+
+static bool check_unique(const std::string& config, const std::string& prefix) {
+ int retval = false;
+
+ std::string data;
+ if (!android::base::ReadFileToString(config, &data)) return retval;
+
+ const fs_path_config_from_file* pc =
+ reinterpret_cast<const fs_path_config_from_file*>(data.c_str());
+ size_t len = data.size();
+
+ std::vector<const char*> paths_tmp;
+ size_t entry_number = 0;
+ while (len > 0) {
+ uint16_t host_len = (len >= endof(pc, len)) ? pc->len : INT16_MAX;
+ if (host_len > len) {
+ GTEST_LOG_(WARNING) << config << ": truncated at entry " << entry_number << " ("
+ << host_len << " > " << len << ")";
+ const std::string unknown("?");
+ GTEST_LOG_(WARNING)
+ << config << ": entry[" << entry_number << "]={ "
+ << "len=" << ((len >= endof(pc, len))
+ ? android::base::StringPrintf("%" PRIu16, pc->len)
+ : unknown)
+ << ", mode=" << ((len >= endof(pc, mode))
+ ? android::base::StringPrintf("0%" PRIo16, pc->mode)
+ : unknown)
+ << ", uid=" << ((len >= endof(pc, uid))
+ ? android::base::StringPrintf("%" PRIu16, pc->uid)
+ : unknown)
+ << ", gid=" << ((len >= endof(pc, gid))
+ ? android::base::StringPrintf("%" PRIu16, pc->gid)
+ : unknown)
+ << ", capabilities="
+ << ((len >= endof(pc, capabilities))
+ ? android::base::StringPrintf("0x%" PRIx64, pc->capabilities)
+ : unknown)
+ << ", prefix="
+ << ((len >= offsetof(fs_path_config_from_file, prefix))
+ ? android::base::StringPrintf(
+ "\"%.*s...", (int)(len - offsetof(fs_path_config_from_file, prefix)),
+ pc->prefix)
+ : unknown)
+ << " }";
+ retval = true;
+ break;
+ }
+ paths_tmp.push_back(pc->prefix);
+
+ pc = reinterpret_cast<const fs_path_config_from_file*>(reinterpret_cast<const char*>(pc) +
+ host_len);
+ len -= host_len;
+ ++entry_number;
+ }
+
+ return check_unique(paths_tmp, config, prefix) || retval;
+}
+
+void check_two(const fs_path_config* paths, const char* type_name, const char* prefix) {
ASSERT_FALSE(paths == nullptr);
- std::string alternate = "system/" + prefix;
- check_one(paths, prefix, alternate);
- check_one(paths, alternate, prefix);
+ ASSERT_FALSE(type_name == nullptr);
+ ASSERT_FALSE(prefix == nullptr);
+ bool check_internal = check_unique(paths, type_name, prefix);
+ EXPECT_FALSE(check_internal);
+ bool check_overrides =
+ check_unique(std::string("/") + prefix + "etc/fs_config_" + type_name, prefix);
+ EXPECT_FALSE(check_overrides);
}
TEST(fs_config, vendor_dirs_alias) {
- check_two(__for_testing_only__android_dirs, "vendor/");
+ check_two(__for_testing_only__android_dirs, "dirs", "vendor/");
}
TEST(fs_config, vendor_files_alias) {
- check_two(__for_testing_only__android_files, "vendor/");
+ check_two(__for_testing_only__android_files, "files", "vendor/");
}
TEST(fs_config, oem_dirs_alias) {
- check_two(__for_testing_only__android_dirs, "oem/");
+ check_two(__for_testing_only__android_dirs, "dirs", "oem/");
}
TEST(fs_config, oem_files_alias) {
- check_two(__for_testing_only__android_files, "oem/");
+ check_two(__for_testing_only__android_files, "files", "oem/");
}
TEST(fs_config, odm_dirs_alias) {
- check_two(__for_testing_only__android_dirs, "odm/");
+ check_two(__for_testing_only__android_dirs, "dirs", "odm/");
}
TEST(fs_config, odm_files_alias) {
- check_two(__for_testing_only__android_files, "odm/");
+ check_two(__for_testing_only__android_files, "files", "odm/");
}
diff --git a/libmetricslogger/Android.bp b/libmetricslogger/Android.bp
index 75eab66..26a041a 100644
--- a/libmetricslogger/Android.bp
+++ b/libmetricslogger/Android.bp
@@ -22,7 +22,8 @@
// 524291 corresponds to sysui_histogram, from
// frameworks/base/core/java/com/android/internal/logging/EventLogTags.logtags
- "-DHISTOGRAM_LOG_TAG=524291",
+ "-DHISTOGRAM_LOG_TAG=524292",
+ "-DCOUNT_LOG_TAG=524290",
],
}
diff --git a/libmetricslogger/include/metricslogger/metrics_logger.h b/libmetricslogger/include/metricslogger/metrics_logger.h
index d30e56c..36e124d 100644
--- a/libmetricslogger/include/metricslogger/metrics_logger.h
+++ b/libmetricslogger/include/metricslogger/metrics_logger.h
@@ -24,5 +24,19 @@
// buffer.
void LogHistogram(const std::string& event, int32_t data);
+// Logs a Tron counter metric named |name| containing |val| count to the Tron
+// log buffer.
+void LogCounter(const std::string& name, int32_t val);
+
+// TODO: replace these with the metric_logger.proto definitions
+enum {
+ LOGBUILDER_CATEGORY = 757,
+ LOGBUILDER_NAME = 799,
+ LOGBUILDER_BUCKET = 801,
+ LOGBUILDER_VALUE = 802,
+ LOGBUILDER_COUNTER = 803,
+ LOGBUILDER_HISTOGRAM = 804,
+};
+
} // namespace metricslogger
} // namespace android
diff --git a/libmetricslogger/metrics_logger.cpp b/libmetricslogger/metrics_logger.cpp
index f8e0174..6f65e10 100644
--- a/libmetricslogger/metrics_logger.cpp
+++ b/libmetricslogger/metrics_logger.cpp
@@ -23,9 +23,18 @@
namespace android {
namespace metricslogger {
+// Mirror com.android.internal.logging.MetricsLogger#histogram().
void LogHistogram(const std::string& event, int32_t data) {
- android_log_event_list log(HISTOGRAM_LOG_TAG);
- log << event << data << LOG_ID_EVENTS;
+ android_log_event_list log(HISTOGRAM_LOG_TAG);
+ log << LOGBUILDER_CATEGORY << LOGBUILDER_HISTOGRAM << LOGBUILDER_NAME << event
+ << LOGBUILDER_BUCKET << data << LOGBUILDER_VALUE << 1 << LOG_ID_EVENTS;
+}
+
+// Mirror com.android.internal.logging.MetricsLogger#count().
+void LogCounter(const std::string& name, int32_t val) {
+ android_log_event_list log(COUNT_LOG_TAG);
+ log << LOGBUILDER_CATEGORY << LOGBUILDER_COUNTER << LOGBUILDER_NAME << name << LOGBUILDER_VALUE
+ << val << LOG_ID_EVENTS;
}
} // namespace metricslogger
diff --git a/libmetricslogger/metrics_logger_test.cpp b/libmetricslogger/metrics_logger_test.cpp
index 5a30ad7..440645c 100644
--- a/libmetricslogger/metrics_logger_test.cpp
+++ b/libmetricslogger/metrics_logger_test.cpp
@@ -19,6 +19,10 @@
#include <gtest/gtest.h>
TEST(MetricsLoggerTest, AddSingleBootEvent) {
- android::metricslogger::LogHistogram("test_event", 42);
- // TODO(jhawkins): Verify the EventLog is updated.
+ android::metricslogger::LogHistogram("test_event", 42);
+ // TODO(jhawkins): Verify the EventLog is updated.
+}
+
+TEST(MetricsLoggerTest, AddCounterVal) {
+ android::metricslogger::LogCounter("test_count", 10);
}
diff --git a/libnetutils/Android.bp b/libnetutils/Android.bp
index f710ba2..0caf145 100644
--- a/libnetutils/Android.bp
+++ b/libnetutils/Android.bp
@@ -17,3 +17,17 @@
export_include_dirs: ["include"],
}
+
+cc_binary {
+ name: "dhcpdbg",
+
+ srcs: [
+ "dhcptool.c",
+ ],
+
+ shared_libs: [
+ "libnetutils",
+ ],
+
+ cflags: ["-Werror"],
+}
diff --git a/libnetutils/dhcptool.c b/libnetutils/dhcptool.c
new file mode 100644
index 0000000..280b977
--- /dev/null
+++ b/libnetutils/dhcptool.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2015, 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 <err.h>
+#include <errno.h>
+#include <error.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <netutils/ifc.h>
+
+extern int do_dhcp(char*);
+
+int main(int argc, char* argv[]) {
+ if (argc != 2) {
+ error(EXIT_FAILURE, 0, "usage: %s INTERFACE", argv[0]);
+ }
+
+ char* interface = argv[1];
+ if (ifc_init()) {
+ err(errno, "dhcptool %s: ifc_init failed", interface);
+ ifc_close();
+ return EXIT_FAILURE;
+ }
+
+ int rc = do_dhcp(interface);
+ if (rc) {
+ err(errno, "dhcptool %s: do_dhcp failed", interface);
+ }
+ warn("IP assignment is for debug purposes ONLY");
+ ifc_close();
+
+ return rc ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index ded6c8c..76a4aff 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -79,10 +79,16 @@
if (monotonic) {
if (!android::isMonotonic(e->mRealTime)) {
LogKlog::convertRealToMonotonic(e->mRealTime);
+ if ((e->mRealTime.tv_nsec % 1000) == 0) {
+ e->mRealTime.tv_nsec++;
+ }
}
} else {
if (android::isMonotonic(e->mRealTime)) {
LogKlog::convertMonotonicToReal(e->mRealTime);
+ if ((e->mRealTime.tv_nsec % 1000) == 0) {
+ e->mRealTime.tv_nsec++;
+ }
}
}
++it;
@@ -194,6 +200,11 @@
return -EINVAL;
}
+ // Slip the time by 1 nsec if the incoming lands on xxxxxx000 ns.
+ // This prevents any chance that an outside source can request an
+ // exact entry with time specified in ms or us precision.
+ if ((realtime.tv_nsec % 1000) == 0) ++realtime.tv_nsec;
+
LogBufferElement* elem =
new LogBufferElement(log_id, realtime, uid, pid, tid, msg, len);
if (log_id != LOG_ID_SECURITY) {
@@ -1109,6 +1120,9 @@
LogBufferElement* element = *it;
if (element->getRealTime() > start) {
last = it;
+ } else if (element->getRealTime() == start) {
+ last = ++it;
+ break;
} else if (!--count || (element->getRealTime() < min)) {
break;
}
@@ -1116,7 +1130,7 @@
it = last;
}
- log_time max = start;
+ log_time curr = start;
LogBufferElement* lastElement = nullptr; // iterator corruption paranoia
static const size_t maxSkip = 4194304; // maximum entries to skip
@@ -1142,10 +1156,6 @@
continue;
}
- if (element->getRealTime() <= start) {
- continue;
- }
-
// NB: calling out to another object with wrlock() held (safe)
if (filter) {
int ret = (*filter)(element, arg);
@@ -1172,10 +1182,10 @@
unlock();
// range locking in LastLogTimes looks after us
- max = element->flushTo(reader, this, privileged, sameTid);
+ curr = element->flushTo(reader, this, privileged, sameTid);
- if (max == element->FLUSH_ERROR) {
- return max;
+ if (curr == element->FLUSH_ERROR) {
+ return curr;
}
skip = maxSkip;
@@ -1183,7 +1193,7 @@
}
unlock();
- return max;
+ return curr;
}
std::string LogBuffer::formatStatistics(uid_t uid, pid_t pid,
diff --git a/shell_and_utilities/Android.bp b/shell_and_utilities/Android.bp
index 81cf315..4f4fc5d 100644
--- a/shell_and_utilities/Android.bp
+++ b/shell_and_utilities/Android.bp
@@ -5,9 +5,12 @@
"grep",
"gzip",
"mkshrc",
+ "mkshrc_vendor",
"reboot",
"sh",
+ "sh_vendor",
"toolbox",
"toybox",
+ "toybox_vendor",
],
}
diff --git a/toolbox/Android.bp b/toolbox/Android.bp
new file mode 100644
index 0000000..1c9fb20
--- /dev/null
+++ b/toolbox/Android.bp
@@ -0,0 +1,44 @@
+common_cflags = [
+ "-Werror",
+ "-Wno-unused-parameter",
+ "-Wno-unused-const-variable",
+ "-include bsd-compatibility.h"
+]
+
+cc_library_static {
+ srcs: [
+ "upstream-netbsd/bin/dd/args.c",
+ "upstream-netbsd/bin/dd/conv.c",
+ "upstream-netbsd/bin/dd/dd.c",
+ "upstream-netbsd/bin/dd/dd_hostops.c",
+ "upstream-netbsd/bin/dd/misc.c",
+ "upstream-netbsd/bin/dd/position.c",
+ "upstream-netbsd/lib/libc/gen/getbsize.c",
+ "upstream-netbsd/lib/libc/gen/humanize_number.c",
+ "upstream-netbsd/lib/libc/stdlib/strsuftoll.c",
+ "upstream-netbsd/lib/libc/string/swab.c",
+ "upstream-netbsd/lib/libutil/raise_default_signal.c",
+ ],
+ cflags: common_cflags + [
+ "-Dmain=dd_main",
+ "-DNO_CONV",
+ ],
+ local_include_dirs: ["upstream-netbsd/include/"],
+ name: "libtoolbox_dd",
+}
+
+// We build BSD grep separately, so it can provide egrep and fgrep too.
+cc_binary {
+ name: "grep",
+ srcs: [
+ "upstream-netbsd/usr.bin/grep/fastgrep.c",
+ "upstream-netbsd/usr.bin/grep/file.c",
+ "upstream-netbsd/usr.bin/grep/grep.c",
+ "upstream-netbsd/usr.bin/grep/queue.c",
+ "upstream-netbsd/usr.bin/grep/util.c",
+ ],
+ cflags: common_cflags,
+ local_include_dirs: ["upstream-netbsd/include/"],
+ symlinks: ["egrep", "fgrep"],
+
+}
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index d6ead1a..94029d8 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -1,30 +1,9 @@
LOCAL_PATH:= $(call my-dir)
-
common_cflags := \
-Werror -Wno-unused-parameter -Wno-unused-const-variable \
-include bsd-compatibility.h \
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := \
- upstream-netbsd/bin/dd/args.c \
- upstream-netbsd/bin/dd/conv.c \
- upstream-netbsd/bin/dd/dd.c \
- upstream-netbsd/bin/dd/dd_hostops.c \
- upstream-netbsd/bin/dd/misc.c \
- upstream-netbsd/bin/dd/position.c \
- upstream-netbsd/lib/libc/gen/getbsize.c \
- upstream-netbsd/lib/libc/gen/humanize_number.c \
- upstream-netbsd/lib/libc/stdlib/strsuftoll.c \
- upstream-netbsd/lib/libc/string/swab.c \
- upstream-netbsd/lib/libutil/raise_default_signal.c
-LOCAL_CFLAGS += $(common_cflags) -Dmain=dd_main -DNO_CONV
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/upstream-netbsd/include/
-LOCAL_MODULE := libtoolbox_dd
-include $(BUILD_STATIC_LIBRARY)
-
-
include $(CLEAR_VARS)
BSD_TOOLS := \
@@ -80,18 +59,3 @@
$(INPUT_H_LABELS_H): $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/generate-input.h-labels.py $(UAPI_INPUT_EVENT_CODES_H)
$(INPUT_H_LABELS_H):
$(transform-generated-source)
-
-
-# We build BSD grep separately, so it can provide egrep and fgrep too.
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := \
- upstream-netbsd/usr.bin/grep/fastgrep.c \
- upstream-netbsd/usr.bin/grep/file.c \
- upstream-netbsd/usr.bin/grep/grep.c \
- upstream-netbsd/usr.bin/grep/queue.c \
- upstream-netbsd/usr.bin/grep/util.c
-LOCAL_CFLAGS += $(common_cflags)
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/upstream-netbsd/include/
-LOCAL_MODULE := grep
-LOCAL_POST_INSTALL_CMD := $(hide) $(foreach t,egrep fgrep,ln -sf grep $(TARGET_OUT)/bin/$(t);)
-include $(BUILD_EXECUTABLE)