Merge "Move libz to vndk-sp"
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 23f6580..a7706a0 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -1140,6 +1140,7 @@
if (should_use_libusb()) {
features.insert(kFeatureLibusb);
}
+ features.insert(kFeaturePushSync);
SendOkay(reply_fd, FeatureSetToString(features));
return 0;
}
@@ -1241,10 +1242,7 @@
return true;
});
- D("update_transport_status: transports_ready = %s", result ? "true" : "false");
-
bool ready;
-
{
std::lock_guard<std::mutex> lock(init_mutex);
transports_ready = result;
@@ -1252,14 +1250,11 @@
}
if (ready) {
- D("update_transport_status: notifying");
init_cv.notify_all();
}
}
void adb_notify_device_scan_complete() {
- D("device scan complete");
-
{
std::lock_guard<std::mutex> lock(init_mutex);
device_scan_complete = true;
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
index bd9ad01..62798cd 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -125,6 +125,11 @@
});
#endif
+ if (is_daemon) {
+ close_stdin();
+ setup_daemon_logging();
+ }
+
android::base::at_quick_exit(adb_server_cleanup);
init_transport_registration();
@@ -148,11 +153,6 @@
std::this_thread::sleep_for(100ms);
}
- if (is_daemon) {
- close_stdin();
- setup_daemon_logging();
- }
-
adb_auth_init();
if (is_daemon) {
diff --git a/adb/client/usb_libusb.cpp b/adb/client/usb_libusb.cpp
index 18a8ff2..fc32469 100644
--- a/adb/client/usb_libusb.cpp
+++ b/adb/client/usb_libusb.cpp
@@ -151,10 +151,7 @@
static auto& usb_handles = *new std::unordered_map<std::string, std::unique_ptr<usb_handle>>();
static auto& usb_handles_mutex = *new std::mutex();
-static std::thread* device_poll_thread = nullptr;
-static bool terminate_device_poll_thread = false;
-static auto& device_poll_mutex = *new std::mutex();
-static auto& device_poll_cv = *new std::condition_variable();
+static libusb_hotplug_callback_handle hotplug_handle;
static std::string get_device_address(libusb_device* device) {
return StringPrintf("usb:%d:%d", libusb_get_bus_number(device),
@@ -175,6 +172,17 @@
path += "/serial";
return path;
}
+
+static std::string get_device_dev_path(libusb_device* device) {
+ uint8_t ports[7];
+ int port_count = libusb_get_port_numbers(device, ports, 7);
+ if (port_count < 0) return "";
+ return StringPrintf("/dev/bus/usb/%03u/%03u", libusb_get_bus_number(device), ports[0]);
+}
+
+static bool is_device_accessible(libusb_device* device) {
+ return access(get_device_dev_path(device).c_str(), R_OK | W_OK) == 0;
+}
#endif
static bool endpoint_is_output(uint8_t endpoint) {
@@ -229,7 +237,7 @@
// TODO: Is this assumption valid?
LOG(VERBOSE) << "skipping interface with incorrect num_altsetting at " << device_address
<< " (interface " << interface_num << ")";
- return;
+ continue;
}
const libusb_interface_descriptor& interface_desc = interface.altsetting[0];
@@ -237,7 +245,7 @@
interface_desc.bInterfaceProtocol)) {
LOG(VERBOSE) << "skipping non-adb interface at " << device_address << " (interface "
<< interface_num << ")";
- return;
+ continue;
}
LOG(VERBOSE) << "found potential adb interface at " << device_address << " (interface "
@@ -253,7 +261,7 @@
const uint8_t transfer_type = endpoint_attr & LIBUSB_TRANSFER_TYPE_MASK;
if (transfer_type != LIBUSB_TRANSFER_TYPE_BULK) {
- return;
+ continue;
}
if (endpoint_is_output(endpoint_addr) && !found_out) {
@@ -371,33 +379,62 @@
}
register_usb_transport(usb_handle_raw, device_serial.c_str(), device_address.c_str(), writable);
-
LOG(INFO) << "registered new usb device '" << device_serial << "'";
}
-static void poll_for_devices() {
- libusb_device** list;
- adb_thread_setname("device poll");
- while (true) {
- const ssize_t device_count = libusb_get_device_list(nullptr, &list);
+static std::atomic<int> connecting_devices(0);
- LOG(VERBOSE) << "found " << device_count << " attached devices";
-
- for (ssize_t i = 0; i < device_count; ++i) {
- process_device(list[i]);
+static void device_connected(libusb_device* device) {
+#if defined(__linux__)
+ // Android's host linux libusb uses netlink instead of udev for device hotplug notification,
+ // which means we can get hotplug notifications before udev has updated ownership/perms on the
+ // device. Since we're not going to be able to link against the system's libudev any time soon,
+ // hack around this by checking for accessibility in a loop.
+ ++connecting_devices;
+ auto thread = std::thread([device]() {
+ std::string device_path = get_device_dev_path(device);
+ auto start = std::chrono::steady_clock::now();
+ while (std::chrono::steady_clock::now() - start < 500ms) {
+ if (is_device_accessible(device)) {
+ break;
+ }
+ std::this_thread::sleep_for(10ms);
}
- libusb_free_device_list(list, 1);
+ process_device(device);
+ --connecting_devices;
+ });
+ thread.detach();
+#else
+ process_device(device);
+#endif
+}
- adb_notify_device_scan_complete();
+static void device_disconnected(libusb_device* device) {
+ std::string device_address = get_device_address(device);
- std::unique_lock<std::mutex> lock(device_poll_mutex);
- if (device_poll_cv.wait_for(lock, 500ms, []() { return terminate_device_poll_thread; })) {
- return;
+ LOG(INFO) << "device disconnected: " << device_address;
+ std::unique_lock<std::mutex> lock(usb_handles_mutex);
+ auto it = usb_handles.find(device_address);
+ if (it != usb_handles.end()) {
+ if (!it->second->device_handle) {
+ // If the handle is null, we were never able to open the device.
+ unregister_usb_transport(it->second.get());
}
+ usb_handles.erase(it);
}
}
+static int hotplug_callback(libusb_context*, libusb_device* device, libusb_hotplug_event event,
+ void*) {
+ if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED) {
+ device_connected(device);
+ } else if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT) {
+ device_disconnected(device);
+ }
+ return 0;
+}
+
void usb_init() {
LOG(DEBUG) << "initializing libusb...";
int rc = libusb_init(nullptr);
@@ -405,6 +442,24 @@
LOG(FATAL) << "failed to initialize libusb: " << libusb_error_name(rc);
}
+ // Register the hotplug callback.
+ rc = libusb_hotplug_register_callback(
+ nullptr, static_cast<libusb_hotplug_event>(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED |
+ LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT),
+ LIBUSB_HOTPLUG_ENUMERATE, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY,
+ LIBUSB_CLASS_PER_INTERFACE, hotplug_callback, nullptr, &hotplug_handle);
+
+ if (rc != LIBUSB_SUCCESS) {
+ LOG(FATAL) << "failed to register libusb hotplug callback";
+ }
+
+ // Wait for all of the connecting devices to finish.
+ while (connecting_devices != 0) {
+ std::this_thread::sleep_for(10ms);
+ }
+
+ adb_notify_device_scan_complete();
+
// Spawn a thread for libusb_handle_events.
std::thread([]() {
adb_thread_setname("libusb");
@@ -412,24 +467,10 @@
libusb_handle_events(nullptr);
}
}).detach();
-
- // Spawn a thread to do device enumeration.
- // TODO: Use libusb_hotplug_* instead?
- std::unique_lock<std::mutex> lock(device_poll_mutex);
- device_poll_thread = new std::thread(poll_for_devices);
}
void usb_cleanup() {
- {
- std::unique_lock<std::mutex> lock(device_poll_mutex);
- terminate_device_poll_thread = true;
-
- if (!device_poll_thread) {
- return;
- }
- }
- device_poll_cv.notify_all();
- device_poll_thread->join();
+ libusb_hotplug_deregister_callback(nullptr, hotplug_handle);
}
// Dispatch a libusb transfer, unlock |device_lock|, and then wait for the result.
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/adb/transport.cpp b/adb/transport.cpp
index 13cfaa1..308ee8d 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -55,6 +55,7 @@
const char* const kFeatureCmd = "cmd";
const char* const kFeatureStat2 = "stat_v2";
const char* const kFeatureLibusb = "libusb";
+const char* const kFeaturePushSync = "push_sync";
static std::string dump_packet(const char* name, const char* func, apacket* p) {
unsigned command = p->msg.command;
@@ -1050,27 +1051,24 @@
[usb](atransport* t) { return t->usb == usb && t->GetConnectionState() == kCsNoPerm; });
}
-int check_header(apacket* p, atransport* t) {
+bool check_header(apacket* p, atransport* t) {
if (p->msg.magic != (p->msg.command ^ 0xffffffff)) {
VLOG(RWX) << "check_header(): invalid magic command = " << std::hex << p->msg.command
<< ", magic = " << p->msg.magic;
- return -1;
+ return false;
}
if (p->msg.data_length > t->get_max_payload()) {
VLOG(RWX) << "check_header(): " << p->msg.data_length
<< " atransport::max_payload = " << t->get_max_payload();
- return -1;
+ return false;
}
- return 0;
+ return true;
}
-int check_data(apacket* p) {
- if (calculate_apacket_checksum(p) != p->msg.data_check) {
- return -1;
- }
- return 0;
+bool check_data(apacket* p) {
+ return calculate_apacket_checksum(p) == p->msg.data_check;
}
#if ADB_HOST
diff --git a/adb/transport.h b/adb/transport.h
index 006aaf4..57fc988 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -51,6 +51,8 @@
extern const char* const kFeatureStat2;
// The server is running with libusb enabled.
extern const char* const kFeatureLibusb;
+// The server supports `push --sync`.
+extern const char* const kFeaturePushSync;
class atransport {
public:
@@ -221,8 +223,8 @@
// This should only be used for transports with connection_state == kCsNoPerm.
void unregister_usb_transport(usb_handle* usb);
-int check_header(apacket* p, atransport* t);
-int check_data(apacket* p);
+bool check_header(apacket* p, atransport* t);
+bool check_data(apacket* p);
void close_usb_devices();
void close_usb_devices(std::function<bool(const atransport*)> predicate);
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index e5992b1..809ed89 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -62,22 +62,22 @@
static int remote_read(apacket *p, atransport *t)
{
- if(!ReadFdExactly(t->sfd, &p->msg, sizeof(amessage))){
+ if (!ReadFdExactly(t->sfd, &p->msg, sizeof(amessage))) {
D("remote local: read terminated (message)");
return -1;
}
- if(check_header(p, t)) {
+ if (!check_header(p, t)) {
D("bad header: terminated (data)");
return -1;
}
- if(!ReadFdExactly(t->sfd, p->data, p->msg.data_length)){
+ if (!ReadFdExactly(t->sfd, p->data, p->msg.data_length)) {
D("remote local: terminated (data)");
return -1;
}
- if(check_data(p)) {
+ if (!check_data(p)) {
D("bad data: terminated (data)");
return -1;
}
diff --git a/adb/transport_usb.cpp b/adb/transport_usb.cpp
index 885d723..47094b8 100644
--- a/adb/transport_usb.cpp
+++ b/adb/transport_usb.cpp
@@ -72,7 +72,7 @@
D("remote usb: read terminated (message)");
return -1;
}
- if (static_cast<size_t>(n) != sizeof(p->msg) || check_header(p, t)) {
+ if (static_cast<size_t>(n) != sizeof(p->msg) || !check_header(p, t)) {
D("remote usb: check_header failed, skip it");
goto err_msg;
}
@@ -95,7 +95,7 @@
goto err_msg;
}
}
- if (check_data(p)) {
+ if (!check_data(p)) {
D("remote usb: check_data failed, skip it");
goto err_msg;
}
@@ -124,19 +124,19 @@
return -1;
}
- if(check_header(p, t)) {
+ if (!check_header(p, t)) {
D("remote usb: check_header failed");
return -1;
}
- if(p->msg.data_length) {
+ if (p->msg.data_length) {
if (usb_read(t->usb, p->data, p->msg.data_length)) {
D("remote usb: terminated (data)");
return -1;
}
}
- if(check_data(p)) {
+ if (!check_data(p)) {
D("remote usb: check_data failed");
return -1;
}
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/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index 6f25d96..d4e215e 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -221,19 +221,24 @@
}
}
-// Parses and records the set of bootloader stages and associated boot times
-// from the ro.boot.boottime system property.
-void RecordBootloaderTimings(BootEventRecordStore* boot_event_store) {
- // |ro.boot.boottime| is of the form 'stage1:time1,...,stageN:timeN'.
+// A map from bootloader timing stage to the time that stage took during boot.
+typedef std::map<std::string, int32_t> BootloaderTimingMap;
+
+// Returns a mapping from bootloader stage names to the time those stages
+// took to boot.
+const BootloaderTimingMap GetBootLoaderTimings() {
+ BootloaderTimingMap timings;
+
+ // |ro.boot.boottime| is of the form 'stage1:time1,...,stageN:timeN',
+ // where timeN is in milliseconds.
std::string value = GetProperty("ro.boot.boottime");
if (value.empty()) {
// ro.boot.boottime is not reported on all devices.
- return;
+ return BootloaderTimingMap();
}
- int32_t total_time = 0;
auto stages = android::base::Split(value, ",");
- for (auto const &stageTiming : stages) {
+ for (const auto& stageTiming : stages) {
// |stageTiming| is of the form 'stage:time'.
auto stageTimingValues = android::base::Split(stageTiming, ":");
DCHECK_EQ(2, stageTimingValues.size());
@@ -241,23 +246,53 @@
std::string stageName = stageTimingValues[0];
int32_t time_ms;
if (android::base::ParseInt(stageTimingValues[1], &time_ms)) {
- total_time += time_ms;
- boot_event_store->AddBootEventWithValue(
- "boottime.bootloader." + stageName, time_ms);
+ timings[stageName] = time_ms;
}
}
+ return timings;
+}
+
+// Parses and records the set of bootloader stages and associated boot times
+// from the ro.boot.boottime system property.
+void RecordBootloaderTimings(BootEventRecordStore* boot_event_store,
+ const BootloaderTimingMap& bootloader_timings) {
+ int32_t total_time = 0;
+ for (const auto& timing : bootloader_timings) {
+ total_time += timing.second;
+ boot_event_store->AddBootEventWithValue("boottime.bootloader." + timing.first, timing.second);
+ }
+
boot_event_store->AddBootEventWithValue("boottime.bootloader.total", total_time);
}
+// Records the closest estimation to the absolute device boot time, i.e.,
+// from power on to boot_complete, including bootloader times.
+void RecordAbsoluteBootTime(BootEventRecordStore* boot_event_store,
+ const BootloaderTimingMap& bootloader_timings,
+ std::chrono::milliseconds uptime) {
+ int32_t bootloader_time_ms = 0;
+
+ for (const auto& timing : bootloader_timings) {
+ if (timing.first.compare("SW") != 0) {
+ bootloader_time_ms += timing.second;
+ }
+ }
+
+ auto bootloader_duration = std::chrono::milliseconds(bootloader_time_ms);
+ auto absolute_total =
+ std::chrono::duration_cast<std::chrono::seconds>(bootloader_duration + uptime);
+ boot_event_store->AddBootEventWithValue("absolute_boot_time", absolute_total.count());
+}
+
// Records several metrics related to the time it takes to boot the device,
// including disambiguating boot time on encrypted or non-encrypted devices.
void RecordBootComplete() {
BootEventRecordStore boot_event_store;
BootEventRecordStore::BootEventRecord record;
- auto uptime = std::chrono::duration_cast<std::chrono::seconds>(
- android::base::boot_clock::now().time_since_epoch());
+ auto time_since_epoch = android::base::boot_clock::now().time_since_epoch();
+ auto uptime = std::chrono::duration_cast<std::chrono::seconds>(time_since_epoch);
time_t current_time_utc = time(nullptr);
if (boot_event_store.GetBootEvent("last_boot_time_utc", &record)) {
@@ -290,7 +325,6 @@
std::chrono::seconds boot_complete = std::chrono::seconds(uptime.count() - record.second);
boot_event_store.AddBootEventWithValue(boot_complete_prefix + "_post_decrypt",
boot_complete.count());
-
} else {
boot_event_store.AddBootEventWithValue(boot_complete_prefix + "_no_encryption",
uptime.count());
@@ -304,7 +338,11 @@
RecordInitBootTimeProp(&boot_event_store, "ro.boottime.init.selinux");
RecordInitBootTimeProp(&boot_event_store, "ro.boottime.init.cold_boot_wait");
- RecordBootloaderTimings(&boot_event_store);
+ const BootloaderTimingMap bootloader_timings = GetBootLoaderTimings();
+ RecordBootloaderTimings(&boot_event_store, bootloader_timings);
+
+ auto uptime_ms = std::chrono::duration_cast<std::chrono::milliseconds>(time_since_epoch);
+ RecordAbsoluteBootTime(&boot_event_store, bootloader_timings, uptime_ms);
}
// Records the boot_reason metric by querying the ro.boot.bootreason system
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index 37d54d7..3a80b50 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -11,12 +11,32 @@
local_include_dirs: ["include"],
}
-// Utility library to tombstoned and get an output fd.
-cc_library_static {
+cc_library_shared {
name: "libtombstoned_client",
defaults: ["debuggerd_defaults"],
srcs: [
- "tombstoned_client.cpp",
+ "tombstoned/tombstoned_client.cpp",
+ "util.cpp",
+ ],
+
+ static_libs: [
+ "libasync_safe"
+ ],
+
+ shared_libs: [
+ "libcutils",
+ "libbase",
+ ],
+
+ export_include_dirs: ["tombstoned/include"]
+}
+
+// Utility library to tombstoned and get an output fd.
+cc_library_static {
+ name: "libtombstoned_client_static",
+ defaults: ["debuggerd_defaults"],
+ srcs: [
+ "tombstoned/tombstoned_client.cpp",
"util.cpp",
],
@@ -25,6 +45,8 @@
"libcutils",
"libbase",
],
+
+ export_include_dirs: ["tombstoned/include"]
}
// Core implementation, linked into libdebuggerd_handler and the dynamic linker.
@@ -64,7 +86,7 @@
whole_static_libs: [
"libdebuggerd_handler_core",
- "libtombstoned_client",
+ "libtombstoned_client_static",
"libasync_safe",
"libbase",
"libdebuggerd",
@@ -159,10 +181,8 @@
srcs: [
"client/debuggerd_client_test.cpp",
"debuggerd_test.cpp",
- "tombstoned_client.cpp",
- "util.cpp"
],
- static_libs: ["libasync_safe"],
+ static_libs: ["libasync_safe", "libtombstoned_client_static"],
},
},
@@ -171,6 +191,7 @@
"libbase",
"libcutils",
"libdebuggerd_client",
+ "liblog"
],
static_libs: [
@@ -211,7 +232,7 @@
},
static_libs: [
- "libtombstoned_client",
+ "libtombstoned_client_static",
"libdebuggerd",
"libcutils",
],
diff --git a/debuggerd/client/debuggerd_client.cpp b/debuggerd/client/debuggerd_client.cpp
index 2be13c6..4ce038c 100644
--- a/debuggerd/client/debuggerd_client.cpp
+++ b/debuggerd/client/debuggerd_client.cpp
@@ -31,9 +31,10 @@
#include <android-base/stringprintf.h>
#include <android-base/unique_fd.h>
#include <cutils/sockets.h>
-#include <debuggerd/handler.h>
-#include <debuggerd/protocol.h>
-#include <debuggerd/util.h>
+
+#include "debuggerd/handler.h"
+#include "protocol.h"
+#include "util.h"
using namespace std::chrono_literals;
diff --git a/debuggerd/client/debuggerd_client_test.cpp b/debuggerd/client/debuggerd_client_test.cpp
index aff03e5..8f97db1 100644
--- a/debuggerd/client/debuggerd_client_test.cpp
+++ b/debuggerd/client/debuggerd_client_test.cpp
@@ -31,7 +31,7 @@
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
-#include <debuggerd/util.h>
+#include "util.h"
using namespace std::chrono_literals;
using android::base::unique_fd;
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index d2a4239..be28079 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -48,9 +48,9 @@
#include "utility.h"
#include "debuggerd/handler.h"
-#include "debuggerd/protocol.h"
-#include "debuggerd/tombstoned.h"
-#include "debuggerd/util.h"
+#include "protocol.h"
+#include "tombstoned/tombstoned.h"
+#include "util.h"
using android::base::unique_fd;
using android::base::ReadFileToString;
diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp
index 492e9f0..4997dd6 100644
--- a/debuggerd/debuggerd.cpp
+++ b/debuggerd/debuggerd.cpp
@@ -27,8 +27,8 @@
#include <android-base/parseint.h>
#include <android-base/unique_fd.h>
#include <debuggerd/client.h>
-#include <debuggerd/util.h>
#include <selinux/selinux.h>
+#include "util.h"
using android::base::unique_fd;
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index 0b4bbfb..f17724a 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -35,12 +35,13 @@
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <cutils/sockets.h>
-#include <debuggerd/handler.h>
-#include <debuggerd/protocol.h>
-#include <debuggerd/tombstoned.h>
-#include <debuggerd/util.h>
#include <gtest/gtest.h>
+#include "debuggerd/handler.h"
+#include "protocol.h"
+#include "tombstoned/tombstoned.h"
+#include "util.h"
+
using namespace std::chrono_literals;
using android::base::unique_fd;
diff --git a/debuggerd/handler/debuggerd_fallback.cpp b/debuggerd/handler/debuggerd_fallback.cpp
index 47c98d1..a9c9862 100644
--- a/debuggerd/handler/debuggerd_fallback.cpp
+++ b/debuggerd/handler/debuggerd_fallback.cpp
@@ -42,8 +42,8 @@
#include <async_safe/log.h>
#include "debuggerd/handler.h"
-#include "debuggerd/tombstoned.h"
-#include "debuggerd/util.h"
+#include "tombstoned/tombstoned.h"
+#include "util.h"
#include "backtrace.h"
#include "tombstone.h"
diff --git a/debuggerd/include/debuggerd/protocol.h b/debuggerd/protocol.h
similarity index 96%
rename from debuggerd/include/debuggerd/protocol.h
rename to debuggerd/protocol.h
index 0756876..144efc8 100644
--- a/debuggerd/include/debuggerd/protocol.h
+++ b/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/tombstoned/include/tombstoned/tombstoned.h
similarity index 89%
rename from debuggerd/include/debuggerd/tombstoned.h
rename to debuggerd/tombstoned/include/tombstoned/tombstoned.h
index d158d50..908517d 100644
--- a/debuggerd/include/debuggerd/tombstoned.h
+++ b/debuggerd/tombstoned/include/tombstoned/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/intercept_manager.cpp b/debuggerd/tombstoned/intercept_manager.cpp
index dff942c..4d4eb9e 100644
--- a/debuggerd/tombstoned/intercept_manager.cpp
+++ b/debuggerd/tombstoned/intercept_manager.cpp
@@ -28,8 +28,8 @@
#include <android-base/unique_fd.h>
#include <cutils/sockets.h>
-#include "debuggerd/protocol.h"
-#include "debuggerd/util.h"
+#include "protocol.h"
+#include "util.h"
using android::base::unique_fd;
diff --git a/debuggerd/tombstoned/tombstoned.cpp b/debuggerd/tombstoned/tombstoned.cpp
index 2248a21..05df9f2 100644
--- a/debuggerd/tombstoned/tombstoned.cpp
+++ b/debuggerd/tombstoned/tombstoned.cpp
@@ -35,8 +35,8 @@
#include <cutils/sockets.h>
#include "debuggerd/handler.h"
-#include "debuggerd/protocol.h"
-#include "debuggerd/util.h"
+#include "protocol.h"
+#include "util.h"
#include "intercept_manager.h"
@@ -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/tombstoned_client.cpp
similarity index 89%
rename from debuggerd/tombstoned_client.cpp
rename to debuggerd/tombstoned/tombstoned_client.cpp
index 4741fa6..39dc6eb 100644
--- a/debuggerd/tombstoned_client.cpp
+++ b/debuggerd/tombstoned/tombstoned_client.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "debuggerd/tombstoned.h"
+#include "tombstoned/tombstoned.h"
#include <fcntl.h>
#include <unistd.h>
@@ -25,14 +25,16 @@
#include <async_safe/log.h>
#include <cutils/sockets.h>
-#include "debuggerd/protocol.h"
-#include "debuggerd/util.h"
+#include "protocol.h"
+#include "util.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));
+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/debuggerd/util.cpp b/debuggerd/util.cpp
index 32d2f18..c6a997b 100644
--- a/debuggerd/util.cpp
+++ b/debuggerd/util.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "debuggerd/util.h"
+#include "util.h"
#include <sys/socket.h>
@@ -22,7 +22,7 @@
#include <android-base/unique_fd.h>
#include <cutils/sockets.h>
-#include <debuggerd/protocol.h>
+#include "protocol.h"
using android::base::unique_fd;
diff --git a/debuggerd/include/debuggerd/util.h b/debuggerd/util.h
similarity index 100%
rename from debuggerd/include/debuggerd/util.h
rename to debuggerd/util.h
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 8a6877a..3e890c7 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -118,6 +118,7 @@
{ "boot", "boot.img", "boot.sig", "boot", false, false },
{ nullptr, "boot_other.img", "boot.sig", "boot", true, true },
{ "dtbo", "dtbo.img", "dtbo.sig", "dtbo", true, false },
+ { "dts", "dt.img", "dt.sig", "dts", true, false },
{ "recovery", "recovery.img", "recovery.sig", "recovery", true, false },
{ "system", "system.img", "system.sig", "system", false, false },
{ nullptr, "system_other.img", "system.sig", "system", true, true },
@@ -1259,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);
}
@@ -1765,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");
@@ -1775,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 c21139e..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;
}
@@ -486,8 +506,11 @@
return nullptr;
}
- AvbSlotVerifyResult verify_result = avb_ops->AvbSlotVerify(
- fs_mgr_get_slot_suffix(), avb_verifier->IsDeviceUnlocked(), &avb_handle->avb_slot_data_);
+ AvbSlotVerifyFlags flags = avb_verifier->IsDeviceUnlocked()
+ ? AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR
+ : AVB_SLOT_VERIFY_FLAGS_NONE;
+ AvbSlotVerifyResult verify_result =
+ avb_ops->AvbSlotVerify(fs_mgr_get_slot_suffix(), flags, &avb_handle->avb_slot_data_);
// Only allow two verify results:
// - AVB_SLOT_VERIFY_RESULT_OK.
diff --git a/fs_mgr/fs_mgr_avb_ops.cpp b/fs_mgr/fs_mgr_avb_ops.cpp
index 8feeb53..512839b 100644
--- a/fs_mgr/fs_mgr_avb_ops.cpp
+++ b/fs_mgr/fs_mgr_avb_ops.cpp
@@ -177,13 +177,15 @@
}
AvbSlotVerifyResult FsManagerAvbOps::AvbSlotVerify(const std::string& ab_suffix,
- bool allow_verification_error,
+ AvbSlotVerifyFlags flags,
AvbSlotVerifyData** out_data) {
// Invokes avb_slot_verify() to load and verify all vbmeta images.
// Sets requested_partitions to nullptr as it's to copy the contents
// of HASH partitions into handle>avb_slot_data_, which is not required as
// fs_mgr only deals with HASHTREE partitions.
const char* requested_partitions[] = {nullptr};
- return avb_slot_verify(&avb_ops_, requested_partitions, ab_suffix.c_str(),
- allow_verification_error, out_data);
+ // The |hashtree_error_mode| field doesn't matter as it only
+ // influences the generated kernel cmdline parameters.
+ return avb_slot_verify(&avb_ops_, requested_partitions, ab_suffix.c_str(), flags,
+ AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, out_data);
}
diff --git a/fs_mgr/fs_mgr_priv_avb_ops.h b/fs_mgr/fs_mgr_priv_avb_ops.h
index a6b52e4..d1ef2e9 100644
--- a/fs_mgr/fs_mgr_priv_avb_ops.h
+++ b/fs_mgr/fs_mgr_priv_avb_ops.h
@@ -56,7 +56,7 @@
AvbIOResult ReadFromPartition(const char* partition, int64_t offset, size_t num_bytes,
void* buffer, size_t* out_num_read);
- AvbSlotVerifyResult AvbSlotVerify(const std::string& ab_suffix, bool allow_verification_error,
+ AvbSlotVerifyResult AvbSlotVerify(const std::string& ab_suffix, AvbSlotVerifyFlags flags,
AvbSlotVerifyData** out_data);
private:
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 617a809..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,35 +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_COMPATIBILITY_SUITE := device-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/AndroidTest.xml b/init/AndroidTest.xml
deleted file mode 100644
index 3de69ed..0000000
--- a/init/AndroidTest.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<configuration description="Config for init_tests">
- <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
- <option name="cleanup" value="true" />
- <option name="push" value="init_tests->/data/local/tmp/init_tests" />
- </target_preparer>
- <option name="test-suite-tag" value="apct" />
- <test class="com.android.tradefed.testtype.GTest" >
- <option name="native-test-device-path" value="/data/local/tmp" />
- <option name="module-name" value="init_tests" />
- </test>
-</configuration>
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/libappfuse/FuseBuffer.cc b/libappfuse/FuseBuffer.cc
index b42a049..653e96b 100644
--- a/libappfuse/FuseBuffer.cc
+++ b/libappfuse/FuseBuffer.cc
@@ -119,7 +119,12 @@
return ResultOrAgain::kFailure;
}
}
- CHECK(static_cast<uint32_t>(result) == header.len);
+
+ if (static_cast<unsigned int>(result) != header.len) {
+ LOG(ERROR) << "Written bytes " << result << " is different from length in header "
+ << header.len;
+ return ResultOrAgain::kFailure;
+ }
return ResultOrAgain::kSuccess;
}
}
@@ -141,8 +146,8 @@
}
constexpr int kMaxMessageSize = sizeof(FuseBuffer);
- if (setsockopt(fds[0], SOL_SOCKET, SO_SNDBUF, &kMaxMessageSize, sizeof(int)) != 0 ||
- setsockopt(fds[1], SOL_SOCKET, SO_SNDBUF, &kMaxMessageSize, sizeof(int)) != 0) {
+ if (setsockopt(fds[0], SOL_SOCKET, SO_SNDBUFFORCE, &kMaxMessageSize, sizeof(int)) != 0 ||
+ setsockopt(fds[1], SOL_SOCKET, SO_SNDBUFFORCE, &kMaxMessageSize, sizeof(int)) != 0) {
PLOG(ERROR) << "Failed to update buffer size for socket";
return false;
}
diff --git a/libcrypto_utils/Android.bp b/libcrypto_utils/Android.bp
index f2560e6..4a5f2a7 100644
--- a/libcrypto_utils/Android.bp
+++ b/libcrypto_utils/Android.bp
@@ -16,6 +16,7 @@
cc_library {
name: "libcrypto_utils",
+ vendor_available: true,
host_supported: true,
srcs: [
"android_pubkey.c",
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 ea99595..221dea2 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 },
@@ -196,18 +186,12 @@
// Support hostapd administering a network interface.
{ 00755, AID_WIFI, AID_WIFI, CAP_MASK_LONG(CAP_NET_ADMIN) |
CAP_MASK_LONG(CAP_NET_RAW),
- "system/vendor/bin/hostapd" },
- { 00755, AID_WIFI, AID_WIFI, CAP_MASK_LONG(CAP_NET_ADMIN) |
- CAP_MASK_LONG(CAP_NET_RAW),
"vendor/bin/hostapd" },
// Support Bluetooth legacy hal accessing /sys/class/rfkill
// 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.
@@ -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/include/private/android_filesystem_config.h b/libcutils/include/private/android_filesystem_config.h
index 48b50a5..02141d6 100644
--- a/libcutils/include/private/android_filesystem_config.h
+++ b/libcutils/include/private/android_filesystem_config.h
@@ -130,6 +130,7 @@
#define AID_MEDIA_OBB 1059 /* GID for OBB files on internal media storage */
#define AID_ESE 1060 /* embedded secure element (eSE) subsystem */
#define AID_OTA_UPDATE 1061 /* resource tracking UID for OTA updates */
+#define AID_AUTOMOTIVE_EVS 1062 /* Automotive rear and surround view system */
/* Changes to this file must be made in AOSP, *not* in internal branches. */
#define AID_SHELL 2000 /* adb and debug shell user */
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 da8afe1..26a041a 100644
--- a/libmetricslogger/Android.bp
+++ b/libmetricslogger/Android.bp
@@ -23,6 +23,7 @@
// 524291 corresponds to sysui_histogram, from
// frameworks/base/core/java/com/android/internal/logging/EventLogTags.logtags
"-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 26aa189..36e124d 100644
--- a/libmetricslogger/include/metricslogger/metrics_logger.h
+++ b/libmetricslogger/include/metricslogger/metrics_logger.h
@@ -24,13 +24,18 @@
// 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_HISTOGRAM = 804,
+ LOGBUILDER_CATEGORY = 757,
+ LOGBUILDER_NAME = 799,
+ LOGBUILDER_BUCKET = 801,
+ LOGBUILDER_VALUE = 802,
+ LOGBUILDER_COUNTER = 803,
+ LOGBUILDER_HISTOGRAM = 804,
};
} // namespace metricslogger
diff --git a/libmetricslogger/metrics_logger.cpp b/libmetricslogger/metrics_logger.cpp
index 0d08f5c..6f65e10 100644
--- a/libmetricslogger/metrics_logger.cpp
+++ b/libmetricslogger/metrics_logger.cpp
@@ -25,12 +25,16 @@
// 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 << LOGBUILDER_CATEGORY << LOGBUILDER_HISTOGRAM
- << LOGBUILDER_NAME << event
- << LOGBUILDER_BUCKET << data
- << LOGBUILDER_VALUE << 1
- << 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/logcat/logcat.cpp b/logcat/logcat.cpp
index 64d1d2f..e9ef9cc 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -530,6 +530,7 @@
" process — Display PID only.\n"
" raw — Display the raw log message, with no other metadata fields.\n"
" tag — Display the priority/tag only.\n"
+ " thread — Display priority, PID and TID of process issuing the message.\n"
" threadtime — Display the date, invocation time, priority, tag, and the PID\n"
" and TID of the thread issuing the message. (the default format).\n"
" time — Display the date, invocation time, priority/tag, and PID of the\n"
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 8b609cb..7498325 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;
@@ -196,6 +202,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) {
@@ -607,6 +618,33 @@
}
};
+// Determine if watermark is within pruneMargin + 1s from the end of the list,
+// the caller will use this result to set an internal busy flag indicating
+// the prune operation could not be completed because a reader is blocking
+// the request.
+bool LogBuffer::isBusy(log_time watermark) {
+ LogBufferElementCollection::iterator ei = mLogElements.end();
+ --ei;
+ return watermark < ((*ei)->getRealTime() - pruneMargin - log_time(1, 0));
+}
+
+// If the selected reader is blocking our pruning progress, decide on
+// what kind of mitigation is necessary to unblock the situation.
+void LogBuffer::kickMe(LogTimeEntry* me, log_id_t id, unsigned long pruneRows) {
+ if (stats.sizes(id) > (2 * log_buffer_size(id))) { // +100%
+ // A misbehaving or slow reader has its connection
+ // dropped if we hit too much memory pressure.
+ me->release_Locked();
+ } else if (me->mTimeout.tv_sec || me->mTimeout.tv_nsec) {
+ // Allow a blocked WRAP timeout reader to
+ // trigger and start reporting the log data.
+ me->triggerReader_Locked();
+ } else {
+ // tell slow reader to skip entries to catch up
+ me->triggerSkip_Locked(id, pruneRows);
+ }
+}
+
// prune "pruneRows" of type "id" from the buffer.
//
// This garbage collection task is used to expire log entries. It is called to
@@ -697,12 +735,8 @@
}
if (oldest && (watermark <= element->getRealTime())) {
- busy = true;
- if (oldest->mTimeout.tv_sec || oldest->mTimeout.tv_nsec) {
- oldest->triggerReader_Locked();
- } else {
- oldest->triggerSkip_Locked(id, pruneRows);
- }
+ busy = isBusy(watermark);
+ if (busy) kickMe(oldest, id, pruneRows);
break;
}
@@ -789,10 +823,8 @@
LogBufferElement* element = *it;
if (oldest && (watermark <= element->getRealTime())) {
- busy = true;
- if (oldest->mTimeout.tv_sec || oldest->mTimeout.tv_nsec) {
- oldest->triggerReader_Locked();
- }
+ busy = isBusy(watermark);
+ // Do not let chatty eliding trigger any reader mitigation
break;
}
@@ -943,19 +975,8 @@
}
if (oldest && (watermark <= element->getRealTime())) {
- busy = true;
- if (whitelist) {
- break;
- }
-
- if (stats.sizes(id) > (2 * log_buffer_size(id))) {
- // kick a misbehaving log reader client off the island
- oldest->release_Locked();
- } else if (oldest->mTimeout.tv_sec || oldest->mTimeout.tv_nsec) {
- oldest->triggerReader_Locked();
- } else {
- oldest->triggerSkip_Locked(id, pruneRows);
- }
+ busy = isBusy(watermark);
+ if (!whitelist && busy) kickMe(oldest, id, pruneRows);
break;
}
@@ -987,15 +1008,8 @@
}
if (oldest && (watermark <= element->getRealTime())) {
- busy = true;
- if (stats.sizes(id) > (2 * log_buffer_size(id))) {
- // kick a misbehaving log reader client off the island
- oldest->release_Locked();
- } else if (oldest->mTimeout.tv_sec || oldest->mTimeout.tv_nsec) {
- oldest->triggerReader_Locked();
- } else {
- oldest->triggerSkip_Locked(id, pruneRows);
- }
+ busy = isBusy(watermark);
+ if (busy) kickMe(oldest, id, pruneRows);
break;
}
@@ -1108,6 +1122,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;
}
@@ -1115,7 +1132,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
@@ -1141,10 +1158,6 @@
continue;
}
- if (element->getRealTime() <= start) {
- continue;
- }
-
// NB: calling out to another object with wrlock() held (safe)
if (filter) {
int ret = (*filter)(element, arg);
@@ -1171,10 +1184,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;
@@ -1182,7 +1195,7 @@
}
unlock();
- return max;
+ return curr;
}
std::string LogBuffer::formatStatistics(uid_t uid, pid_t pid,
diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h
index f0d6fcb..0942987 100644
--- a/logd/LogBuffer.h
+++ b/logd/LogBuffer.h
@@ -184,6 +184,9 @@
static const log_time pruneMargin;
void maybePrune(log_id_t id);
+ bool isBusy(log_time watermark);
+ void kickMe(LogTimeEntry* me, log_id_t id, unsigned long pruneRows);
+
bool prune(log_id_t id, unsigned long pruneRows, uid_t uid = AID_ROOT);
LogBufferElementCollection::iterator erase(
LogBufferElementCollection::iterator it, bool coalesce = false);
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index a1b69e3..773ca06 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -77,9 +77,12 @@
# to load the compiled *.so file and libmediandk.so can be used here.
###############################################################################
namespace.rs.isolated = true
-namespace.rs.search.paths = /system/${LIB}/vndk-sp:/vendor/${LIB}
+namespace.rs.search.paths = /vendor/${LIB}/vndk-sp:/system/${LIB}/vndk-sp:/vendor/${LIB}
namespace.rs.permitted.paths = /vendor/${LIB}:/data
+namespace.rs.asan.search.paths = /data/asan/vendor/${LIB}/vndk-sp:/vendor/${LIB}/vndk-sp:/data/asan/system/${LIB}/vndk-sp:/system/${LIB}/vndk-sp:/data/asan/vendor/${LIB}:/vendor/${LIB}
+namespace.rs.asan.permitted.paths = /data/asan/vendor/${LIB}:/vendor/${LIB}:/data
+
namespace.rs.links = default,vndk
namespace.rs.link.default.shared_libs = libc.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libEGL.so:libsync.so:libGLESv1_CM.so:libGLESv2.so:libmediandk.so:libui.so:libvndksupport.so
namespace.rs.link.vndk.shared_libs = android.hardware.renderscript@1.0.so:android.hardware.graphics.allocator@2.0.so:android.hardware.graphics.mapper@2.0.so:android.hardware.graphics.common@1.0.so:libhwbinder.so:libbase.so:libcutils.so:libhardware.so:libhidlbase.so:libhidltransport.so:libutils.so:libc++.so:libz.so
@@ -90,10 +93,10 @@
# This namespace is exclusively for vndk-sp libs.
###############################################################################
namespace.vndk.isolated = true
-namespace.vndk.search.paths = /system/${LIB}/vndk-sp:/vendor/${LIB}
+namespace.vndk.search.paths = /vendor/${LIB}/vndk-sp:/system/${LIB}/vndk-sp:/vendor/${LIB}
namespace.vndk.permitted.paths = /vendor/${LIB}/hw:/vendor/${LIB}/egl
-namespace.vndk.asan.search.paths = /data/asan/system/${LIB}/vndk-sp:/system/${LIB}/vndk-sp:/data/asan/vendor/${LIB}:/vendor/${LIB}
+namespace.vndk.asan.search.paths = /data/asan/vendor/${LIB}/vndk-sp:/vendor/${LIB}/vndk-sp:/data/asan/system/${LIB}/vndk-sp:/system/${LIB}/vndk-sp:/data/asan/vendor/${LIB}:/vendor/${LIB}
namespace.vndk.asan.permitted.paths = /data/asan/vendor/${LIB}/hw:/vendor/${LIB}/hw:/data/asan/vendor/${LIB}/egl:/vendor/${LIB}/egl
# When these NDK libs are required inside this namespace, then it is redirected
@@ -105,6 +108,6 @@
[vendor]
namespace.default.isolated = false
-namespace.default.search.paths = /vendor/${LIB}:/system/${LIB}/vndk-sp:/system/${LIB}
+namespace.default.search.paths = /vendor/${LIB}:/vendor/${LIB}/vndk-sp:/system/${LIB}/vndk-sp:/system/${LIB}
-namespace.default.asan.search.paths = /data/asan/vendor/${LIB}:/vendor/${LIB}:/data/asan/system/${LIB}/vndk-sp:/system/${LIB}/vndk-sp:/data/asan/system/${LIB}:/system/${LIB}
+namespace.default.asan.search.paths = /data/asan/vendor/${LIB}:/vendor/${LIB}:/data/asan/vendor/${LIB}/vndk-sp:/vendor/${LIB}/vndk-sp:/data/asan/system/${LIB}/vndk-sp:/system/${LIB}/vndk-sp:/data/asan/system/${LIB}:/system/${LIB}
diff --git a/rootdir/init.rc b/rootdir/init.rc
index a224d5e..c006d80 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -7,6 +7,7 @@
import /init.environ.rc
import /init.usb.rc
import /init.${ro.hardware}.rc
+import /vendor/etc/init/hw/init.${ro.hardware}.rc
import /init.usb.configfs.rc
import /init.${ro.zygote}.rc
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)