Merge "Add basic tests for ashmem"
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 0000000..949a7fe
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1,22 @@
+// 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.
+
+ndk_headers {
+ name: "liblog_headers",
+ from: "include/android",
+ to: "android",
+ srcs: ["include/android/log.h"],
+}
+
+optional_subdirs = ["*"]
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 31e60ca..5b5eff4 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -59,3 +59,4 @@
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/hw/gatekeeper.$(TARGET_DEVICE).so)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib64/hw/gatekeeper.$(TARGET_DEVICE).so)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/vendor)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/init.rc)
diff --git a/adb/Android.mk b/adb/Android.mk
index b2a0dc4..0114ca3 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -62,6 +62,7 @@
adb_listeners_test.cpp \
adb_utils_test.cpp \
fdevent_test.cpp \
+ socket_spec_test.cpp \
socket_test.cpp \
sysdeps_test.cpp \
sysdeps/stat_test.cpp \
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 056dbef..9ae3f1c 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -48,9 +48,9 @@
#include "transport.h"
#if !ADB_HOST
-#include <cutils/properties.h>
#include <sys/capability.h>
#include <sys/mount.h>
+#include <android-base/properties.h>
#endif
std::string adb_version() {
@@ -200,11 +200,9 @@
"ro.product.device",
};
- for (const auto& prop_name : cnxn_props) {
- char value[PROPERTY_VALUE_MAX];
- property_get(prop_name, value, "");
- connection_properties.push_back(
- android::base::StringPrintf("%s=%s", prop_name, value));
+ for (const auto& prop : cnxn_props) {
+ std::string value = std::string(prop) + "=" + android::base::GetProperty(prop, "");
+ connection_properties.push_back(value);
}
#endif
diff --git a/adb/adb_auth_host.cpp b/adb/adb_auth_host.cpp
index 8366549..072c7f5 100644
--- a/adb/adb_auth_host.cpp
+++ b/adb/adb_auth_host.cpp
@@ -45,7 +45,6 @@
#include "adb_auth.h"
#include "adb_utils.h"
#include "sysdeps.h"
-#include "sysdeps/mutex.h"
static std::mutex& g_keys_mutex = *new std::mutex;
static std::map<std::string, std::shared_ptr<RSA>>& g_keys =
diff --git a/adb/adb_trace.cpp b/adb/adb_trace.cpp
index 62900c0..369dec9 100644
--- a/adb/adb_trace.cpp
+++ b/adb/adb_trace.cpp
@@ -27,7 +27,7 @@
#include "adb.h"
#if !ADB_HOST
-#include <cutils/properties.h>
+#include <android-base/properties.h>
#endif
#if !ADB_HOST
@@ -88,19 +88,11 @@
return std::string(setting);
}
-#if !ADB_HOST
-std::string get_trace_setting_from_prop() {
- char buf[PROPERTY_VALUE_MAX];
- property_get("persist.adb.trace_mask", buf, "");
- return std::string(buf);
-}
-#endif
-
std::string get_trace_setting() {
#if ADB_HOST
return get_trace_setting_from_env();
#else
- return get_trace_setting_from_prop();
+ return android::base::GetProperty("persist.adb.trace_mask", "");
#endif
}
diff --git a/adb/adb_utils.cpp b/adb/adb_utils.cpp
index db39ef4..5a3b401 100644
--- a/adb/adb_utils.cpp
+++ b/adb/adb_utils.cpp
@@ -26,6 +26,7 @@
#include <unistd.h>
#include <algorithm>
+#include <mutex>
#include <vector>
#include <android-base/logging.h>
@@ -47,8 +48,6 @@
#include <pwd.h>
#endif
-ADB_MUTEX_DEFINE(basename_lock);
-ADB_MUTEX_DEFINE(dirname_lock);
#if defined(_WIN32)
constexpr char kNullFileName[] = "NUL";
@@ -102,13 +101,15 @@
}
std::string adb_basename(const std::string& path) {
+ static std::mutex& basename_lock = *new std::mutex();
+
// Copy path because basename may modify the string passed in.
std::string result(path);
// Use lock because basename() may write to a process global and return a
// pointer to that. Note that this locking strategy only works if all other
- // callers to dirname in the process also grab this same lock.
- adb_mutex_lock(&basename_lock);
+ // callers to basename in the process also grab this same lock.
+ std::lock_guard<std::mutex> lock(basename_lock);
// Note that if std::string uses copy-on-write strings, &str[0] will cause
// the copy to be made, so there is no chance of us accidentally writing to
@@ -119,19 +120,19 @@
// before leaving the lock.
result.assign(name);
- adb_mutex_unlock(&basename_lock);
-
return result;
}
std::string adb_dirname(const std::string& path) {
+ static std::mutex& dirname_lock = *new std::mutex();
+
// Copy path because dirname may modify the string passed in.
std::string result(path);
// Use lock because dirname() may write to a process global and return a
// pointer to that. Note that this locking strategy only works if all other
// callers to dirname in the process also grab this same lock.
- adb_mutex_lock(&dirname_lock);
+ std::lock_guard<std::mutex> lock(dirname_lock);
// Note that if std::string uses copy-on-write strings, &str[0] will cause
// the copy to be made, so there is no chance of us accidentally writing to
@@ -142,8 +143,6 @@
// before leaving the lock.
result.assign(parent);
- adb_mutex_unlock(&dirname_lock);
-
return result;
}
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
index 571c227..4ec0fc2 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -129,7 +129,9 @@
// Start a new session for the daemon. Do this here instead of after the fork so
// that a ctrl-c between the "starting server" and "done starting server" messages
// gets a chance to terminate the server.
- if (setsid() == -1) {
+ // setsid will fail with EPERM if it's already been a lead process of new session.
+ // Ignore such error.
+ if (setsid() == -1 && errno != EPERM) {
fatal("setsid() failed: %s", strerror(errno));
}
#endif
@@ -170,7 +172,6 @@
}
int main(int argc, char** argv) {
- adb_sysdeps_init();
adb_trace_init(argv);
return adb_commandline(argc - 1, const_cast<const char**>(argv + 1));
}
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index 77c5f96..a9185a0 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -37,6 +37,7 @@
#include <android-base/file.h>
#include <android-base/logging.h>
+#include <android-base/parseint.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
@@ -1549,23 +1550,32 @@
// If -L, -H, or -P are specified, ignore environment variables.
// Otherwise, prefer ADB_SERVER_SOCKET over ANDROID_ADB_SERVER_ADDRESS/PORT.
- if (!(server_host_str || server_port_str || server_socket_str)) {
- server_socket_str = server_socket_str ? server_socket_str : getenv("ADB_SERVER_SOCKET");
+ if (!server_host_str && !server_port_str && !server_socket_str) {
+ server_socket_str = getenv("ADB_SERVER_SOCKET");
}
if (!server_socket_str) {
// tcp:1234 and tcp:localhost:1234 are different with -a, so don't default to localhost
server_host_str = server_host_str ? server_host_str : getenv("ANDROID_ADB_SERVER_ADDRESS");
- long server_port = DEFAULT_ADB_PORT;
+ int server_port = DEFAULT_ADB_PORT;
server_port_str = server_port_str ? server_port_str : getenv("ANDROID_ADB_SERVER_PORT");
+ if (server_port_str && strlen(server_port_str) > 0) {
+ if (!android::base::ParseInt(server_port_str, &server_port, 1, 65535)) {
+ fprintf(stderr,
+ "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive"
+ " number less than 65535. Got \"%s\"\n",
+ server_port_str);
+ exit(1);
+ }
+ }
int rc;
char* temp;
if (server_host_str) {
- rc = asprintf(&temp, "tcp:%s:%ld", server_host_str, server_port);
+ rc = asprintf(&temp, "tcp:%s:%d", server_host_str, server_port);
} else {
- rc = asprintf(&temp, "tcp:%ld", server_port);
+ rc = asprintf(&temp, "tcp:%d", server_port);
}
if (rc < 0) {
fatal("failed to allocate server socket specification");
diff --git a/adb/daemon/main.cpp b/adb/daemon/main.cpp
index b54243e..094988a 100644
--- a/adb/daemon/main.cpp
+++ b/adb/daemon/main.cpp
@@ -29,11 +29,11 @@
#include <android-base/logging.h>
#include <android-base/macros.h>
+#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <libminijail.h>
#include <scoped_minijail.h>
-#include "cutils/properties.h"
#include "debuggerd/client.h"
#include "private/android_filesystem_config.h"
#include "selinux/android.h"
@@ -48,9 +48,7 @@
static void drop_capabilities_bounding_set_if_needed(struct minijail *j) {
#if defined(ALLOW_ADBD_ROOT)
- char value[PROPERTY_VALUE_MAX];
- property_get("ro.debuggable", value, "");
- if (strcmp(value, "1") == 0) {
+ if (android::base::GetBoolProperty("ro.debuggable", false)) {
return;
}
#endif
@@ -59,8 +57,6 @@
static bool should_drop_privileges() {
#if defined(ALLOW_ADBD_ROOT)
- char value[PROPERTY_VALUE_MAX];
-
// The properties that affect `adb root` and `adb unroot` are ro.secure and
// ro.debuggable. In this context the names don't make the expected behavior
// particularly obvious.
@@ -71,24 +67,19 @@
//
// ro.secure:
// Drop privileges by default. Set to 1 on userdebug and user builds.
- property_get("ro.secure", value, "1");
- bool ro_secure = (strcmp(value, "1") == 0);
-
- property_get("ro.debuggable", value, "");
- bool ro_debuggable = (strcmp(value, "1") == 0);
+ bool ro_secure = android::base::GetBoolProperty("ro.secure", true);
+ bool ro_debuggable = android::base::GetBoolProperty("ro.debuggable", false);
// Drop privileges if ro.secure is set...
bool drop = ro_secure;
- property_get("service.adb.root", value, "");
- bool adb_root = (strcmp(value, "1") == 0);
- bool adb_unroot = (strcmp(value, "0") == 0);
-
// ... except "adb root" lets you keep privileges in a debuggable build.
+ std::string prop = android::base::GetProperty("service.adb.root", "");
+ bool adb_root = (prop == "1");
+ bool adb_unroot = (prop == "0");
if (ro_debuggable && adb_root) {
drop = false;
}
-
// ... and "adb unroot" lets you explicitly drop privileges.
if (adb_unroot) {
drop = true;
@@ -159,7 +150,7 @@
// descriptor will always be open.
adbd_cloexec_auth_socket();
- if (ALLOW_ADBD_NO_AUTH && property_get_bool("ro.adb.secure", 0) == 0) {
+ if (ALLOW_ADBD_NO_AUTH && !android::base::GetBoolProperty("ro.adb.secure", false)) {
auth_required = false;
}
@@ -187,14 +178,13 @@
// If one of these properties is set, also listen on that port.
// If one of the properties isn't set and we couldn't listen on usb, listen
// on the default port.
- char prop_port[PROPERTY_VALUE_MAX];
- property_get("service.adb.tcp.port", prop_port, "");
- if (prop_port[0] == '\0') {
- property_get("persist.adb.tcp.port", prop_port, "");
+ std::string prop_port = android::base::GetProperty("service.adb.tcp.port", "");
+ if (prop_port.empty()) {
+ prop_port = android::base::GetProperty("persist.adb.tcp.port", "");
}
int port;
- if (sscanf(prop_port, "%d", &port) == 1 && port > 0) {
+ if (sscanf(prop_port.c_str(), "%d", &port) == 1 && port > 0) {
D("using port=%d", port);
// Listen on TCP port specified by service.adb.tcp.port property.
local_init(port);
diff --git a/adb/mutex_list.h b/adb/mutex_list.h
deleted file mode 100644
index 4a188ee..0000000
--- a/adb/mutex_list.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* the list of mutexes used by adb */
-/* #ifndef __MUTEX_LIST_H
- * Do not use an include-guard. This file is included once to declare the locks
- * and once in win32 to actually do the runtime initialization.
- */
-#ifndef ADB_MUTEX
-#error ADB_MUTEX not defined when including this file
-#endif
-ADB_MUTEX(basename_lock)
-ADB_MUTEX(dirname_lock)
-ADB_MUTEX(transport_lock)
-#if ADB_HOST
-ADB_MUTEX(local_transports_lock)
-#endif
-ADB_MUTEX(usb_lock)
-
-#undef ADB_MUTEX
diff --git a/adb/remount_service.cpp b/adb/remount_service.cpp
index 8f1c9b0..5ca73cc 100644
--- a/adb/remount_service.cpp
+++ b/adb/remount_service.cpp
@@ -29,10 +29,11 @@
#include <string>
+#include <android-base/properties.h>
+
#include "adb.h"
#include "adb_io.h"
#include "adb_utils.h"
-#include "cutils/properties.h"
#include "fs_mgr.h"
// Returns the device used to mount a directory in /proc/mounts.
@@ -53,10 +54,7 @@
// Returns the device used to mount a directory in the fstab.
static std::string find_fstab_mount(const char* dir) {
- char propbuf[PROPERTY_VALUE_MAX];
-
- property_get("ro.hardware", propbuf, "");
- std::string fstab_filename = std::string("/fstab.") + propbuf;
+ std::string fstab_filename = "/fstab." + android::base::GetProperty("ro.hardware", "");
struct fstab* fstab = fs_mgr_read_fstab(fstab_filename.c_str());
struct fstab_rec* rec = fs_mgr_get_entry_for_mount_point(fstab, dir);
std::string dev = rec ? std::string(rec->blk_device) : "";
@@ -113,12 +111,8 @@
return;
}
- char prop_buf[PROPERTY_VALUE_MAX];
- property_get("partition.system.verified", prop_buf, "");
- bool system_verified = (strlen(prop_buf) > 0);
-
- property_get("partition.vendor.verified", prop_buf, "");
- bool vendor_verified = (strlen(prop_buf) > 0);
+ bool system_verified = !(android::base::GetProperty("partition.system.verified", "").empty());
+ bool vendor_verified = !(android::base::GetProperty("partition.vendor.verified", "").empty());
if (system_verified || vendor_verified) {
// Allow remount but warn of likely bad effects
@@ -136,9 +130,7 @@
}
bool success = true;
- property_get("ro.build.system_root_image", prop_buf, "");
- bool system_root = !strcmp(prop_buf, "true");
- if (system_root) {
+ if (android::base::GetBoolProperty("ro.build.system_root_image", false)) {
success &= remount_partition(fd, "/");
} else {
success &= remount_partition(fd, "/system");
diff --git a/adb/services.cpp b/adb/services.cpp
index 2207a3e..0c3dd00 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -39,7 +39,7 @@
#if !ADB_HOST
#include "cutils/android_reboot.h"
-#include "cutils/properties.h"
+#include <android-base/properties.h>
#endif
#include "adb.h"
@@ -73,15 +73,13 @@
WriteFdExactly(fd, "adbd is already running as root\n");
adb_close(fd);
} else {
- char value[PROPERTY_VALUE_MAX];
- property_get("ro.debuggable", value, "");
- if (strcmp(value, "1") != 0) {
+ if (!android::base::GetBoolProperty("ro.debuggable", false)) {
WriteFdExactly(fd, "adbd cannot run as root in production builds\n");
adb_close(fd);
return;
}
- property_set("service.adb.root", "1");
+ android::base::SetProperty("service.adb.root", "1");
WriteFdExactly(fd, "restarting adbd as root\n");
adb_close(fd);
}
@@ -92,7 +90,7 @@
WriteFdExactly(fd, "adbd not running as root\n");
adb_close(fd);
} else {
- property_set("service.adb.root", "0");
+ android::base::SetProperty("service.adb.root", "0");
WriteFdExactly(fd, "restarting adbd as non root\n");
adb_close(fd);
}
@@ -106,15 +104,13 @@
return;
}
- char value[PROPERTY_VALUE_MAX];
- snprintf(value, sizeof(value), "%d", port);
- property_set("service.adb.tcp.port", value);
+ android::base::SetProperty("service.adb.tcp.port", android::base::StringPrintf("%d", port));
WriteFdFmt(fd, "restarting in TCP mode port: %d\n", port);
adb_close(fd);
}
void restart_usb_service(int fd, void *cookie) {
- property_set("service.adb.tcp.port", "0");
+ android::base::SetProperty("service.adb.tcp.port", "0");
WriteFdExactly(fd, "restarting in USB mode\n");
adb_close(fd);
}
@@ -155,16 +151,9 @@
sync();
- char property_val[PROPERTY_VALUE_MAX];
- int ret = snprintf(property_val, sizeof(property_val), "reboot,%s", reboot_arg);
- if (ret >= static_cast<int>(sizeof(property_val))) {
- WriteFdFmt(fd, "reboot string too long: %d\n", ret);
- return false;
- }
-
- ret = property_set(ANDROID_RB_PROPERTY, property_val);
- if (ret < 0) {
- WriteFdFmt(fd, "reboot failed: %d\n", ret);
+ std::string reboot_string = android::base::StringPrintf("reboot,%s", reboot_arg);
+ if (!android::base::SetProperty(ANDROID_RB_PROPERTY, reboot_string)) {
+ WriteFdFmt(fd, "reboot (%s) failed\n", reboot_string.c_str());
return false;
}
diff --git a/adb/set_verity_enable_state_service.cpp b/adb/set_verity_enable_state_service.cpp
index f5188e9..ae628e4 100644
--- a/adb/set_verity_enable_state_service.cpp
+++ b/adb/set_verity_enable_state_service.cpp
@@ -24,16 +24,17 @@
#include <stdio.h>
#include <sys/stat.h>
-#include "cutils/properties.h"
+#include "android-base/properties.h"
+#include "android-base/stringprintf.h"
#include "adb.h"
#include "adb_io.h"
+#include "adb_unique_fd.h"
#include "fs_mgr.h"
#include "remount_service.h"
#include "fec/io.h"
-#define FSTAB_PREFIX "/fstab."
struct fstab *fstab;
#ifdef ALLOW_ADBD_DISABLE_VERITY
@@ -88,56 +89,46 @@
return 0;
}
-void set_verity_enabled_state_service(int fd, void* cookie)
-{
+void set_verity_enabled_state_service(int fd, void* cookie) {
+ unique_fd closer(fd);
+
bool enable = (cookie != NULL);
- if (kAllowDisableVerity) {
- char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)];
- char propbuf[PROPERTY_VALUE_MAX];
- int i;
- bool any_changed = false;
-
- property_get("ro.secure", propbuf, "0");
- if (strcmp(propbuf, "1")) {
- WriteFdFmt(fd, "verity not enabled - ENG build\n");
- goto errout;
- }
-
- property_get("ro.debuggable", propbuf, "0");
- if (strcmp(propbuf, "1")) {
- WriteFdFmt(fd, "verity cannot be disabled/enabled - USER build\n");
- goto errout;
- }
-
- property_get("ro.hardware", propbuf, "");
- snprintf(fstab_filename, sizeof(fstab_filename), FSTAB_PREFIX"%s",
- propbuf);
-
- fstab = fs_mgr_read_fstab(fstab_filename);
- if (!fstab) {
- WriteFdFmt(fd, "Failed to open %s\nMaybe run adb root?\n", fstab_filename);
- goto errout;
- }
-
- /* Loop through entries looking for ones that vold manages */
- for (i = 0; i < fstab->num_entries; i++) {
- if(fs_mgr_is_verified(&fstab->recs[i])) {
- if (!set_verity_enabled_state(fd, fstab->recs[i].blk_device,
- fstab->recs[i].mount_point,
- enable)) {
- any_changed = true;
- }
- }
- }
-
- if (any_changed) {
- WriteFdFmt(fd, "Now reboot your device for settings to take effect\n");
- }
- } else {
+ if (!kAllowDisableVerity) {
WriteFdFmt(fd, "%s-verity only works for userdebug builds\n",
enable ? "enable" : "disable");
}
-errout:
- adb_close(fd);
+ if (!android::base::GetBoolProperty("ro.secure", false)) {
+ WriteFdFmt(fd, "verity not enabled - ENG build\n");
+ return;
+ }
+
+ if (!android::base::GetBoolProperty("ro.debuggable", false)) {
+ WriteFdFmt(fd, "verity cannot be disabled/enabled - USER build\n");
+ return;
+ }
+
+ std::string fstab_filename = "/fstab." + android::base::GetProperty("ro.hardware", "");
+
+ fstab = fs_mgr_read_fstab(fstab_filename.c_str());
+ if (!fstab) {
+ WriteFdFmt(fd, "Failed to open %s\nMaybe run adb root?\n", fstab_filename.c_str());
+ return;
+ }
+
+ // Loop through entries looking for ones that vold manages.
+ bool any_changed = false;
+ for (int i = 0; i < fstab->num_entries; i++) {
+ if (fs_mgr_is_verified(&fstab->recs[i])) {
+ if (!set_verity_enabled_state(fd, fstab->recs[i].blk_device,
+ fstab->recs[i].mount_point,
+ enable)) {
+ any_changed = true;
+ }
+ }
+ }
+
+ if (any_changed) {
+ WriteFdFmt(fd, "Now reboot your device for settings to take effect\n");
+ }
}
diff --git a/adb/shell_service.cpp b/adb/shell_service.cpp
index 01e206a..b0b31f1 100644
--- a/adb/shell_service.cpp
+++ b/adb/shell_service.cpp
@@ -493,10 +493,10 @@
// We also need to close the pipes connected to the child process
// so that if it ignores SIGHUP and continues to write data it
// won't fill up the pipe and block.
- stdinout_sfd_.clear();
- stderr_sfd_.clear();
+ stdinout_sfd_.reset();
+ stderr_sfd_.reset();
}
- dead_sfd->clear();
+ dead_sfd->reset();
}
}
}
diff --git a/adb/socket_spec.cpp b/adb/socket_spec.cpp
index 18e6e6d..14eb16b 100644
--- a/adb/socket_spec.cpp
+++ b/adb/socket_spec.cpp
@@ -20,6 +20,8 @@
#include <unordered_map>
#include <vector>
+#include <android-base/parseint.h>
+#include <android-base/parsenetaddress.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <cutils/sockets.h>
@@ -62,55 +64,47 @@
{ "localfilesystem", { ANDROID_SOCKET_NAMESPACE_FILESYSTEM, !ADB_WINDOWS } },
});
-static bool parse_tcp_spec(const std::string& spec, std::string* hostname, int* port,
+bool parse_tcp_socket_spec(const std::string& spec, std::string* hostname, int* port,
std::string* error) {
- std::vector<std::string> fragments = android::base::Split(spec, ":");
- if (fragments.size() == 1 || fragments.size() > 3) {
- *error = StringPrintf("invalid tcp specification: '%s'", spec.c_str());
- return false;
- }
-
- if (fragments[0] != "tcp") {
+ if (!StartsWith(spec, "tcp:")) {
*error = StringPrintf("specification is not tcp: '%s'", spec.c_str());
return false;
}
- // strtol accepts leading whitespace.
- const std::string& port_str = fragments.back();
- if (port_str.empty() || port_str[0] < '0' || port_str[0] > '9') {
- *error = StringPrintf("invalid port '%s'", port_str.c_str());
- return false;
- }
+ std::string hostname_value;
+ int port_value;
- char* parsed_end;
- long parsed_port = strtol(port_str.c_str(), &parsed_end, 10);
- if (*parsed_end != '\0') {
- *error = StringPrintf("trailing chars in port: '%s'", port_str.c_str());
- return false;
- }
- if (parsed_port > 65535) {
- *error = StringPrintf("invalid port %ld", parsed_port);
- return false;
- }
-
- // tcp:123 is valid, tcp::123 isn't.
- if (fragments.size() == 2) {
- // Empty hostname.
- if (hostname) {
- *hostname = "";
- }
- } else {
- if (fragments[1].empty()) {
- *error = StringPrintf("empty host in '%s'", spec.c_str());
+ // If the spec is tcp:<port>, parse it ourselves.
+ // Otherwise, delegate to android::base::ParseNetAddress.
+ if (android::base::ParseInt(&spec[4], &port_value)) {
+ // Do the range checking ourselves, because ParseInt rejects 'tcp:65536' and 'tcp:foo:1234'
+ // identically.
+ if (port_value < 0 || port_value > 65535) {
+ *error = StringPrintf("bad port number '%d'", port_value);
return false;
}
- if (hostname) {
- *hostname = fragments[1];
+ } else {
+ std::string addr = spec.substr(4);
+ port_value = -1;
+
+ // FIXME: ParseNetAddress rejects port 0. This currently doesn't hurt, because listening
+ // on an address that isn't 'localhost' is unsupported.
+ if (!android::base::ParseNetAddress(addr, &hostname_value, &port_value, nullptr, error)) {
+ return false;
}
+
+ if (port_value == -1) {
+ *error = StringPrintf("missing port in specification: '%s'", spec.c_str());
+ return false;
+ }
+ }
+
+ if (hostname) {
+ *hostname = std::move(hostname_value);
}
if (port) {
- *port = parsed_port;
+ *port = port_value;
}
return true;
@@ -141,7 +135,7 @@
std::string error;
std::string hostname;
- if (!parse_tcp_spec(spec, &hostname, nullptr, &error)) {
+ if (!parse_tcp_socket_spec(spec, &hostname, nullptr, &error)) {
return false;
}
return tcp_host_is_local(hostname);
@@ -151,7 +145,7 @@
if (StartsWith(spec, "tcp:")) {
std::string hostname;
int port;
- if (!parse_tcp_spec(spec, &hostname, &port, error)) {
+ if (!parse_tcp_socket_spec(spec, &hostname, &port, error)) {
return -1;
}
@@ -196,7 +190,7 @@
if (StartsWith(spec, "tcp:")) {
std::string hostname;
int port;
- if (!parse_tcp_spec(spec, &hostname, &port, error)) {
+ if (!parse_tcp_socket_spec(spec, &hostname, &port, error)) {
return -1;
}
diff --git a/adb/socket_spec.h b/adb/socket_spec.h
index 6302da5..6920e91 100644
--- a/adb/socket_spec.h
+++ b/adb/socket_spec.h
@@ -25,3 +25,7 @@
int socket_spec_connect(const std::string& spec, std::string* error);
int socket_spec_listen(const std::string& spec, std::string* error,
int* resolved_tcp_port = nullptr);
+
+// Exposed for testing.
+bool parse_tcp_socket_spec(const std::string& spec, std::string* hostname, int* port,
+ std::string* error);
diff --git a/adb/socket_spec_test.cpp b/adb/socket_spec_test.cpp
new file mode 100644
index 0000000..40ce21c
--- /dev/null
+++ b/adb/socket_spec_test.cpp
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+#include "socket_spec.h"
+
+#include <string>
+
+#include <gtest/gtest.h>
+
+TEST(socket_spec, parse_tcp_socket_spec) {
+ std::string hostname, error;
+ int port;
+ EXPECT_TRUE(parse_tcp_socket_spec("tcp:5037", &hostname, &port, &error));
+ EXPECT_EQ("", hostname);
+ EXPECT_EQ(5037, port);
+
+ // Bad ports:
+ EXPECT_FALSE(parse_tcp_socket_spec("tcp:", &hostname, &port, &error));
+ EXPECT_FALSE(parse_tcp_socket_spec("tcp:-1", &hostname, &port, &error));
+ EXPECT_FALSE(parse_tcp_socket_spec("tcp:65536", &hostname, &port, &error));
+
+ EXPECT_TRUE(parse_tcp_socket_spec("tcp:localhost:1234", &hostname, &port, &error));
+ EXPECT_EQ("localhost", hostname);
+ EXPECT_EQ(1234, port);
+
+ EXPECT_FALSE(parse_tcp_socket_spec("tcp:localhost", &hostname, &port, &error));
+ EXPECT_FALSE(parse_tcp_socket_spec("tcp:localhost:", &hostname, &port, &error));
+ EXPECT_FALSE(parse_tcp_socket_spec("tcp:localhost:-1", &hostname, &port, &error));
+ EXPECT_FALSE(parse_tcp_socket_spec("tcp:localhost:65536", &hostname, &port, &error));
+
+ // IPv6:
+ EXPECT_TRUE(parse_tcp_socket_spec("tcp:[::1]:1234", &hostname, &port, &error));
+ EXPECT_EQ("::1", hostname);
+ EXPECT_EQ(1234, port);
+
+ EXPECT_FALSE(parse_tcp_socket_spec("tcp:[::1]", &hostname, &port, &error));
+ EXPECT_FALSE(parse_tcp_socket_spec("tcp:[::1]:", &hostname, &port, &error));
+ EXPECT_FALSE(parse_tcp_socket_spec("tcp:[::1]:-1", &hostname, &port, &error));
+ EXPECT_FALSE(parse_tcp_socket_spec("tcp:::1", &hostname, &port, &error));
+ EXPECT_FALSE(parse_tcp_socket_spec("tcp:::1:1234", &hostname, &port, &error));
+}
diff --git a/adb/socket_test.cpp b/adb/socket_test.cpp
index 2bb01a3..5e79b5e 100644
--- a/adb/socket_test.cpp
+++ b/adb/socket_test.cpp
@@ -307,6 +307,17 @@
// Don't register a port unless it's all numbers and ends with ':'.
VerifySkipHostSerial(protocol + "foo:123", ":123");
VerifySkipHostSerial(protocol + "foo:123bar:baz", ":123bar:baz");
+
+ VerifySkipHostSerial(protocol + "100.100.100.100:5555:foo", ":foo");
+ VerifySkipHostSerial(protocol + "[0123:4567:89ab:CDEF:0:9:a:f]:5555:foo", ":foo");
+ VerifySkipHostSerial(protocol + "[::1]:5555:foo", ":foo");
+
+ // If we can't find both [] then treat it as a normal serial with [ in it.
+ VerifySkipHostSerial(protocol + "[0123:foo", ":foo");
+
+ // Don't be fooled by random IPv6 addresses in the command string.
+ VerifySkipHostSerial(protocol + "foo:ping [0123:4567:89ab:CDEF:0:9:a:f]:5555",
+ ":ping [0123:4567:89ab:CDEF:0:9:a:f]:5555");
}
}
diff --git a/adb/sockets.cpp b/adb/sockets.cpp
index 4ed1c45..b809c4f 100644
--- a/adb/sockets.cpp
+++ b/adb/sockets.cpp
@@ -31,12 +31,11 @@
#include <vector>
#if !ADB_HOST
-#include "cutils/properties.h"
+#include <android-base/properties.h>
#endif
#include "adb.h"
#include "adb_io.h"
-#include "sysdeps/mutex.h"
#include "transport.h"
static std::recursive_mutex& local_socket_list_lock = *new std::recursive_mutex();
@@ -417,12 +416,12 @@
D("LS(%d): bound to '%s' via %d", s->id, name, fd);
#if !ADB_HOST
- char debug[PROPERTY_VALUE_MAX];
+ bool debuggable = false;
if (!strncmp(name, "root:", 5)) {
- property_get("ro.debuggable", debug, "");
+ debuggable = android::base::GetBoolProperty("ro.debuggable", false);
}
- if ((!strncmp(name, "root:", 5) && getuid() != 0 && strcmp(debug, "1") == 0) ||
+ if ((!strncmp(name, "root:", 5) && getuid() != 0 && debuggable) ||
(!strncmp(name, "unroot:", 7) && getuid() == 0) ||
!strncmp(name, "usb:", 4) ||
!strncmp(name, "tcpip:", 6)) {
@@ -623,21 +622,32 @@
service += 4;
}
- char* first_colon = strchr(service, ':');
- if (!first_colon) {
+ // Check for an IPv6 address. `adb connect` creates the serial number from the canonical
+ // network address so it will always have the [] delimiters.
+ if (service[0] == '[') {
+ char* ipv6_end = strchr(service, ']');
+ if (ipv6_end != nullptr) {
+ service = ipv6_end;
+ }
+ }
+
+ // The next colon we find must either begin the port field or the command field.
+ char* colon_ptr = strchr(service, ':');
+ if (!colon_ptr) {
// No colon in service string.
return nullptr;
}
- char* serial_end = first_colon;
+ // If the next field is only decimal digits and ends with another colon, it's a port.
+ char* serial_end = colon_ptr;
if (isdigit(serial_end[1])) {
serial_end++;
while (*serial_end && isdigit(*serial_end)) {
serial_end++;
}
if (*serial_end != ':') {
- // Something other than numbers was found, reset the end.
- serial_end = first_colon;
+ // Something other than "<port>:" was found, this must be the command field instead.
+ serial_end = colon_ptr;
}
}
return serial_end;
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index 8d99722..3ed589c 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -97,27 +97,6 @@
return c == '\\' || c == '/';
}
-typedef CRITICAL_SECTION adb_mutex_t;
-
-#define ADB_MUTEX_DEFINE(x) adb_mutex_t x
-
-/* declare all mutexes */
-/* For win32, adb_sysdeps_init() will do the mutex runtime initialization. */
-#define ADB_MUTEX(x) extern adb_mutex_t x;
-#include "mutex_list.h"
-
-extern void adb_sysdeps_init(void);
-
-static __inline__ void adb_mutex_lock( adb_mutex_t* lock )
-{
- EnterCriticalSection( lock );
-}
-
-static __inline__ void adb_mutex_unlock( adb_mutex_t* lock )
-{
- LeaveCriticalSection( lock );
-}
-
typedef void (*adb_thread_func_t)(void* arg);
typedef HANDLE adb_thread_t;
@@ -476,27 +455,6 @@
return c == '/';
}
-typedef pthread_mutex_t adb_mutex_t;
-
-#define ADB_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
-#define adb_mutex_init pthread_mutex_init
-#define adb_mutex_lock pthread_mutex_lock
-#define adb_mutex_unlock pthread_mutex_unlock
-#define adb_mutex_destroy pthread_mutex_destroy
-
-#define ADB_MUTEX_DEFINE(m) adb_mutex_t m = PTHREAD_MUTEX_INITIALIZER
-
-#define adb_cond_t pthread_cond_t
-#define adb_cond_init pthread_cond_init
-#define adb_cond_wait pthread_cond_wait
-#define adb_cond_broadcast pthread_cond_broadcast
-#define adb_cond_signal pthread_cond_signal
-#define adb_cond_destroy pthread_cond_destroy
-
-/* declare all mutexes */
-#define ADB_MUTEX(x) extern adb_mutex_t x;
-#include "mutex_list.h"
-
static __inline__ void close_on_exec(int fd)
{
fcntl( fd, F_SETFD, FD_CLOEXEC );
@@ -818,10 +776,6 @@
#undef mkdir
#define mkdir ___xxx_mkdir
-static __inline__ void adb_sysdeps_init(void)
-{
-}
-
static __inline__ int adb_is_absolute_host_path(const char* path) {
return path[0] == '/';
}
diff --git a/adb/sysdeps/condition_variable.h b/adb/sysdeps/condition_variable.h
deleted file mode 100644
index 117cd40..0000000
--- a/adb/sysdeps/condition_variable.h
+++ /dev/null
@@ -1,61 +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.
- */
-
-#pragma once
-
-#include <condition_variable>
-
-#include "sysdeps/mutex.h"
-
-#if defined(_WIN32)
-
-#include <windows.h>
-
-#include <android-base/macros.h>
-
-// The prebuilt version of mingw we use doesn't support condition_variable.
-// Therefore, implement our own using the Windows primitives.
-// Put them directly into the std namespace, so that when they're actually available, the build
-// breaks until they're removed.
-
-namespace std {
-
-class condition_variable {
- public:
- condition_variable() {
- InitializeConditionVariable(&cond_);
- }
-
- void wait(std::unique_lock<std::mutex>& lock) {
- std::mutex *m = lock.mutex();
- m->lock_count_--;
- SleepConditionVariableCS(&cond_, m->native_handle(), INFINITE);
- m->lock_count_++;
- }
-
- void notify_one() {
- WakeConditionVariable(&cond_);
- }
-
- private:
- CONDITION_VARIABLE cond_;
-
- DISALLOW_COPY_AND_ASSIGN(condition_variable);
-};
-
-}
-
-#endif // defined(_WIN32)
diff --git a/adb/sysdeps/mutex.h b/adb/sysdeps/mutex.h
deleted file mode 100644
index 226f7f1..0000000
--- a/adb/sysdeps/mutex.h
+++ /dev/null
@@ -1,120 +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.
- */
-
-#pragma once
-#if defined(_WIN32)
-
-#include <windows.h>
-
-#include <android-base/macros.h>
-
-#include "adb.h"
-
-// The prebuilt version of mingw we use doesn't support mutex or recursive_mutex.
-// Therefore, implement our own using the Windows primitives.
-// Put them directly into the std namespace, so that when they're actually available, the build
-// breaks until they're removed.
-
-#include <mutex>
-namespace std {
-
-// CRITICAL_SECTION is recursive, so just wrap it in a Mutex-compatible class.
-class recursive_mutex {
- public:
- typedef CRITICAL_SECTION* native_handle_type;
-
- recursive_mutex() {
- InitializeCriticalSection(&cs_);
- }
-
- ~recursive_mutex() {
- DeleteCriticalSection(&cs_);
- }
-
- void lock() {
- EnterCriticalSection(&cs_);
- }
-
- bool try_lock() {
- return TryEnterCriticalSection(&cs_);
- }
-
- void unlock() {
- LeaveCriticalSection(&cs_);
- }
-
- native_handle_type native_handle() {
- return &cs_;
- }
-
- private:
- CRITICAL_SECTION cs_;
-
- DISALLOW_COPY_AND_ASSIGN(recursive_mutex);
-};
-
-class mutex {
- public:
- typedef CRITICAL_SECTION* native_handle_type;
-
- mutex() {
- }
-
- ~mutex() {
- }
-
- void lock() {
- mutex_.lock();
- if (++lock_count_ != 1) {
- fatal("non-recursive mutex locked reentrantly");
- }
- }
-
- void unlock() {
- if (--lock_count_ != 0) {
- fatal("non-recursive mutex unlock resulted in unexpected lock count: %d", lock_count_);
- }
- mutex_.unlock();
- }
-
- bool try_lock() {
- if (!mutex_.try_lock()) {
- return false;
- }
-
- if (lock_count_ != 0) {
- mutex_.unlock();
- return false;
- }
-
- ++lock_count_;
- return true;
- }
-
- native_handle_type native_handle() {
- return mutex_.native_handle();
- }
-
- private:
- recursive_mutex mutex_;
- size_t lock_count_ = 0;
-
- friend class condition_variable;
-};
-
-}
-
-#endif // defined(_WIN32)
diff --git a/adb/sysdeps_test.cpp b/adb/sysdeps_test.cpp
index 740f283..9f77942 100644
--- a/adb/sysdeps_test.cpp
+++ b/adb/sysdeps_test.cpp
@@ -17,11 +17,10 @@
#include <gtest/gtest.h>
#include <unistd.h>
#include <atomic>
+#include <condition_variable>
#include "adb_io.h"
#include "sysdeps.h"
-#include "sysdeps/condition_variable.h"
-#include "sysdeps/mutex.h"
static void increment_atomic_int(void* c) {
sleep(1);
@@ -270,17 +269,6 @@
m.unlock();
}
-// Our implementation on Windows aborts on double lock.
-#if defined(_WIN32)
-TEST(sysdeps_mutex, mutex_reentrant_lock) {
- std::mutex &m = *new std::mutex();
-
- m.lock();
- ASSERT_FALSE(m.try_lock());
- EXPECT_DEATH(m.lock(), "non-recursive mutex locked reentrantly");
-}
-#endif
-
TEST(sysdeps_mutex, recursive_mutex_smoke) {
static std::recursive_mutex &m = *new std::recursive_mutex();
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index 5fda27b..4dd549d 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -27,6 +27,7 @@
#include <algorithm>
#include <memory>
+#include <mutex>
#include <string>
#include <unordered_map>
#include <vector>
@@ -137,7 +138,7 @@
#define WIN32_FH_BASE 2048
#define WIN32_MAX_FHS 2048
-static adb_mutex_t _win32_lock;
+static std::mutex& _win32_lock = *new std::mutex();
static FHRec _win32_fhs[ WIN32_MAX_FHS ];
static int _win32_fh_next; // where to start search for free FHRec
@@ -182,27 +183,24 @@
{
FH f = NULL;
- adb_mutex_lock( &_win32_lock );
+ std::lock_guard<std::mutex> lock(_win32_lock);
for (int i = _win32_fh_next; i < WIN32_MAX_FHS; ++i) {
if (_win32_fhs[i].clazz == NULL) {
f = &_win32_fhs[i];
_win32_fh_next = i + 1;
- goto Exit;
+ f->clazz = clazz;
+ f->used = 1;
+ f->eof = 0;
+ f->name[0] = '\0';
+ clazz->_fh_init(f);
+ return f;
}
}
- D( "_fh_alloc: no more free file descriptors" );
- errno = EMFILE; // Too many open files
-Exit:
- if (f) {
- f->clazz = clazz;
- f->used = 1;
- f->eof = 0;
- f->name[0] = '\0';
- clazz->_fh_init(f);
- }
- adb_mutex_unlock( &_win32_lock );
- return f;
+
+ D("_fh_alloc: no more free file descriptors");
+ errno = EMFILE; // Too many open files
+ return nullptr;
}
@@ -211,7 +209,7 @@
{
// Use lock so that closing only happens once and so that _fh_alloc can't
// allocate a FH that we're in the middle of closing.
- adb_mutex_lock(&_win32_lock);
+ std::lock_guard<std::mutex> lock(_win32_lock);
int offset = f - _win32_fhs;
if (_win32_fh_next > offset) {
@@ -225,7 +223,6 @@
f->used = 0;
f->clazz = NULL;
}
- adb_mutex_unlock(&_win32_lock);
return 0;
}
@@ -1234,17 +1231,6 @@
return true;
}
-static adb_mutex_t g_console_output_buffer_lock;
-
-void
-adb_sysdeps_init( void )
-{
-#define ADB_MUTEX(x) InitializeCriticalSection( & x );
-#include "mutex_list.h"
- InitializeCriticalSection( &_win32_lock );
- InitializeCriticalSection( &g_console_output_buffer_lock );
-}
-
/**************************************************************************/
/**************************************************************************/
/***** *****/
@@ -2437,12 +2423,13 @@
// Bytes that have not yet been output to the console because they are incomplete UTF-8 sequences.
// Note that we use only one buffer even though stderr and stdout are logically separate streams.
// This matches the behavior of Linux.
-// Protected by g_console_output_buffer_lock.
-static auto& g_console_output_buffer = *new std::vector<char>();
// Internal helper function to write UTF-8 bytes to a console. Returns -1 on error.
static int _console_write_utf8(const char* const buf, const size_t buf_size, FILE* stream,
HANDLE console) {
+ static std::mutex& console_output_buffer_lock = *new std::mutex();
+ static auto& console_output_buffer = *new std::vector<char>();
+
const int saved_errno = errno;
std::vector<char> combined_buffer;
@@ -2450,24 +2437,25 @@
const char* utf8;
size_t utf8_size;
- adb_mutex_lock(&g_console_output_buffer_lock);
- if (g_console_output_buffer.empty()) {
- // If g_console_output_buffer doesn't have a buffered up incomplete UTF-8 sequence (the
- // common case with plain ASCII), parse buf directly.
- utf8 = buf;
- utf8_size = internal::ParseCompleteUTF8(buf, buf + buf_size, &g_console_output_buffer);
- } else {
- // If g_console_output_buffer has a buffered up incomplete UTF-8 sequence, move it to
- // combined_buffer (and effectively clear g_console_output_buffer) and append buf to
- // combined_buffer, then parse it all together.
- combined_buffer.swap(g_console_output_buffer);
- combined_buffer.insert(combined_buffer.end(), buf, buf + buf_size);
+ {
+ std::lock_guard<std::mutex> lock(console_output_buffer_lock);
+ if (console_output_buffer.empty()) {
+ // If console_output_buffer doesn't have a buffered up incomplete UTF-8 sequence (the
+ // common case with plain ASCII), parse buf directly.
+ utf8 = buf;
+ utf8_size = internal::ParseCompleteUTF8(buf, buf + buf_size, &console_output_buffer);
+ } else {
+ // If console_output_buffer has a buffered up incomplete UTF-8 sequence, move it to
+ // combined_buffer (and effectively clear console_output_buffer) and append buf to
+ // combined_buffer, then parse it all together.
+ combined_buffer.swap(console_output_buffer);
+ combined_buffer.insert(combined_buffer.end(), buf, buf + buf_size);
- utf8 = combined_buffer.data();
- utf8_size = internal::ParseCompleteUTF8(utf8, utf8 + combined_buffer.size(),
- &g_console_output_buffer);
+ utf8 = combined_buffer.data();
+ utf8_size = internal::ParseCompleteUTF8(utf8, utf8 + combined_buffer.size(),
+ &console_output_buffer);
+ }
}
- adb_mutex_unlock(&g_console_output_buffer_lock);
std::wstring utf16;
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 3eaeb06..87712fc 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -28,6 +28,7 @@
#include <algorithm>
#include <list>
+#include <mutex>
#include <android-base/logging.h>
#include <android-base/parsenetaddress.h>
@@ -44,7 +45,7 @@
static auto& transport_list = *new std::list<atransport*>();
static auto& pending_list = *new std::list<atransport*>();
-ADB_MUTEX_DEFINE( transport_lock );
+static std::mutex& transport_lock = *new std::mutex();
const char* const kFeatureShell2 = "shell_v2";
const char* const kFeatureCmd = "cmd";
@@ -297,13 +298,12 @@
}
void kick_transport(atransport* t) {
- adb_mutex_lock(&transport_lock);
+ std::lock_guard<std::mutex> lock(transport_lock);
// As kick_transport() can be called from threads without guarantee that t is valid,
// check if the transport is in transport_list first.
if (std::find(transport_list.begin(), transport_list.end(), t) != transport_list.end()) {
t->Kick();
}
- adb_mutex_unlock(&transport_lock);
}
static int transport_registration_send = -1;
@@ -333,7 +333,7 @@
device_tracker** pnode = &device_tracker_list;
device_tracker* node = *pnode;
- adb_mutex_lock( &transport_lock );
+ std::lock_guard<std::mutex> lock(transport_lock);
while (node) {
if (node == tracker) {
*pnode = node->next;
@@ -342,7 +342,6 @@
pnode = &node->next;
node = *pnode;
}
- adb_mutex_unlock( &transport_lock );
}
static void
@@ -504,9 +503,10 @@
fdevent_remove(&(t->transport_fde));
adb_close(t->fd);
- adb_mutex_lock(&transport_lock);
- transport_list.remove(t);
- adb_mutex_unlock(&transport_lock);
+ {
+ std::lock_guard<std::mutex> lock(transport_lock);
+ transport_list.remove(t);
+ }
if (t->product)
free(t->product);
@@ -555,10 +555,11 @@
}
}
- adb_mutex_lock(&transport_lock);
- pending_list.remove(t);
- transport_list.push_front(t);
- adb_mutex_unlock(&transport_lock);
+ {
+ std::lock_guard<std::mutex> lock(transport_lock);
+ pending_list.remove(t);
+ transport_list.push_front(t);
+ }
update_transports();
}
@@ -609,7 +610,8 @@
static void transport_unref(atransport* t) {
CHECK(t != nullptr);
- adb_mutex_lock(&transport_lock);
+
+ std::lock_guard<std::mutex> lock(transport_lock);
CHECK_GT(t->ref_count, 0u);
t->ref_count--;
if (t->ref_count == 0) {
@@ -619,7 +621,6 @@
} else {
D("transport: %s unref (count=%zu)", t->serial, t->ref_count);
}
- adb_mutex_unlock(&transport_lock);
}
static int qual_match(const char *to_test,
@@ -665,7 +666,7 @@
*error_out = "no devices found";
}
- adb_mutex_lock(&transport_lock);
+ std::unique_lock<std::mutex> lock(transport_lock);
for (const auto& t : transport_list) {
if (t->connection_state == kCsNoPerm) {
#if ADB_HOST
@@ -713,7 +714,7 @@
}
}
}
- adb_mutex_unlock(&transport_lock);
+ lock.unlock();
// Don't return unauthorized devices; the caller can't do anything with them.
if (result && result->connection_state == kCsUnauthorized) {
@@ -914,21 +915,20 @@
std::string list_transports(bool long_listing) {
std::string result;
- adb_mutex_lock(&transport_lock);
+
+ std::lock_guard<std::mutex> lock(transport_lock);
for (const auto& t : transport_list) {
append_transport(t, &result, long_listing);
}
- adb_mutex_unlock(&transport_lock);
return result;
}
/* hack for osx */
void close_usb_devices() {
- adb_mutex_lock(&transport_lock);
+ std::lock_guard<std::mutex> lock(transport_lock);
for (const auto& t : transport_list) {
t->Kick();
}
- adb_mutex_unlock(&transport_lock);
}
#endif // ADB_HOST
@@ -947,10 +947,9 @@
return -1;
}
- adb_mutex_lock(&transport_lock);
+ std::unique_lock<std::mutex> lock(transport_lock);
for (const auto& transport : pending_list) {
if (transport->serial && strcmp(serial, transport->serial) == 0) {
- adb_mutex_unlock(&transport_lock);
VLOG(TRANSPORT) << "socket transport " << transport->serial
<< " is already in pending_list and fails to register";
delete t;
@@ -960,7 +959,6 @@
for (const auto& transport : transport_list) {
if (transport->serial && strcmp(serial, transport->serial) == 0) {
- adb_mutex_unlock(&transport_lock);
VLOG(TRANSPORT) << "socket transport " << transport->serial
<< " is already in transport_list and fails to register";
delete t;
@@ -970,7 +968,8 @@
pending_list.push_front(t);
t->serial = strdup(serial);
- adb_mutex_unlock(&transport_lock);
+
+ lock.unlock();
register_transport(t);
return 0;
@@ -980,20 +979,19 @@
atransport *find_transport(const char *serial) {
atransport* result = nullptr;
- adb_mutex_lock(&transport_lock);
+ std::lock_guard<std::mutex> lock(transport_lock);
for (auto& t : transport_list) {
if (t->serial && strcmp(serial, t->serial) == 0) {
result = t;
break;
}
}
- adb_mutex_unlock(&transport_lock);
return result;
}
void kick_all_tcp_devices() {
- adb_mutex_lock(&transport_lock);
+ std::lock_guard<std::mutex> lock(transport_lock);
for (auto& t : transport_list) {
if (t->IsTcpDevice()) {
// Kicking breaks the read_transport thread of this transport out of any read, then
@@ -1003,7 +1001,6 @@
t->Kick();
}
}
- adb_mutex_unlock(&transport_lock);
}
#endif
@@ -1023,20 +1020,20 @@
t->devpath = strdup(devpath);
}
- adb_mutex_lock(&transport_lock);
- pending_list.push_front(t);
- adb_mutex_unlock(&transport_lock);
+ {
+ std::lock_guard<std::mutex> lock(transport_lock);
+ pending_list.push_front(t);
+ }
register_transport(t);
}
// This should only be used for transports with connection_state == kCsNoPerm.
void unregister_usb_transport(usb_handle *usb) {
- adb_mutex_lock(&transport_lock);
+ std::lock_guard<std::mutex> lock(transport_lock);
transport_list.remove_if([usb](atransport* t) {
return t->usb == usb && t->connection_state == kCsNoPerm;
});
- adb_mutex_unlock(&transport_lock);
}
int check_header(apacket *p, atransport *t)
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index 395b893..a94b41e 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -17,8 +17,6 @@
#define TRACE_TAG TRANSPORT
#include "sysdeps.h"
-#include "sysdeps/condition_variable.h"
-#include "sysdeps/mutex.h"
#include "transport.h"
#include <errno.h>
@@ -27,13 +25,15 @@
#include <string.h>
#include <sys/types.h>
+#include <condition_variable>
+#include <mutex>
#include <vector>
#include <android-base/stringprintf.h>
#include <cutils/sockets.h>
#if !ADB_HOST
-#include "cutils/properties.h"
+#include <android-base/properties.h>
#endif
#include "adb.h"
@@ -48,7 +48,7 @@
// connected.
#define ADB_LOCAL_TRANSPORT_MAX 16
-ADB_MUTEX_DEFINE(local_transports_lock);
+static std::mutex& local_transports_lock = *new std::mutex();
/* we keep a list of opened transports. The atransport struct knows to which
* local transport it is connected. The list is used to detect when we're
@@ -356,15 +356,13 @@
func = client_socket_thread;
debug_name = "client";
#else
- /* For the adbd daemon in the system image we need to distinguish
- * between the device, and the emulator. */
- char is_qemu[PROPERTY_VALUE_MAX];
- property_get("ro.kernel.qemu", is_qemu, "");
- if (!strcmp(is_qemu, "1")) {
- /* Running inside the emulator: use QEMUD pipe as the transport. */
+ // For the adbd daemon in the system image we need to distinguish
+ // between the device, and the emulator.
+ if (android::base::GetBoolProperty("ro.kernel.qemu", false)) {
+ // Running inside the emulator: use QEMUD pipe as the transport.
func = qemu_socket_thread;
} else {
- /* Running inside the device: use TCP socket as the transport. */
+ // Running inside the device: use TCP socket as the transport.
func = server_socket_thread;
}
debug_name = "server";
@@ -385,14 +383,13 @@
#if ADB_HOST
int nn;
- adb_mutex_lock( &local_transports_lock );
+ std::lock_guard<std::mutex> lock(local_transports_lock);
for (nn = 0; nn < ADB_LOCAL_TRANSPORT_MAX; nn++) {
if (local_transports[nn] == t) {
local_transports[nn] = NULL;
break;
}
}
- adb_mutex_unlock( &local_transports_lock );
#endif
}
@@ -436,9 +433,8 @@
atransport* find_emulator_transport_by_adb_port(int adb_port)
{
- adb_mutex_lock( &local_transports_lock );
+ std::lock_guard<std::mutex> lock(local_transports_lock);
atransport* result = find_emulator_transport_by_adb_port_locked(adb_port);
- adb_mutex_unlock( &local_transports_lock );
return result;
}
@@ -456,9 +452,8 @@
int get_available_local_transport_index()
{
- adb_mutex_lock( &local_transports_lock );
+ std::lock_guard<std::mutex> lock(local_transports_lock);
int result = get_available_local_transport_index_locked();
- adb_mutex_unlock( &local_transports_lock );
return result;
}
#endif
@@ -478,26 +473,20 @@
#if ADB_HOST
if (local) {
- adb_mutex_lock( &local_transports_lock );
- {
- t->SetLocalPortForEmulator(adb_port);
- atransport* existing_transport =
- find_emulator_transport_by_adb_port_locked(adb_port);
- int index = get_available_local_transport_index_locked();
- if (existing_transport != NULL) {
- D("local transport for port %d already registered (%p)?",
- adb_port, existing_transport);
- fail = -1;
- } else if (index < 0) {
- // Too many emulators.
- D("cannot register more emulators. Maximum is %d",
- ADB_LOCAL_TRANSPORT_MAX);
- fail = -1;
- } else {
- local_transports[index] = t;
- }
- }
- adb_mutex_unlock( &local_transports_lock );
+ std::lock_guard<std::mutex> lock(local_transports_lock);
+ t->SetLocalPortForEmulator(adb_port);
+ atransport* existing_transport = find_emulator_transport_by_adb_port_locked(adb_port);
+ int index = get_available_local_transport_index_locked();
+ if (existing_transport != NULL) {
+ D("local transport for port %d already registered (%p)?", adb_port, existing_transport);
+ fail = -1;
+ } else if (index < 0) {
+ // Too many emulators.
+ D("cannot register more emulators. Maximum is %d", ADB_LOCAL_TRANSPORT_MAX);
+ fail = -1;
+ } else {
+ local_transports[index] = t;
+ }
}
#endif
return fail;
diff --git a/adb/transport_test.cpp b/adb/transport_test.cpp
index a6db07a..8b38e03 100644
--- a/adb/transport_test.cpp
+++ b/adb/transport_test.cpp
@@ -20,27 +20,6 @@
#include "adb.h"
-class TransportSetup {
-public:
- TransportSetup() {
-#ifdef _WIN32
- // Use extern instead of including sysdeps.h which brings in various macros
- // that conflict with APIs used in this file.
- extern void adb_sysdeps_init(void);
- adb_sysdeps_init();
-#else
- // adb_sysdeps_init() is an inline function that we cannot link against.
-#endif
- }
-};
-
-// Static initializer will call adb_sysdeps_init() before main() to initialize
-// the transport mutex before it is used in the tests. Alternatives would be to
-// use __attribute__((constructor)) here or to use that or a static initializer
-// for adb_sysdeps_init() itself in sysdeps_win32.cpp (caveats of unclear
-// init order), or to use a test fixture whose SetUp() could do the init once.
-static TransportSetup g_TransportSetup;
-
TEST(transport, kick_transport) {
atransport t;
static size_t kick_count;
diff --git a/adb/usb_linux_client.cpp b/adb/usb_linux_client.cpp
index 0ba6b4b..6de10f5 100644
--- a/adb/usb_linux_client.cpp
+++ b/adb/usb_linux_client.cpp
@@ -18,7 +18,6 @@
#include "sysdeps.h"
-#include <cutils/properties.h>
#include <dirent.h>
#include <errno.h>
#include <linux/usb/ch9.h>
@@ -32,8 +31,11 @@
#include <algorithm>
#include <atomic>
+#include <condition_variable>
+#include <mutex>
#include <android-base/logging.h>
+#include <android-base/properties.h>
#include "adb.h"
#include "transport.h"
@@ -54,12 +56,14 @@
static int dummy_fd = -1;
-struct usb_handle
-{
- adb_cond_t notify;
- adb_mutex_t lock;
- bool open_new_connection;
+struct usb_handle {
+ usb_handle() : kicked(false) {
+ }
+
+ std::condition_variable notify;
+ std::mutex lock;
std::atomic<bool> kicked;
+ bool open_new_connection = true;
int (*write)(usb_handle *h, const void *data, int len);
int (*read)(usb_handle *h, void *data, int len);
@@ -67,12 +71,12 @@
void (*close)(usb_handle *h);
// Legacy f_adb
- int fd;
+ int fd = -1;
// FunctionFS
- int control;
- int bulk_out; /* "out" from the host's perspective => source for adbd */
- int bulk_in; /* "in" from the host's perspective => sink for adbd */
+ int control = -1;
+ int bulk_out = -1; /* "out" from the host's perspective => source for adbd */
+ int bulk_in = -1; /* "in" from the host's perspective => sink for adbd */
};
struct func_desc {
@@ -248,12 +252,12 @@
while (true) {
// wait until the USB device needs opening
- adb_mutex_lock(&usb->lock);
+ std::unique_lock<std::mutex> lock(usb->lock);
while (!usb->open_new_connection) {
- adb_cond_wait(&usb->notify, &usb->lock);
+ usb->notify.wait(lock);
}
usb->open_new_connection = false;
- adb_mutex_unlock(&usb->lock);
+ lock.unlock();
D("[ usb_thread - opening device ]");
do {
@@ -339,27 +343,20 @@
h->kicked = false;
adb_close(h->fd);
// Notify usb_adb_open_thread to open a new connection.
- adb_mutex_lock(&h->lock);
+ h->lock.lock();
h->open_new_connection = true;
- adb_cond_signal(&h->notify);
- adb_mutex_unlock(&h->lock);
+ h->lock.unlock();
+ h->notify.notify_one();
}
static void usb_adb_init()
{
- usb_handle* h = reinterpret_cast<usb_handle*>(calloc(1, sizeof(usb_handle)));
- if (h == nullptr) fatal("couldn't allocate usb_handle");
+ usb_handle* h = new usb_handle();
h->write = usb_adb_write;
h->read = usb_adb_read;
h->kick = usb_adb_kick;
h->close = usb_adb_close;
- h->kicked = false;
- h->fd = -1;
-
- h->open_new_connection = true;
- adb_cond_init(&h->notify, 0);
- adb_mutex_init(&h->lock, 0);
// Open the file /dev/android_adb_enable to trigger
// the enabling of the adb USB function in the kernel.
@@ -468,12 +465,12 @@
while (true) {
// wait until the USB device needs opening
- adb_mutex_lock(&usb->lock);
+ std::unique_lock<std::mutex> lock(usb->lock);
while (!usb->open_new_connection) {
- adb_cond_wait(&usb->notify, &usb->lock);
+ usb->notify.wait(lock);
}
usb->open_new_connection = false;
- adb_mutex_unlock(&usb->lock);
+ lock.unlock();
while (true) {
if (init_functionfs(usb)) {
@@ -481,7 +478,7 @@
}
adb_sleep_ms(1000);
}
- property_set("sys.usb.ffs.ready", "1");
+ android::base::SetProperty("sys.usb.ffs.ready", "1");
D("[ usb_thread - registering device ]");
register_usb_transport(usb, 0, 0, 1);
@@ -557,31 +554,22 @@
adb_close(h->bulk_out);
adb_close(h->bulk_in);
// Notify usb_adb_open_thread to open a new connection.
- adb_mutex_lock(&h->lock);
+ h->lock.lock();
h->open_new_connection = true;
- adb_cond_signal(&h->notify);
- adb_mutex_unlock(&h->lock);
+ h->lock.unlock();
+ h->notify.notify_one();
}
static void usb_ffs_init()
{
D("[ usb_init - using FunctionFS ]");
- usb_handle* h = reinterpret_cast<usb_handle*>(calloc(1, sizeof(usb_handle)));
- if (h == nullptr) fatal("couldn't allocate usb_handle");
+ usb_handle* h = new usb_handle();
h->write = usb_ffs_write;
h->read = usb_ffs_read;
h->kick = usb_ffs_kick;
h->close = usb_ffs_close;
- h->kicked = false;
- h->control = -1;
- h->bulk_out = -1;
- h->bulk_out = -1;
-
- h->open_new_connection = true;
- adb_cond_init(&h->notify, 0);
- adb_mutex_init(&h->lock, 0);
D("[ usb_init - starting thread ]");
if (!adb_thread_create(usb_ffs_open_thread, h)) {
@@ -608,6 +596,7 @@
{
return h->read(h, data, len);
}
+
int usb_close(usb_handle *h)
{
h->close(h);
diff --git a/adb/usb_osx.cpp b/adb/usb_osx.cpp
index ddde454..adcbb3e 100644
--- a/adb/usb_osx.cpp
+++ b/adb/usb_osx.cpp
@@ -177,6 +177,7 @@
kr = (*iface)->GetDevice(iface, &usbDevice);
if (kIOReturnSuccess != kr || !usbDevice) {
LOG(ERROR) << "Couldn't grab device from interface (" << std::hex << kr << ")";
+ (*iface)->Release(iface);
continue;
}
@@ -191,6 +192,7 @@
(void)IOObjectRelease(usbDevice);
if ((kIOReturnSuccess != kr) || (!plugInInterface)) {
LOG(ERROR) << "Unable to create a device plug-in (" << std::hex << kr << ")";
+ (*iface)->Release(iface);
continue;
}
@@ -200,6 +202,7 @@
(*plugInInterface)->Release(plugInInterface);
if (result || !dev) {
LOG(ERROR) << "Couldn't create a device interface (" << std::hex << result << ")";
+ (*iface)->Release(iface);
continue;
}
@@ -211,6 +214,8 @@
if (kr == KERN_SUCCESS) {
devpath = android::base::StringPrintf("usb:%" PRIu32 "X", locationId);
if (IsKnownDevice(devpath)) {
+ (*dev)->Release(dev);
+ (*iface)->Release(iface);
continue;
}
}
diff --git a/adb/usb_windows.cpp b/adb/usb_windows.cpp
index 8ecca37..4649454 100644
--- a/adb/usb_windows.cpp
+++ b/adb/usb_windows.cpp
@@ -19,13 +19,17 @@
#include "sysdeps.h"
#include <winsock2.h> // winsock.h *must* be included before windows.h.
-#include <adb_api.h>
+#include <windows.h>
+#include <usb100.h>
+#include <winerror.h>
+
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
-#include <usb100.h>
-#include <windows.h>
-#include <winerror.h>
+
+#include <mutex>
+
+#include <adb_api.h>
#include <android-base/errors.h>
@@ -73,7 +77,7 @@
};
/// Locker for the list of opened usb handles
-ADB_MUTEX_DEFINE( usb_lock );
+static std::mutex& usb_lock = *new std::mutex();
/// Checks if there is opened usb handle in handle_list for this device.
int known_device(const wchar_t* dev_name);
@@ -141,9 +145,8 @@
int ret = 0;
if (NULL != dev_name) {
- adb_mutex_lock(&usb_lock);
+ std::lock_guard<std::mutex> lock(usb_lock);
ret = known_device_locked(dev_name);
- adb_mutex_unlock(&usb_lock);
}
return ret;
@@ -153,11 +156,10 @@
if (NULL == handle)
return 0;
- adb_mutex_lock(&usb_lock);
+ std::lock_guard<std::mutex> lock(usb_lock);
// Check if device is already in the list
if (known_device_locked(handle->interface_name)) {
- adb_mutex_unlock(&usb_lock);
return 0;
}
@@ -167,8 +169,6 @@
handle->prev->next = handle;
handle->next->prev = handle;
- adb_mutex_unlock(&usb_lock);
-
return 1;
}
@@ -493,11 +493,8 @@
void usb_kick(usb_handle* handle) {
D("usb_kick");
if (NULL != handle) {
- adb_mutex_lock(&usb_lock);
-
+ std::lock_guard<std::mutex> lock(usb_lock);
usb_kick_locked(handle);
-
- adb_mutex_unlock(&usb_lock);
} else {
errno = EINVAL;
}
@@ -508,17 +505,17 @@
if (NULL != handle) {
// Remove handle from the list
- adb_mutex_lock(&usb_lock);
+ {
+ std::lock_guard<std::mutex> lock(usb_lock);
- if ((handle->next != handle) && (handle->prev != handle)) {
- handle->next->prev = handle->prev;
- handle->prev->next = handle->next;
- handle->prev = handle;
- handle->next = handle;
+ if ((handle->next != handle) && (handle->prev != handle)) {
+ handle->next->prev = handle->prev;
+ handle->prev->next = handle->next;
+ handle->prev = handle;
+ handle->next = handle;
+ }
}
- adb_mutex_unlock(&usb_lock);
-
// Cleanup handle
usb_cleanup_handle(handle);
free(handle);
@@ -651,9 +648,8 @@
static void kick_devices() {
// Need to acquire lock to safely walk the list which might be modified
// by another thread.
- adb_mutex_lock(&usb_lock);
+ std::lock_guard<std::mutex> lock(usb_lock);
for (usb_handle* usb = handle_list.next; usb != &handle_list; usb = usb->next) {
usb_kick_locked(usb);
}
- adb_mutex_unlock(&usb_lock);
}
diff --git a/base/Android.bp b/base/Android.bp
index e260412..88d8ad1 100644
--- a/base/Android.bp
+++ b/base/Android.bp
@@ -39,7 +39,10 @@
shared_libs: ["liblog"],
target: {
android: {
- srcs: ["errors_unix.cpp"],
+ srcs: [
+ "errors_unix.cpp",
+ "properties.cpp",
+ ],
cppflags: ["-Wexit-time-destructors"],
},
darwin: {
@@ -78,6 +81,9 @@
"test_main.cpp",
],
target: {
+ android: {
+ srcs: ["properties_test.cpp"],
+ },
windows: {
srcs: ["utf8_test.cpp"],
enabled: true,
diff --git a/base/include/android-base/logging.h b/base/include/android-base/logging.h
index e8b445f..50677a3 100644
--- a/base/include/android-base/logging.h
+++ b/base/include/android-base/logging.h
@@ -120,6 +120,39 @@
DISALLOW_COPY_AND_ASSIGN(ErrnoRestorer);
};
+// A helper macro that produces an expression that accepts both a qualified name and an
+// unqualified name for a LogSeverity, and returns a LogSeverity value.
+// Note: DO NOT USE DIRECTLY. This is an implementation detail.
+#define SEVERITY_LAMBDA(severity) ([&]() { \
+ using ::android::base::VERBOSE; \
+ using ::android::base::DEBUG; \
+ using ::android::base::INFO; \
+ using ::android::base::WARNING; \
+ using ::android::base::ERROR; \
+ using ::android::base::FATAL_WITHOUT_ABORT; \
+ using ::android::base::FATAL; \
+ return (severity); }())
+
+// Defines whether the given severity will be logged or silently swallowed.
+#define WOULD_LOG(severity) \
+ UNLIKELY((SEVERITY_LAMBDA(severity)) >= ::android::base::GetMinimumLogSeverity())
+
+// Get an ostream that can be used for logging at the given severity and to the default
+// destination.
+//
+// Notes:
+// 1) This will not check whether the severity is high enough. One should use WOULD_LOG to filter
+// usage manually.
+// 2) This does not save and restore errno.
+#define LOG_STREAM(severity) LOG_STREAM_TO(DEFAULT, severity)
+
+// Get an ostream that can be used for logging at the given severity and to the
+// given destination. The same notes as for LOG_STREAM apply.
+#define LOG_STREAM_TO(dest, severity) \
+ ::android::base::LogMessage(__FILE__, __LINE__, \
+ ::android::base::dest, \
+ SEVERITY_LAMBDA(severity), -1).stream()
+
// Logs a message to logcat on Android otherwise to stderr. If the severity is
// FATAL it also causes an abort. For example:
//
@@ -132,24 +165,23 @@
// else statement after LOG() macro, it won't bind to the if statement in the macro.
// do-while(0) statement doesn't work here. Because we need to support << operator
// following the macro, like "LOG(DEBUG) << xxx;".
-#define LOG_TO(dest, severity) \
- UNLIKELY(::android::base::severity >= ::android::base::GetMinimumLogSeverity()) && \
- ::android::base::ErrnoRestorer() && \
- ::android::base::LogMessage(__FILE__, __LINE__, \
- ::android::base::dest, \
- ::android::base::severity, -1).stream()
+
+#define LOG_TO(dest, severity) \
+ WOULD_LOG(severity) && \
+ ::android::base::ErrnoRestorer() && \
+ LOG_STREAM_TO(dest, severity)
// A variant of LOG that also logs the current errno value. To be used when
// library calls fail.
#define PLOG(severity) PLOG_TO(DEFAULT, severity)
// Behaves like PLOG, but logs to the specified log ID.
-#define PLOG_TO(dest, severity) \
- UNLIKELY(::android::base::severity >= ::android::base::GetMinimumLogSeverity()) && \
- ::android::base::ErrnoRestorer() && \
- ::android::base::LogMessage(__FILE__, __LINE__, \
- ::android::base::dest, \
- ::android::base::severity, errno).stream()
+#define PLOG_TO(dest, severity) \
+ WOULD_LOG(SEVERITY_LAMBDA(severity)) && \
+ ::android::base::ErrnoRestorer() && \
+ ::android::base::LogMessage(__FILE__, __LINE__, \
+ ::android::base::dest, \
+ SEVERITY_LAMBDA(severity), errno).stream()
// Marker that code is yet to be implemented.
#define UNIMPLEMENTED(level) \
diff --git a/base/include/android-base/mutex.h b/base/include/android-base/mutex.h
deleted file mode 100644
index 22e75c7..0000000
--- a/base/include/android-base/mutex.h
+++ /dev/null
@@ -1,49 +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.
- */
-
-#pragma once
-
-#include <mutex>
-
-#include "android-base/macros.h"
-
-#if defined(_WIN32)
-#include <windows.h>
-
-namespace std {
-class mutex {
- public:
- mutex() {
- InitializeCriticalSection(&critical_section_);
- }
- ~mutex() {
- DeleteCriticalSection(&critical_section_);
- }
-
- void lock() {
- EnterCriticalSection(&critical_section_);
- }
-
- void unlock() {
- LeaveCriticalSection(&critical_section_);
- }
-
- private:
- CRITICAL_SECTION critical_section_;
- DISALLOW_COPY_AND_ASSIGN(mutex);
-};
-} // namespace std
-#endif
diff --git a/base/include/android-base/properties.h b/base/include/android-base/properties.h
new file mode 100644
index 0000000..95d1b6a
--- /dev/null
+++ b/base/include/android-base/properties.h
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_BASE_PROPERTIES_H
+#define ANDROID_BASE_PROPERTIES_H
+
+#include <sys/cdefs.h>
+
+#if !defined(__BIONIC__)
+#error Only bionic supports system properties.
+#endif
+
+#include <limits>
+#include <string>
+
+namespace android {
+namespace base {
+
+// Returns the current value of the system property `key`,
+// or `default_value` if the property is empty or doesn't exist.
+std::string GetProperty(const std::string& key, const std::string& default_value);
+
+// Returns true if the system property `key` has the value "1", "y", "yes", "on", or "true",
+// false for "0", "n", "no", "off", or "false", or `default_value` otherwise.
+bool GetBoolProperty(const std::string& key, bool default_value);
+
+// Returns the signed integer corresponding to the system property `key`.
+// If the property is empty, doesn't exist, doesn't have an integer value, or is outside
+// the optional bounds, returns `default_value`.
+template <typename T> T GetIntProperty(const std::string& key,
+ T default_value,
+ T min = std::numeric_limits<T>::min(),
+ T max = std::numeric_limits<T>::max());
+
+// Returns the unsigned integer corresponding to the system property `key`.
+// If the property is empty, doesn't exist, doesn't have an integer value, or is outside
+// the optional bound, returns `default_value`.
+template <typename T> T GetUintProperty(const std::string& key,
+ T default_value,
+ T max = std::numeric_limits<T>::max());
+
+// Sets the system property `key` to `value`.
+// Note that system property setting is inherently asynchronous so a return value of `true`
+// isn't particularly meaningful, and immediately reading back the value won't necessarily
+// tell you whether or not your call succeeded. A `false` return value definitely means failure.
+bool SetProperty(const std::string& key, const std::string& value);
+
+} // namespace base
+} // namespace android
+
+#endif // ANDROID_BASE_MEMORY_H
diff --git a/base/include/android-base/unique_fd.h b/base/include/android-base/unique_fd.h
index c323311..6cfcfcd 100644
--- a/base/include/android-base/unique_fd.h
+++ b/base/include/android-base/unique_fd.h
@@ -55,7 +55,7 @@
unique_fd_impl() : value_(-1) {}
explicit unique_fd_impl(int value) : value_(value) {}
- ~unique_fd_impl() { clear(); }
+ ~unique_fd_impl() { reset(); }
unique_fd_impl(unique_fd_impl&& other) : value_(other.release()) {}
unique_fd_impl& operator=(unique_fd_impl&& s) {
@@ -63,17 +63,13 @@
return *this;
}
- void reset(int new_value) {
+ void reset(int new_value = -1) {
if (value_ != -1) {
Closer::Close(value_);
}
value_ = new_value;
}
- void clear() {
- reset(-1);
- }
-
int get() const { return value_; }
operator int() const { return get(); }
diff --git a/base/logging.cpp b/base/logging.cpp
index 33313e4..eaed9ab 100644
--- a/base/logging.cpp
+++ b/base/logging.cpp
@@ -44,7 +44,6 @@
#include <vector>
#include "android-base/macros.h"
-#include "android-base/mutex.h"
#include "android-base/strings.h"
// Headers for LogMessage::LogLine.
@@ -391,6 +390,11 @@
}
LogMessage::~LogMessage() {
+ // Check severity again. This is duplicate work wrt/ LOG macros, but not LOG_STREAM.
+ if (!WOULD_LOG(data_->GetSeverity())) {
+ return;
+ }
+
// Finish constructing the message.
if (data_->GetError() != -1) {
data_->GetBuffer() << ": " << strerror(data_->GetError());
diff --git a/base/logging_test.cpp b/base/logging_test.cpp
index 8813525..9fc7736 100644
--- a/base/logging_test.cpp
+++ b/base/logging_test.cpp
@@ -142,6 +142,92 @@
// we don't get more bit-rot).
}
+
+#define CHECK_WOULD_LOG_DISABLED(severity) \
+ static_assert(android::base::severity < android::base::FATAL, "Bad input"); \
+ for (size_t i = static_cast<size_t>(android::base::severity) + 1; \
+ i <= static_cast<size_t>(android::base::FATAL); \
+ ++i) { \
+ { \
+ android::base::ScopedLogSeverity sls2(static_cast<android::base::LogSeverity>(i)); \
+ EXPECT_FALSE(WOULD_LOG(severity)) << i; \
+ } \
+ { \
+ android::base::ScopedLogSeverity sls2(static_cast<android::base::LogSeverity>(i)); \
+ EXPECT_FALSE(WOULD_LOG(::android::base::severity)) << i; \
+ } \
+ } \
+
+#define CHECK_WOULD_LOG_ENABLED(severity) \
+ for (size_t i = static_cast<size_t>(android::base::VERBOSE); \
+ i <= static_cast<size_t>(android::base::severity); \
+ ++i) { \
+ { \
+ android::base::ScopedLogSeverity sls2(static_cast<android::base::LogSeverity>(i)); \
+ EXPECT_TRUE(WOULD_LOG(severity)) << i; \
+ } \
+ { \
+ android::base::ScopedLogSeverity sls2(static_cast<android::base::LogSeverity>(i)); \
+ EXPECT_TRUE(WOULD_LOG(::android::base::severity)) << i; \
+ } \
+ } \
+
+TEST(logging, WOULD_LOG_FATAL) {
+ CHECK_WOULD_LOG_ENABLED(FATAL);
+}
+
+TEST(logging, WOULD_LOG_FATAL_WITHOUT_ABORT_disabled) {
+ CHECK_WOULD_LOG_DISABLED(FATAL_WITHOUT_ABORT);
+}
+
+TEST(logging, WOULD_LOG_FATAL_WITHOUT_ABORT_enabled) {
+ CHECK_WOULD_LOG_ENABLED(FATAL_WITHOUT_ABORT);
+}
+
+TEST(logging, WOULD_LOG_ERROR_disabled) {
+ CHECK_WOULD_LOG_DISABLED(ERROR);
+}
+
+TEST(logging, WOULD_LOG_ERROR_enabled) {
+ CHECK_WOULD_LOG_ENABLED(ERROR);
+}
+
+TEST(logging, WOULD_LOG_WARNING_disabled) {
+ CHECK_WOULD_LOG_DISABLED(WARNING);
+}
+
+TEST(logging, WOULD_LOG_WARNING_enabled) {
+ CHECK_WOULD_LOG_ENABLED(WARNING);
+}
+
+TEST(logging, WOULD_LOG_INFO_disabled) {
+ CHECK_WOULD_LOG_DISABLED(INFO);
+}
+
+TEST(logging, WOULD_LOG_INFO_enabled) {
+ CHECK_WOULD_LOG_ENABLED(INFO);
+}
+
+TEST(logging, WOULD_LOG_DEBUG_disabled) {
+ CHECK_WOULD_LOG_DISABLED(DEBUG);
+}
+
+TEST(logging, WOULD_LOG_DEBUG_enabled) {
+ CHECK_WOULD_LOG_ENABLED(DEBUG);
+}
+
+TEST(logging, WOULD_LOG_VERBOSE_disabled) {
+ CHECK_WOULD_LOG_DISABLED(VERBOSE);
+}
+
+TEST(logging, WOULD_LOG_VERBOSE_enabled) {
+ CHECK_WOULD_LOG_ENABLED(VERBOSE);
+}
+
+#undef CHECK_WOULD_LOG_DISABLED
+#undef CHECK_WOULD_LOG_ENABLED
+
+
static std::string make_log_pattern(android::base::LogSeverity severity,
const char* message) {
static const char log_characters[] = "VDIWEFF";
@@ -154,18 +240,6 @@
log_char, basename(&holder[0]), message);
}
-#define CHECK_LOG_DISABLED(severity) \
- android::base::ScopedLogSeverity sls1(android::base::FATAL); \
- CapturedStderr cap1; \
- LOG(severity) << "foo bar"; \
- ASSERT_EQ(0, lseek(cap1.fd(), 0, SEEK_CUR)); \
-
-#define CHECK_LOG_ENABLED(severity) \
- android::base::ScopedLogSeverity sls2(android::base::severity); \
- CapturedStderr cap2; \
- LOG(severity) << "foobar"; \
- CheckMessage(cap2, android::base::severity, "foobar"); \
-
static void CheckMessage(const CapturedStderr& cap,
android::base::LogSeverity severity, const char* expected) {
std::string output;
@@ -184,8 +258,118 @@
#endif
}
+
+#define CHECK_LOG_STREAM_DISABLED(severity) \
+ { \
+ android::base::ScopedLogSeverity sls1(android::base::FATAL); \
+ CapturedStderr cap1; \
+ LOG_STREAM(severity) << "foo bar"; \
+ ASSERT_EQ(0, lseek(cap1.fd(), 0, SEEK_CUR)); \
+ } \
+ { \
+ android::base::ScopedLogSeverity sls1(android::base::FATAL); \
+ CapturedStderr cap1; \
+ LOG_STREAM(::android::base::severity) << "foo bar"; \
+ ASSERT_EQ(0, lseek(cap1.fd(), 0, SEEK_CUR)); \
+ } \
+
+#define CHECK_LOG_STREAM_ENABLED(severity) \
+ { \
+ android::base::ScopedLogSeverity sls2(android::base::severity); \
+ CapturedStderr cap2; \
+ LOG_STREAM(severity) << "foobar"; \
+ CheckMessage(cap2, android::base::severity, "foobar"); \
+ } \
+ { \
+ android::base::ScopedLogSeverity sls2(android::base::severity); \
+ CapturedStderr cap2; \
+ LOG_STREAM(::android::base::severity) << "foobar"; \
+ CheckMessage(cap2, android::base::severity, "foobar"); \
+ } \
+
+TEST(logging, LOG_STREAM_FATAL_WITHOUT_ABORT_disabled) {
+ CHECK_LOG_STREAM_DISABLED(FATAL_WITHOUT_ABORT);
+}
+
+TEST(logging, LOG_STREAM_FATAL_WITHOUT_ABORT_enabled) {
+ CHECK_LOG_STREAM_ENABLED(FATAL_WITHOUT_ABORT);
+}
+
+TEST(logging, LOG_STREAM_ERROR_disabled) {
+ CHECK_LOG_STREAM_DISABLED(ERROR);
+}
+
+TEST(logging, LOG_STREAM_ERROR_enabled) {
+ CHECK_LOG_STREAM_ENABLED(ERROR);
+}
+
+TEST(logging, LOG_STREAM_WARNING_disabled) {
+ CHECK_LOG_STREAM_DISABLED(WARNING);
+}
+
+TEST(logging, LOG_STREAM_WARNING_enabled) {
+ CHECK_LOG_STREAM_ENABLED(WARNING);
+}
+
+TEST(logging, LOG_STREAM_INFO_disabled) {
+ CHECK_LOG_STREAM_DISABLED(INFO);
+}
+
+TEST(logging, LOG_STREAM_INFO_enabled) {
+ CHECK_LOG_STREAM_ENABLED(INFO);
+}
+
+TEST(logging, LOG_STREAM_DEBUG_disabled) {
+ CHECK_LOG_STREAM_DISABLED(DEBUG);
+}
+
+TEST(logging, LOG_STREAM_DEBUG_enabled) {
+ CHECK_LOG_STREAM_ENABLED(DEBUG);
+}
+
+TEST(logging, LOG_STREAM_VERBOSE_disabled) {
+ CHECK_LOG_STREAM_DISABLED(VERBOSE);
+}
+
+TEST(logging, LOG_STREAM_VERBOSE_enabled) {
+ CHECK_LOG_STREAM_ENABLED(VERBOSE);
+}
+
+#undef CHECK_LOG_STREAM_DISABLED
+#undef CHECK_LOG_STREAM_ENABLED
+
+
+#define CHECK_LOG_DISABLED(severity) \
+ { \
+ android::base::ScopedLogSeverity sls1(android::base::FATAL); \
+ CapturedStderr cap1; \
+ LOG(severity) << "foo bar"; \
+ ASSERT_EQ(0, lseek(cap1.fd(), 0, SEEK_CUR)); \
+ } \
+ { \
+ android::base::ScopedLogSeverity sls1(android::base::FATAL); \
+ CapturedStderr cap1; \
+ LOG(::android::base::severity) << "foo bar"; \
+ ASSERT_EQ(0, lseek(cap1.fd(), 0, SEEK_CUR)); \
+ } \
+
+#define CHECK_LOG_ENABLED(severity) \
+ { \
+ android::base::ScopedLogSeverity sls2(android::base::severity); \
+ CapturedStderr cap2; \
+ LOG(severity) << "foobar"; \
+ CheckMessage(cap2, android::base::severity, "foobar"); \
+ } \
+ { \
+ android::base::ScopedLogSeverity sls2(android::base::severity); \
+ CapturedStderr cap2; \
+ LOG(::android::base::severity) << "foobar"; \
+ CheckMessage(cap2, android::base::severity, "foobar"); \
+ } \
+
TEST(logging, LOG_FATAL) {
ASSERT_DEATH({SuppressAbortUI(); LOG(FATAL) << "foobar";}, "foobar");
+ ASSERT_DEATH({SuppressAbortUI(); LOG(::android::base::FATAL) << "foobar";}, "foobar");
}
TEST(logging, LOG_FATAL_WITHOUT_ABORT_disabled) {
@@ -236,6 +420,36 @@
CHECK_LOG_ENABLED(VERBOSE);
}
+#undef CHECK_LOG_DISABLED
+#undef CHECK_LOG_ENABLED
+
+
+TEST(logging, LOG_complex_param) {
+#define CHECK_LOG_COMBINATION(use_scoped_log_severity_info, use_logging_severity_info) \
+ { \
+ android::base::ScopedLogSeverity sls( \
+ (use_scoped_log_severity_info) ? ::android::base::INFO : ::android::base::WARNING); \
+ CapturedStderr cap; \
+ LOG((use_logging_severity_info) ? ::android::base::INFO : ::android::base::WARNING) \
+ << "foobar"; \
+ if ((use_scoped_log_severity_info) || !(use_logging_severity_info)) { \
+ CheckMessage(cap, \
+ (use_logging_severity_info) ? ::android::base::INFO : ::android::base::WARNING, \
+ "foobar"); \
+ } else { \
+ ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_CUR)); \
+ } \
+ }
+
+ CHECK_LOG_COMBINATION(false,false);
+ CHECK_LOG_COMBINATION(false,true);
+ CHECK_LOG_COMBINATION(true,false);
+ CHECK_LOG_COMBINATION(true,true);
+
+#undef CHECK_LOG_COMBINATION
+}
+
+
TEST(logging, LOG_does_not_clobber_errno) {
CapturedStderr cap;
errno = 12345;
@@ -277,23 +491,39 @@
EXPECT_FALSE(flag) << "LOG macro probably has a dangling if with no else";
}
-#define CHECK_PLOG(severity) \
-
#define CHECK_PLOG_DISABLED(severity) \
- android::base::ScopedLogSeverity sls1(android::base::FATAL); \
- CapturedStderr cap1; \
- PLOG(severity) << "foo bar"; \
- ASSERT_EQ(0, lseek(cap1.fd(), 0, SEEK_CUR)); \
+ { \
+ android::base::ScopedLogSeverity sls1(android::base::FATAL); \
+ CapturedStderr cap1; \
+ PLOG(severity) << "foo bar"; \
+ ASSERT_EQ(0, lseek(cap1.fd(), 0, SEEK_CUR)); \
+ } \
+ { \
+ android::base::ScopedLogSeverity sls1(android::base::FATAL); \
+ CapturedStderr cap1; \
+ PLOG(severity) << "foo bar"; \
+ ASSERT_EQ(0, lseek(cap1.fd(), 0, SEEK_CUR)); \
+ } \
#define CHECK_PLOG_ENABLED(severity) \
- android::base::ScopedLogSeverity sls2(android::base::severity); \
- CapturedStderr cap2; \
- errno = ENOENT; \
- PLOG(severity) << "foobar"; \
- CheckMessage(cap2, android::base::severity, "foobar: No such file or directory"); \
+ { \
+ android::base::ScopedLogSeverity sls2(android::base::severity); \
+ CapturedStderr cap2; \
+ errno = ENOENT; \
+ PLOG(severity) << "foobar"; \
+ CheckMessage(cap2, android::base::severity, "foobar: No such file or directory"); \
+ } \
+ { \
+ android::base::ScopedLogSeverity sls2(android::base::severity); \
+ CapturedStderr cap2; \
+ errno = ENOENT; \
+ PLOG(severity) << "foobar"; \
+ CheckMessage(cap2, android::base::severity, "foobar: No such file or directory"); \
+ } \
TEST(logging, PLOG_FATAL) {
ASSERT_DEATH({SuppressAbortUI(); PLOG(FATAL) << "foobar";}, "foobar");
+ ASSERT_DEATH({SuppressAbortUI(); PLOG(::android::base::FATAL) << "foobar";}, "foobar");
}
TEST(logging, PLOG_FATAL_WITHOUT_ABORT_disabled) {
@@ -344,6 +574,10 @@
CHECK_PLOG_ENABLED(VERBOSE);
}
+#undef CHECK_PLOG_DISABLED
+#undef CHECK_PLOG_ENABLED
+
+
TEST(logging, UNIMPLEMENTED) {
std::string expected = android::base::StringPrintf("%s unimplemented ", __PRETTY_FUNCTION__);
diff --git a/base/properties.cpp b/base/properties.cpp
new file mode 100644
index 0000000..fab3005
--- /dev/null
+++ b/base/properties.cpp
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+#include "android-base/properties.h"
+
+#include <sys/system_properties.h>
+
+#include <string>
+
+#include <android-base/parseint.h>
+
+namespace android {
+namespace base {
+
+std::string GetProperty(const std::string& key, const std::string& default_value) {
+ const prop_info* pi = __system_property_find(key.c_str());
+ if (pi == nullptr) return default_value;
+
+ char buf[PROP_VALUE_MAX];
+ if (__system_property_read(pi, nullptr, buf) > 0) return buf;
+
+ // If the property exists but is empty, also return the default value.
+ // Since we can't remove system properties, "empty" is traditionally
+ // the same as "missing" (this was true for cutils' property_get).
+ return default_value;
+}
+
+bool GetBoolProperty(const std::string& key, bool default_value) {
+ std::string value = GetProperty(key, "");
+ if (value == "1" || value == "y" || value == "yes" || value == "on" || value == "true") {
+ return true;
+ } else if (value == "0" || value == "n" || value == "no" || value == "off" || value == "false") {
+ return false;
+ }
+ return default_value;
+}
+
+template <typename T>
+T GetIntProperty(const std::string& key, T default_value, T min, T max) {
+ T result;
+ std::string value = GetProperty(key, "");
+ if (!value.empty() && android::base::ParseInt(value.c_str(), &result, min, max)) return result;
+ return default_value;
+}
+
+template <typename T>
+T GetUintProperty(const std::string& key, T default_value, T max) {
+ T result;
+ std::string value = GetProperty(key, "");
+ if (!value.empty() && android::base::ParseUint(value.c_str(), &result, max)) return result;
+ return default_value;
+}
+
+template int8_t GetIntProperty(const std::string&, int8_t, int8_t, int8_t);
+template int16_t GetIntProperty(const std::string&, int16_t, int16_t, int16_t);
+template int32_t GetIntProperty(const std::string&, int32_t, int32_t, int32_t);
+template int64_t GetIntProperty(const std::string&, int64_t, int64_t, int64_t);
+
+template uint8_t GetUintProperty(const std::string&, uint8_t, uint8_t);
+template uint16_t GetUintProperty(const std::string&, uint16_t, uint16_t);
+template uint32_t GetUintProperty(const std::string&, uint32_t, uint32_t);
+template uint64_t GetUintProperty(const std::string&, uint64_t, uint64_t);
+
+bool SetProperty(const std::string& key, const std::string& value) {
+ return (__system_property_set(key.c_str(), value.c_str()) == 0);
+}
+
+} // namespace base
+} // namespace android
diff --git a/base/properties_test.cpp b/base/properties_test.cpp
new file mode 100644
index 0000000..da89ec5
--- /dev/null
+++ b/base/properties_test.cpp
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+
+#include "android-base/properties.h"
+
+#include <gtest/gtest.h>
+
+#include <string>
+
+TEST(properties, smoke) {
+ android::base::SetProperty("debug.libbase.property_test", "hello");
+
+ std::string s = android::base::GetProperty("debug.libbase.property_test", "");
+ ASSERT_EQ("hello", s);
+
+ android::base::SetProperty("debug.libbase.property_test", "world");
+ s = android::base::GetProperty("debug.libbase.property_test", "");
+ ASSERT_EQ("world", s);
+
+ s = android::base::GetProperty("this.property.does.not.exist", "");
+ ASSERT_EQ("", s);
+
+ s = android::base::GetProperty("this.property.does.not.exist", "default");
+ ASSERT_EQ("default", s);
+}
+
+TEST(properties, empty) {
+ // Because you can't delete a property, people "delete" them by
+ // setting them to the empty string. In that case we'd want to
+ // keep the default value (like cutils' property_get did).
+ android::base::SetProperty("debug.libbase.property_test", "");
+ std::string s = android::base::GetProperty("debug.libbase.property_test", "default");
+ ASSERT_EQ("default", s);
+}
+
+static void CheckGetBoolProperty(bool expected, const std::string& value, bool default_value) {
+ android::base::SetProperty("debug.libbase.property_test", value.c_str());
+ ASSERT_EQ(expected, android::base::GetBoolProperty("debug.libbase.property_test", default_value));
+}
+
+TEST(properties, GetBoolProperty_true) {
+ CheckGetBoolProperty(true, "1", false);
+ CheckGetBoolProperty(true, "y", false);
+ CheckGetBoolProperty(true, "yes", false);
+ CheckGetBoolProperty(true, "on", false);
+ CheckGetBoolProperty(true, "true", false);
+}
+
+TEST(properties, GetBoolProperty_false) {
+ CheckGetBoolProperty(false, "0", true);
+ CheckGetBoolProperty(false, "n", true);
+ CheckGetBoolProperty(false, "no", true);
+ CheckGetBoolProperty(false, "off", true);
+ CheckGetBoolProperty(false, "false", true);
+}
+
+TEST(properties, GetBoolProperty_default) {
+ CheckGetBoolProperty(true, "burp", true);
+ CheckGetBoolProperty(false, "burp", false);
+}
+
+template <typename T> void CheckGetIntProperty() {
+ // Positive and negative.
+ android::base::SetProperty("debug.libbase.property_test", "-12");
+ EXPECT_EQ(T(-12), android::base::GetIntProperty<T>("debug.libbase.property_test", 45));
+ android::base::SetProperty("debug.libbase.property_test", "12");
+ EXPECT_EQ(T(12), android::base::GetIntProperty<T>("debug.libbase.property_test", 45));
+
+ // Default value.
+ android::base::SetProperty("debug.libbase.property_test", "");
+ EXPECT_EQ(T(45), android::base::GetIntProperty<T>("debug.libbase.property_test", 45));
+
+ // Bounds checks.
+ android::base::SetProperty("debug.libbase.property_test", "0");
+ EXPECT_EQ(T(45), android::base::GetIntProperty<T>("debug.libbase.property_test", 45, 1, 2));
+ android::base::SetProperty("debug.libbase.property_test", "1");
+ EXPECT_EQ(T(1), android::base::GetIntProperty<T>("debug.libbase.property_test", 45, 1, 2));
+ android::base::SetProperty("debug.libbase.property_test", "2");
+ EXPECT_EQ(T(2), android::base::GetIntProperty<T>("debug.libbase.property_test", 45, 1, 2));
+ android::base::SetProperty("debug.libbase.property_test", "3");
+ EXPECT_EQ(T(45), android::base::GetIntProperty<T>("debug.libbase.property_test", 45, 1, 2));
+}
+
+template <typename T> void CheckGetUintProperty() {
+ // Positive.
+ android::base::SetProperty("debug.libbase.property_test", "12");
+ EXPECT_EQ(T(12), android::base::GetUintProperty<T>("debug.libbase.property_test", 45));
+
+ // Default value.
+ android::base::SetProperty("debug.libbase.property_test", "");
+ EXPECT_EQ(T(45), android::base::GetUintProperty<T>("debug.libbase.property_test", 45));
+
+ // Bounds checks.
+ android::base::SetProperty("debug.libbase.property_test", "12");
+ EXPECT_EQ(T(12), android::base::GetUintProperty<T>("debug.libbase.property_test", 33, 22));
+ android::base::SetProperty("debug.libbase.property_test", "12");
+ EXPECT_EQ(T(5), android::base::GetUintProperty<T>("debug.libbase.property_test", 5, 10));
+}
+
+TEST(properties, GetIntProperty_int8_t) { CheckGetIntProperty<int8_t>(); }
+TEST(properties, GetIntProperty_int16_t) { CheckGetIntProperty<int16_t>(); }
+TEST(properties, GetIntProperty_int32_t) { CheckGetIntProperty<int32_t>(); }
+TEST(properties, GetIntProperty_int64_t) { CheckGetIntProperty<int64_t>(); }
+
+TEST(properties, GetUintProperty_uint8_t) { CheckGetUintProperty<uint8_t>(); }
+TEST(properties, GetUintProperty_uint16_t) { CheckGetUintProperty<uint16_t>(); }
+TEST(properties, GetUintProperty_uint32_t) { CheckGetUintProperty<uint32_t>(); }
+TEST(properties, GetUintProperty_uint64_t) { CheckGetUintProperty<uint64_t>(); }
diff --git a/base/quick_exit.cpp b/base/quick_exit.cpp
index fa67122..e4dd62b 100644
--- a/base/quick_exit.cpp
+++ b/base/quick_exit.cpp
@@ -21,8 +21,6 @@
#include <mutex>
#include <vector>
-#include "android-base/mutex.h"
-
namespace android {
namespace base {
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 987ba83..d6b631f 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -402,6 +402,9 @@
" --skip-secondary Will not flash secondary slots when\n"
" performing a flashall or update. This\n"
" will preserve data on other slots.\n"
+ " --skip-reboot Will not reboot the device when\n"
+ " performing commands that normally\n"
+ " trigger a reboot.\n"
#if !defined(_WIN32)
" --wipe-and-use-fbe On devices which support it,\n"
" erase userdata and cache, and\n"
@@ -1392,6 +1395,7 @@
bool wants_wipe = false;
bool wants_reboot = false;
bool wants_reboot_bootloader = false;
+ bool skip_reboot = false;
bool wants_set_active = false;
bool skip_secondary = false;
bool erase_first = true;
@@ -1419,6 +1423,7 @@
{"set_active", optional_argument, 0, 'a'},
{"set-active", optional_argument, 0, 'a'},
{"skip-secondary", no_argument, 0, 0},
+ {"skip-reboot", no_argument, 0, 0},
#if !defined(_WIN32)
{"wipe-and-use-fbe", no_argument, 0, 0},
#endif
@@ -1505,6 +1510,8 @@
slot_override = std::string(optarg);
} else if (strcmp("skip-secondary", longopts[longindex].name) == 0 ) {
skip_secondary = true;
+ } else if (strcmp("skip-reboot", longopts[longindex].name) == 0 ) {
+ skip_reboot = true;
#if !defined(_WIN32)
} else if (strcmp("wipe-and-use-fbe", longopts[longindex].name) == 0) {
wants_wipe = true;
@@ -1729,7 +1736,7 @@
do_update(transport, "update.zip", slot_override, erase_first, skip_secondary || slot_all);
skip(1);
}
- wants_reboot = 1;
+ wants_reboot = true;
} else if(!strcmp(*argv, "set_active")) {
require(2);
std::string slot = verify_slot(transport, std::string(argv[1]), false);
@@ -1784,7 +1791,7 @@
if (wants_set_active) {
fb_set_active(next_active.c_str());
}
- if (wants_reboot) {
+ if (wants_reboot && !skip_reboot) {
fb_queue_reboot();
fb_queue_wait_for_disconnect();
} else if (wants_reboot_bootloader) {
diff --git a/include/cutils/native_handle.h b/include/cutils/native_handle.h
index 268c5d3..31695cb 100644
--- a/include/cutils/native_handle.h
+++ b/include/cutils/native_handle.h
@@ -26,7 +26,14 @@
int version; /* sizeof(native_handle_t) */
int numFds; /* number of file-descriptors at &data[0] */
int numInts; /* number of ints at &data[numFds] */
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wzero-length-array"
+#endif
int data[0]; /* numFds + numInts ints */
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
} native_handle_t;
/*
diff --git a/include/cutils/sockets.h b/include/cutils/sockets.h
index 783bd0b..a93c8ea 100644
--- a/include/cutils/sockets.h
+++ b/include/cutils/sockets.h
@@ -18,6 +18,7 @@
#define __CUTILS_SOCKETS_H
#include <errno.h>
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -51,28 +52,8 @@
* android_get_control_socket - simple helper function to get the file
* descriptor of our init-managed Unix domain socket. `name' is the name of the
* socket, as given in init.rc. Returns -1 on error.
- *
- * This is inline and not in libcutils proper because we want to use this in
- * third-party daemons with minimal modification.
*/
-static inline int android_get_control_socket(const char* name)
-{
- char key[64];
- snprintf(key, sizeof(key), ANDROID_SOCKET_ENV_PREFIX "%s", name);
-
- const char* val = getenv(key);
- if (!val) {
- return -1;
- }
-
- errno = 0;
- int fd = strtol(val, NULL, 10);
- if (errno) {
- return -1;
- }
-
- return fd;
-}
+int android_get_control_socket(const char* name);
/*
* See also android.os.LocalSocketAddress.Namespace
diff --git a/include/cutils/trace.h b/include/cutils/trace.h
index c9790ad..dc3833f 100644
--- a/include/cutils/trace.h
+++ b/include/cutils/trace.h
@@ -188,8 +188,8 @@
static inline void atrace_end(uint64_t tag)
{
if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
- char c = 'E';
- write(atrace_marker_fd, &c, 1);
+ void atrace_end_body();
+ atrace_end_body();
}
}
diff --git a/include/log/event_tag_map.h b/include/log/event_tag_map.h
index 1653c61..7ee0a7c 100644
--- a/include/log/event_tag_map.h
+++ b/include/log/event_tag_map.h
@@ -41,7 +41,7 @@
/*
* Look up a tag by index. Returns the tag string, or NULL if not found.
*/
-const char* android_lookupEventTag(const EventTagMap* map, int tag);
+const char* android_lookupEventTag(const EventTagMap* map, unsigned int tag);
#ifdef __cplusplus
}
diff --git a/include/log/log.h b/include/log/log.h
index 045feca..24c77fc 100644
--- a/include/log/log.h
+++ b/include/log/log.h
@@ -41,6 +41,15 @@
extern "C" {
#endif
+// This file uses ", ## __VA_ARGS__" zero-argument token pasting to
+// work around issues with debug-only syntax errors in assertions
+// that are missing format strings. See commit
+// 19299904343daf191267564fe32e6cd5c165cd42
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
+#endif
+
// ---------------------------------------------------------------------
/*
@@ -692,6 +701,10 @@
#endif
;
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index bc1c0ca..167a6d9 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -115,7 +115,6 @@
#define AID_NET_ADMIN 3005 /* can configure interfaces and routing tables. */
#define AID_NET_BW_STATS 3006 /* read bandwidth statistics */
#define AID_NET_BW_ACCT 3007 /* change bandwidth statistics accounting */
-#define AID_NET_BT_STACK 3008 /* bluetooth: access config files */
#define AID_READPROC 3009 /* Allow /proc read access */
#define AID_WAKELOCK 3010 /* Allow system wakelock read/write access */
@@ -221,7 +220,6 @@
{ "net_admin", AID_NET_ADMIN, },
{ "net_bw_stats", AID_NET_BW_STATS, },
{ "net_bw_acct", AID_NET_BW_ACCT, },
- { "net_bt_stack", AID_NET_BT_STACK, },
{ "readproc", AID_READPROC, },
{ "wakelock", AID_WAKELOCK, },
diff --git a/include/system/graphics.h b/include/system/graphics.h
index 529a562..ae10fa0 100644
--- a/include/system/graphics.h
+++ b/include/system/graphics.h
@@ -452,15 +452,15 @@
*
* Buffers must have a 8 bit depth.
*
- * @y, @cb, and @cr point to the first byte of their respective planes.
+ * y, cb, and cr point to the first byte of their respective planes.
*
* Stride describes the distance in bytes from the first value of one row of
* the image to the first value of the next row. It includes the width of the
* image plus padding.
- * @ystride is the stride of the luma plane.
- * @cstride is the stride of the chroma planes.
+ * ystride is the stride of the luma plane.
+ * cstride is the stride of the chroma planes.
*
- * @chroma_step is the distance in bytes from one chroma pixel value to the
+ * chroma_step is the distance in bytes from one chroma pixel value to the
* next. This is 2 bytes for semiplanar (because chroma values are interleaved
* and each chroma value is one byte) and 1 for planar.
*/
@@ -585,9 +585,9 @@
* measurement is correct. It is between 0.f and 1.f, inclusive, with 1.f ==
* 100% confidence.
*
- * @num_points is the number of points in the list
+ * num_points is the number of points in the list
*
- * @xyz_points is the flexible array of floating-point values.
+ * xyz_points is the flexible array of floating-point values.
* It contains (num_points) * 4 floats.
*
* For example:
@@ -612,7 +612,14 @@
/** reserved for future use, set to 0 by gralloc's (*lock)() */
uint32_t reserved[8];
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wc99-extensions"
+#endif
float xyzc_points[];
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
};
/**
diff --git a/include/system/qemu_pipe.h b/include/system/qemu_pipe.h
index d403f8d..40a5b50 100644
--- a/include/system/qemu_pipe.h
+++ b/include/system/qemu_pipe.h
@@ -85,7 +85,7 @@
const void* buff,
size_t len) {
char header[5];
- snprintf(header, sizeof(header), "%04x", len);
+ snprintf(header, sizeof(header), "%04zu", len);
ssize_t ret = TEMP_FAILURE_RETRY(write(fd, header, 4));
if (ret != 4) {
QEMU_PIPE_DEBUG("Can't write qemud frame header: %s", strerror(errno));
@@ -123,7 +123,7 @@
return -1;
}
ret = TEMP_FAILURE_RETRY(read(fd, buff, size));
- if (ret != size) {
+ if (ret != (ssize_t)size) {
QEMU_PIPE_DEBUG("Could not read qemud frame payload: %s",
strerror(errno));
return -1;
diff --git a/include/system/radio.h b/include/system/radio.h
index 9e291c8..d73d3ae 100644
--- a/include/system/radio.h
+++ b/include/system/radio.h
@@ -218,7 +218,8 @@
} radio_event_t;
-static radio_rds_t radio_rds_for_region(bool rds, radio_region_t region) {
+static inline
+radio_rds_t radio_rds_for_region(bool rds, radio_region_t region) {
if (!rds)
return RADIO_RDS_NONE;
switch(region) {
@@ -234,7 +235,8 @@
}
}
-static radio_deemphasis_t radio_demephasis_for_region(radio_region_t region) {
+static inline
+radio_deemphasis_t radio_demephasis_for_region(radio_region_t region) {
switch(region) {
case RADIO_REGION_KOREA:
case RADIO_REGION_ITU_2:
diff --git a/include/system/window.h b/include/system/window.h
index b8f33ff..49ab4dc 100644
--- a/include/system/window.h
+++ b/include/system/window.h
@@ -38,8 +38,17 @@
/*****************************************************************************/
+#ifdef __cplusplus
+#define ANDROID_NATIVE_UNSIGNED_CAST(x) static_cast<unsigned int>(x)
+#else
+#define ANDROID_NATIVE_UNSIGNED_CAST(x) ((unsigned int)(x))
+#endif
+
#define ANDROID_NATIVE_MAKE_CONSTANT(a,b,c,d) \
- (((unsigned)(a)<<24)|((unsigned)(b)<<16)|((unsigned)(c)<<8)|(unsigned)(d))
+ ((ANDROID_NATIVE_UNSIGNED_CAST(a) << 24) | \
+ (ANDROID_NATIVE_UNSIGNED_CAST(b) << 16) | \
+ (ANDROID_NATIVE_UNSIGNED_CAST(c) << 8) | \
+ (ANDROID_NATIVE_UNSIGNED_CAST(d)))
#define ANDROID_NATIVE_WINDOW_MAGIC \
ANDROID_NATIVE_MAKE_CONSTANT('_','w','n','d')
diff --git a/include/utils/Compat.h b/include/utils/Compat.h
index b2ba55e..2709e3b 100644
--- a/include/utils/Compat.h
+++ b/include/utils/Compat.h
@@ -45,13 +45,8 @@
#define DEFFILEMODE 0666
#endif /* _WIN32 */
-#if defined(_WIN32)
-#define ZD "%ld"
-#define ZD_TYPE long
-#else
#define ZD "%zd"
#define ZD_TYPE ssize_t
-#endif
/*
* Needed for cases where something should be constexpr if possible, but not
diff --git a/include/utils/Condition.h b/include/utils/Condition.h
index 5650598..25a53aa 100644
--- a/include/utils/Condition.h
+++ b/include/utils/Condition.h
@@ -17,6 +17,7 @@
#ifndef _LIBS_UTILS_CONDITION_H
#define _LIBS_UTILS_CONDITION_H
+#include <limits.h>
#include <stdint.h>
#include <sys/types.h>
#include <time.h>
@@ -120,7 +121,7 @@
// On 32-bit devices, tv_sec is 32-bit, but `reltime` is 64-bit.
int64_t reltime_sec = reltime/1000000000;
- ts.tv_nsec += reltime%1000000000;
+ ts.tv_nsec += static_cast<long>(reltime%1000000000);
if (reltime_sec < INT64_MAX && ts.tv_nsec >= 1000000000) {
ts.tv_nsec -= 1000000000;
++reltime_sec;
@@ -133,11 +134,7 @@
time_sec += reltime_sec;
}
-#if defined(__LP64__)
- ts.tv_sec = time_sec;
-#else
- ts.tv_sec = (time_sec > INT32_MAX) ? INT32_MAX : time_sec;
-#endif
+ ts.tv_sec = (time_sec > LONG_MAX) ? LONG_MAX : static_cast<long>(time_sec);
return -pthread_cond_timedwait(&mCond, &mutex.mMutex, &ts);
}
diff --git a/include/utils/Flattenable.h b/include/utils/Flattenable.h
index 882a8b2..22b811a 100644
--- a/include/utils/Flattenable.h
+++ b/include/utils/Flattenable.h
@@ -19,55 +19,62 @@
#include <stdint.h>
+#include <string.h>
#include <sys/types.h>
#include <utils/Errors.h>
#include <utils/Debug.h>
+#include <type_traits>
+
namespace android {
class FlattenableUtils {
public:
- template<int N>
+ template<size_t N>
static size_t align(size_t size) {
COMPILE_TIME_ASSERT_FUNCTION_SCOPE( !(N & (N-1)) );
return (size + (N-1)) & ~(N-1);
}
- template<int N>
+ template<size_t N>
static size_t align(void const*& buffer) {
COMPILE_TIME_ASSERT_FUNCTION_SCOPE( !(N & (N-1)) );
- intptr_t b = intptr_t(buffer);
- buffer = (void*)((intptr_t(buffer) + (N-1)) & ~(N-1));
- return size_t(intptr_t(buffer) - b);
+ uintptr_t b = uintptr_t(buffer);
+ buffer = reinterpret_cast<void*>((uintptr_t(buffer) + (N-1)) & ~(N-1));
+ return size_t(uintptr_t(buffer) - b);
}
- template<int N>
+ template<size_t N>
static size_t align(void*& buffer) {
return align<N>( const_cast<void const*&>(buffer) );
}
static void advance(void*& buffer, size_t& size, size_t offset) {
- buffer = reinterpret_cast<void*>( intptr_t(buffer) + offset );
+ buffer = reinterpret_cast<void*>( uintptr_t(buffer) + offset );
size -= offset;
}
static void advance(void const*& buffer, size_t& size, size_t offset) {
- buffer = reinterpret_cast<void const*>( intptr_t(buffer) + offset );
+ buffer = reinterpret_cast<void const*>( uintptr_t(buffer) + offset );
size -= offset;
}
// write a POD structure
template<typename T>
static void write(void*& buffer, size_t& size, const T& value) {
- *static_cast<T*>(buffer) = value;
+ static_assert(std::is_trivially_copyable<T>::value,
+ "Cannot flatten a non-trivially-copyable type");
+ memcpy(buffer, &value, sizeof(T));
advance(buffer, size, sizeof(T));
}
// read a POD structure
template<typename T>
static void read(void const*& buffer, size_t& size, T& value) {
- value = *static_cast<T const*>(buffer);
+ static_assert(std::is_trivially_copyable<T>::value,
+ "Cannot unflatten a non-trivially-copyable type");
+ memcpy(&value, buffer, sizeof(T));
advance(buffer, size, sizeof(T));
}
};
diff --git a/include/utils/KeyedVector.h b/include/utils/KeyedVector.h
index c4faae0..92579e2 100644
--- a/include/utils/KeyedVector.h
+++ b/include/utils/KeyedVector.h
@@ -97,13 +97,6 @@
SortedVector< key_value_pair_t<KEY, VALUE> > mVector;
};
-// KeyedVector<KEY, VALUE> can be trivially moved using memcpy() because its
-// underlying SortedVector can be trivially moved.
-template<typename KEY, typename VALUE> struct trait_trivial_move<KeyedVector<KEY, VALUE> > {
- enum { value = trait_trivial_move<SortedVector< key_value_pair_t<KEY, VALUE> > >::value };
-};
-
-
// ---------------------------------------------------------------------------
/**
@@ -164,7 +157,7 @@
VALUE& KeyedVector<KEY,VALUE>::editValueFor(const KEY& key) {
ssize_t i = this->indexOfKey(key);
LOG_ALWAYS_FATAL_IF(i<0, "%s: key not found", __PRETTY_FUNCTION__);
- return mVector.editItemAt(i).value;
+ return mVector.editItemAt(static_cast<size_t>(i)).value;
}
template<typename KEY, typename VALUE> inline
@@ -188,7 +181,7 @@
ssize_t KeyedVector<KEY,VALUE>::replaceValueAt(size_t index, const VALUE& item) {
if (index<size()) {
mVector.editItemAt(index).value = item;
- return index;
+ return static_cast<ssize_t>(index);
}
return BAD_INDEX;
}
diff --git a/include/utils/Looper.h b/include/utils/Looper.h
index da2d5f2..a62e67f 100644
--- a/include/utils/Looper.h
+++ b/include/utils/Looper.h
@@ -49,7 +49,7 @@
*/
struct Message {
Message() : what(0) { }
- Message(int what) : what(what) { }
+ Message(int w) : what(w) { }
/* The message type. (interpretation is left up to the handler) */
int what;
@@ -66,7 +66,7 @@
*/
class MessageHandler : public virtual RefBase {
protected:
- virtual ~MessageHandler() { }
+ virtual ~MessageHandler();
public:
/**
@@ -97,7 +97,7 @@
*/
class LooperCallback : public virtual RefBase {
protected:
- virtual ~LooperCallback() { }
+ virtual ~LooperCallback();
public:
/**
@@ -436,8 +436,8 @@
struct MessageEnvelope {
MessageEnvelope() : uptime(0) { }
- MessageEnvelope(nsecs_t uptime, const sp<MessageHandler> handler,
- const Message& message) : uptime(uptime), handler(handler), message(message) {
+ MessageEnvelope(nsecs_t u, const sp<MessageHandler> h,
+ const Message& m) : uptime(u), handler(h), message(m) {
}
nsecs_t uptime;
diff --git a/include/utils/LruCache.h b/include/utils/LruCache.h
index f4e225a..89dccd6 100644
--- a/include/utils/LruCache.h
+++ b/include/utils/LruCache.h
@@ -166,7 +166,7 @@
, mOldest(NULL)
, mYoungest(NULL)
, mMaxCapacity(maxCapacity)
- , mNullValue(NULL) {
+ , mNullValue(0) {
mSet->max_load_factor(1.0);
};
diff --git a/include/utils/RefBase.h b/include/utils/RefBase.h
index 3c318c4..36016cd 100644
--- a/include/utils/RefBase.h
+++ b/include/utils/RefBase.h
@@ -206,6 +206,14 @@
// ---------------------------------------------------------------------------
+// RefererenceRenamer is pure abstract, there is no virtual method
+// implementation to put in a translation unit in order to silence the
+// weak vtables warning.
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wweak-vtables"
+#endif
+
class ReferenceRenamer {
protected:
// destructor is purposedly not virtual so we avoid code overhead from
@@ -217,6 +225,10 @@
virtual void operator()(size_t i) const = 0;
};
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+
// ---------------------------------------------------------------------------
class RefBase
@@ -372,7 +384,7 @@
// destructor to eliminate the template requirement of LightRefBase
class VirtualLightRefBase : public LightRefBase<VirtualLightRefBase> {
public:
- virtual ~VirtualLightRefBase() {}
+ virtual ~VirtualLightRefBase();
};
// ---------------------------------------------------------------------------
@@ -646,42 +658,42 @@
// a template<typename TYPE inherits RefBase> template...
template<typename TYPE> static inline
- void move_references(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
+ void move_references(sp<TYPE>* dest, sp<TYPE> const* src, size_t n) {
class Renamer : public ReferenceRenamer {
- sp<TYPE>* d;
- sp<TYPE> const* s;
+ sp<TYPE>* d_;
+ sp<TYPE> const* s_;
virtual void operator()(size_t i) const {
// The id are known to be the sp<>'s this pointer
- TYPE::renameRefId(d[i].get(), &s[i], &d[i]);
+ TYPE::renameRefId(d_[i].get(), &s_[i], &d_[i]);
}
public:
- Renamer(sp<TYPE>* d, sp<TYPE> const* s) : d(d), s(s) { }
+ Renamer(sp<TYPE>* d, sp<TYPE> const* s) : d_(d), s_(s) { }
virtual ~Renamer() { }
};
- memmove(d, s, n*sizeof(sp<TYPE>));
- TYPE::renameRefs(n, Renamer(d, s));
+ memmove(dest, src, n*sizeof(sp<TYPE>));
+ TYPE::renameRefs(n, Renamer(dest, src));
}
template<typename TYPE> static inline
- void move_references(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
+ void move_references(wp<TYPE>* dest, wp<TYPE> const* src, size_t n) {
class Renamer : public ReferenceRenamer {
- wp<TYPE>* d;
- wp<TYPE> const* s;
+ wp<TYPE>* d_;
+ wp<TYPE> const* s_;
virtual void operator()(size_t i) const {
// The id are known to be the wp<>'s this pointer
- TYPE::renameRefId(d[i].get_refs(), &s[i], &d[i]);
+ TYPE::renameRefId(d_[i].get_refs(), &s_[i], &d_[i]);
}
public:
- Renamer(wp<TYPE>* d, wp<TYPE> const* s) : d(d), s(s) { }
+ Renamer(wp<TYPE>* rd, wp<TYPE> const* rs) : d_(rd), s_(rs) { }
virtual ~Renamer() { }
};
- memmove(d, s, n*sizeof(wp<TYPE>));
- TYPE::renameRefs(n, Renamer(d, s));
+ memmove(dest, src, n*sizeof(wp<TYPE>));
+ TYPE::renameRefs(n, Renamer(dest, src));
}
};
@@ -712,7 +724,6 @@
ReferenceMover::move_references(d, s, n);
}
-
}; // namespace android
// ---------------------------------------------------------------------------
diff --git a/include/utils/Singleton.h b/include/utils/Singleton.h
index ffc03cb..7cc4c18 100644
--- a/include/utils/Singleton.h
+++ b/include/utils/Singleton.h
@@ -19,6 +19,7 @@
#include <stdint.h>
#include <sys/types.h>
+#include <utils/Mutex.h>
#include <utils/threads.h>
#include <cutils/compiler.h>
@@ -45,8 +46,8 @@
}
protected:
- ~Singleton() { };
- Singleton() { };
+ ~Singleton() { }
+ Singleton() { }
private:
Singleton(const Singleton&);
@@ -55,6 +56,12 @@
static TYPE* sInstance;
};
+template <typename TYPE>
+Mutex Singleton<TYPE>::sLock;
+
+template <typename TYPE>
+TYPE* Singleton<TYPE>::sInstance;
+
/*
* use ANDROID_SINGLETON_STATIC_INSTANCE(TYPE) in your implementation file
* (eg: <TYPE>.cpp) to create the static instance of Singleton<>'s attributes,
diff --git a/include/utils/SortedVector.h b/include/utils/SortedVector.h
index 2d3e82a..ea0f82c 100644
--- a/include/utils/SortedVector.h
+++ b/include/utils/SortedVector.h
@@ -133,10 +133,6 @@
virtual int do_compare(const void* lhs, const void* rhs) const;
};
-// SortedVector<T> can be trivially moved using memcpy() because moving does not
-// require any change to the underlying SharedBuffer contents or reference count.
-template<typename T> struct trait_trivial_move<SortedVector<T> > { enum { value = true }; };
-
// ---------------------------------------------------------------------------
// No user serviceable parts from here...
// ---------------------------------------------------------------------------
diff --git a/include/utils/StrongPointer.h b/include/utils/StrongPointer.h
index d90b788..294e6b6 100644
--- a/include/utils/StrongPointer.h
+++ b/include/utils/StrongPointer.h
@@ -137,7 +137,7 @@
sp<T>::sp(U* other)
: m_ptr(other) {
if (other)
- ((T*) other)->incStrong(this);
+ (static_cast<T*>(other))->incStrong(this);
}
template<typename T> template<typename U>
@@ -212,7 +212,7 @@
template<typename T> template<typename U>
sp<T>& sp<T>::operator =(U* other) {
if (other)
- ((T*) other)->incStrong(this);
+ (static_cast<T*>(other))->incStrong(this);
if (m_ptr)
m_ptr->decStrong(this);
m_ptr = other;
diff --git a/include/utils/TypeHelpers.h b/include/utils/TypeHelpers.h
index 64d25c5..2a25227 100644
--- a/include/utils/TypeHelpers.h
+++ b/include/utils/TypeHelpers.h
@@ -18,6 +18,8 @@
#define ANDROID_TYPE_HELPERS_H
#include <new>
+#include <type_traits>
+
#include <stdint.h>
#include <string.h>
#include <sys/types.h>
@@ -149,16 +151,21 @@
}
}
-template<typename TYPE> inline
-void copy_type(TYPE* d, const TYPE* s, size_t n) {
- if (!traits<TYPE>::has_trivial_copy) {
- while (n > 0) {
- n--;
- new(d) TYPE(*s);
- d++, s++;
- }
- } else {
- memcpy(d,s,n*sizeof(TYPE));
+template<typename TYPE>
+typename std::enable_if<traits<TYPE>::has_trivial_copy>::type
+inline
+copy_type(TYPE* d, const TYPE* s, size_t n) {
+ memcpy(d,s,n*sizeof(TYPE));
+}
+
+template<typename TYPE>
+typename std::enable_if<!traits<TYPE>::has_trivial_copy>::type
+inline
+copy_type(TYPE* d, const TYPE* s, size_t n) {
+ while (n > 0) {
+ n--;
+ new(d) TYPE(*s);
+ d++, s++;
}
}
@@ -178,49 +185,61 @@
}
}
-template<typename TYPE> inline
-void move_forward_type(TYPE* d, const TYPE* s, size_t n = 1) {
- if ((traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy)
- || traits<TYPE>::has_trivial_move)
- {
- memmove(d,s,n*sizeof(TYPE));
- } else {
- d += n;
- s += n;
- while (n > 0) {
- n--;
- --d, --s;
- if (!traits<TYPE>::has_trivial_copy) {
- new(d) TYPE(*s);
- } else {
- *d = *s;
- }
- if (!traits<TYPE>::has_trivial_dtor) {
- s->~TYPE();
- }
+template<typename TYPE>
+struct use_trivial_move : public std::integral_constant<bool,
+ (traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy)
+ || traits<TYPE>::has_trivial_move
+> {};
+
+template<typename TYPE>
+typename std::enable_if<use_trivial_move<TYPE>::value>::type
+inline
+move_forward_type(TYPE* d, const TYPE* s, size_t n = 1) {
+ memmove(d, s, n*sizeof(TYPE));
+}
+
+template<typename TYPE>
+typename std::enable_if<!use_trivial_move<TYPE>::value>::type
+inline
+move_forward_type(TYPE* d, const TYPE* s, size_t n = 1) {
+ d += n;
+ s += n;
+ while (n > 0) {
+ n--;
+ --d, --s;
+ if (!traits<TYPE>::has_trivial_copy) {
+ new(d) TYPE(*s);
+ } else {
+ *d = *s;
+ }
+ if (!traits<TYPE>::has_trivial_dtor) {
+ s->~TYPE();
}
}
}
-template<typename TYPE> inline
-void move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) {
- if ((traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy)
- || traits<TYPE>::has_trivial_move)
- {
- memmove(d,s,n*sizeof(TYPE));
- } else {
- while (n > 0) {
- n--;
- if (!traits<TYPE>::has_trivial_copy) {
- new(d) TYPE(*s);
- } else {
- *d = *s;
- }
- if (!traits<TYPE>::has_trivial_dtor) {
- s->~TYPE();
- }
- d++, s++;
+template<typename TYPE>
+typename std::enable_if<use_trivial_move<TYPE>::value>::type
+inline
+move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) {
+ memmove(d, s, n*sizeof(TYPE));
+}
+
+template<typename TYPE>
+typename std::enable_if<!use_trivial_move<TYPE>::value>::type
+inline
+move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) {
+ while (n > 0) {
+ n--;
+ if (!traits<TYPE>::has_trivial_copy) {
+ new(d) TYPE(*s);
+ } else {
+ *d = *s;
}
+ if (!traits<TYPE>::has_trivial_dtor) {
+ s->~TYPE();
+ }
+ d++, s++;
}
}
@@ -239,6 +258,11 @@
VALUE value;
key_value_pair_t() { }
key_value_pair_t(const key_value_pair_t& o) : key(o.key), value(o.value) { }
+ key_value_pair_t& operator=(const key_value_pair_t& o) {
+ key = o.key;
+ value = o.value;
+ return *this;
+ }
key_value_pair_t(const KEY& k, const VALUE& v) : key(k), value(v) { }
explicit key_value_pair_t(const KEY& k) : key(k) { }
inline bool operator < (const key_value_pair_t& o) const {
@@ -275,8 +299,7 @@
template <typename TKey>
hash_t hash_type(const TKey& key);
-/* Built-in hash code specializations.
- * Assumes pointers are 32bit. */
+/* Built-in hash code specializations */
#define ANDROID_INT32_HASH(T) \
template <> inline hash_t hash_type(const T& value) { return hash_t(value); }
#define ANDROID_INT64_HASH(T) \
@@ -284,7 +307,11 @@
return hash_t((value >> 32) ^ value); }
#define ANDROID_REINTERPRET_HASH(T, R) \
template <> inline hash_t hash_type(const T& value) { \
- return hash_type(*reinterpret_cast<const R*>(&value)); }
+ R newValue; \
+ static_assert(sizeof(newValue) == sizeof(value), "size mismatch"); \
+ memcpy(&newValue, &value, sizeof(newValue)); \
+ return hash_type(newValue); \
+ }
ANDROID_INT32_HASH(bool)
ANDROID_INT32_HASH(int8_t)
diff --git a/include/utils/Unicode.h b/include/utils/Unicode.h
index a13f347..666b70f 100644
--- a/include/utils/Unicode.h
+++ b/include/utils/Unicode.h
@@ -60,6 +60,7 @@
* Returns the size actually used for storing the string.
* dst" is not nul-terminated when dst_len is fully used (like strncpy).
*
+ * \code
* Example 1
* "src" == \u3042\u3044 (\xE3\x81\x82\xE3\x81\x84)
* "src_len" == 2
@@ -87,6 +88,7 @@
* Returned value == 6
* "dst" becomes \xE3\x81\x82\xE3\x81\x84
* (note that "dst" is NOT nul-terminated, like strncpy)
+ * \endcode
*/
void utf32_to_utf8(const char32_t* src, size_t src_len, char* dst, size_t dst_len);
diff --git a/include/utils/Vector.h b/include/utils/Vector.h
index ed7b725..b6d5686 100644
--- a/include/utils/Vector.h
+++ b/include/utils/Vector.h
@@ -194,7 +194,7 @@
inline void push_back(const TYPE& item) { insertAt(item, size(), 1); }
inline void push_front(const TYPE& item) { insertAt(item, 0, 1); }
inline iterator erase(iterator pos) {
- ssize_t index = removeItemsAt(pos-array());
+ ssize_t index = removeItemsAt(static_cast<size_t>(pos-array()));
return begin() + index;
}
@@ -207,10 +207,6 @@
virtual void do_move_backward(void* dest, const void* from, size_t num) const;
};
-// Vector<T> can be trivially moved using memcpy() because moving does not
-// require any change to the underlying SharedBuffer contents or reference count.
-template<typename T> struct trait_trivial_move<Vector<T> > { enum { value = true }; };
-
// ---------------------------------------------------------------------------
// No user serviceable parts from here...
// ---------------------------------------------------------------------------
@@ -375,12 +371,12 @@
template<class TYPE> inline
status_t Vector<TYPE>::sort(Vector<TYPE>::compar_t cmp) {
- return VectorImpl::sort((VectorImpl::compar_t)cmp);
+ return VectorImpl::sort(reinterpret_cast<VectorImpl::compar_t>(cmp));
}
template<class TYPE> inline
status_t Vector<TYPE>::sort(Vector<TYPE>::compar_r_t cmp, void* state) {
- return VectorImpl::sort((VectorImpl::compar_r_t)cmp, state);
+ return VectorImpl::sort(reinterpret_cast<VectorImpl::compar_r_t>(cmp), state);
}
// ---------------------------------------------------------------------------
diff --git a/include/ziparchive/zip_archive.h b/include/ziparchive/zip_archive.h
index 7dc60ae..4f68c3b 100644
--- a/include/ziparchive/zip_archive.h
+++ b/include/ziparchive/zip_archive.h
@@ -43,8 +43,7 @@
/*
* entry_name has to be an c-style string with only ASCII characters.
*/
- explicit ZipString(const char* entry_name)
- : name(reinterpret_cast<const uint8_t*>(entry_name)), name_length(strlen(entry_name)) {}
+ explicit ZipString(const char* entry_name);
bool operator==(const ZipString& rhs) const {
return name && (name_length == rhs.name_length) &&
diff --git a/libcutils/fs_config.c b/libcutils/fs_config.c
index 2922ec4..0b0e2c7 100644
--- a/libcutils/fs_config.c
+++ b/libcutils/fs_config.c
@@ -146,6 +146,9 @@
{ 00755, AID_WIFI, AID_WIFI, CAP_MASK_LONG(CAP_NET_ADMIN) |
CAP_MASK_LONG(CAP_NET_RAW), "system/bin/hostapd" },
+ /* Support wifi_hal_legacy administering a network interface. */
+ { 00755, AID_WIFI, AID_WIFI, CAP_MASK_LONG(CAP_NET_ADMIN) | CAP_MASK_LONG(CAP_NET_RAW), "system/bin/hw/wifi_hal_legacy" },
+
{ 00750, AID_ROOT, AID_ROOT, 0, "system/bin/uncrypt" },
{ 00750, AID_ROOT, AID_ROOT, 0, "system/bin/install-recovery.sh" },
{ 00755, AID_ROOT, AID_SHELL, 0, "system/bin/*" },
diff --git a/libcutils/socket_network_client_unix.c b/libcutils/socket_network_client_unix.c
index 46818d6..37851b1 100644
--- a/libcutils/socket_network_client_unix.c
+++ b/libcutils/socket_network_client_unix.c
@@ -112,6 +112,7 @@
}
result = toggle_O_NONBLOCK(s);
+ break;
}
freeaddrinfo(addrs);
diff --git a/libcutils/sockets.cpp b/libcutils/sockets.cpp
index d9ab146..bba63ac 100644
--- a/libcutils/sockets.cpp
+++ b/libcutils/sockets.cpp
@@ -45,3 +45,24 @@
}
return -1;
}
+
+int android_get_control_socket(const char* name) {
+ char key[64];
+ snprintf(key, sizeof(key), ANDROID_SOCKET_ENV_PREFIX "%s", name);
+
+ const char* val = getenv(key);
+ if (!val) {
+ return -1;
+ }
+
+ errno = 0;
+ long ret = strtol(val, NULL, 10);
+ if (errno) {
+ return -1;
+ }
+ if (ret < 0 || ret > INT_MAX) {
+ return -1;
+ }
+
+ return static_cast<int>(ret);
+}
diff --git a/libcutils/trace-dev.c b/libcutils/trace-dev.c
index 778e4f0..099ab45 100644
--- a/libcutils/trace-dev.c
+++ b/libcutils/trace-dev.c
@@ -196,6 +196,12 @@
write(atrace_marker_fd, buf, len);
}
+void atrace_end_body()
+{
+ char c = 'E';
+ write(atrace_marker_fd, &c, 1);
+}
+
#define WRITE_MSG(format_begin, format_end, pid, name, value) { \
char buf[ATRACE_MESSAGE_LENGTH]; \
int len = snprintf(buf, sizeof(buf), format_begin "%s" format_end, pid, \
diff --git a/libcutils/trace-host.c b/libcutils/trace-host.c
index 6478e3e..05842cd 100644
--- a/libcutils/trace-host.c
+++ b/libcutils/trace-host.c
@@ -29,6 +29,7 @@
void atrace_update_tags() { }
void atrace_setup() { }
void atrace_begin_body(const char* name __unused) { }
+void atrace_end_body() { }
void atrace_async_begin_body(const char* name __unused, int32_t cookie __unused) { }
void atrace_async_end_body(const char* name __unused, int32_t cookie __unused) { }
void atrace_int_body(const char* name __unused, int32_t value __unused) { }
diff --git a/liblog/Android.bp b/liblog/Android.bp
index e32f73c..ba7cc8a 100644
--- a/liblog/Android.bp
+++ b/liblog/Android.bp
@@ -91,3 +91,9 @@
compile_multilib: "both",
stl: "none",
}
+
+ndk_library {
+ name: "liblog.ndk",
+ symbol_file: "liblog.map.txt",
+ first_version: "9",
+}
diff --git a/liblog/event_tag_map.c b/liblog/event_tag_map.c
index 345f0d3..c8943e0 100644
--- a/liblog/event_tag_map.c
+++ b/liblog/event_tag_map.c
@@ -15,8 +15,10 @@
*/
#include <assert.h>
+#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
+#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
@@ -32,8 +34,8 @@
* Single entry.
*/
typedef struct EventTag {
- unsigned int tagIndex;
- const char* tagStr;
+ uint32_t tagIndex;
+ const char* tagStr;
} EventTag;
/*
@@ -56,7 +58,6 @@
static int scanTagLine(char** pData, EventTag* tag, int lineNum);
static int sortTags(EventTagMap* map);
-
/*
* Open the map file and allocate a structure to manage it.
*
@@ -67,47 +68,57 @@
{
EventTagMap* newTagMap;
off_t end;
- int fd = -1;
+ int save_errno;
- newTagMap = calloc(1, sizeof(EventTagMap));
- if (newTagMap == NULL)
- return NULL;
-
- fd = open(fileName, O_RDONLY | O_CLOEXEC);
+ int fd = open(fileName, O_RDONLY | O_CLOEXEC);
if (fd < 0) {
+ save_errno = errno;
fprintf(stderr, "%s: unable to open map '%s': %s\n",
- OUT_TAG, fileName, strerror(errno));
- goto fail;
+ OUT_TAG, fileName, strerror(save_errno));
+ goto fail_errno;
}
end = lseek(fd, 0L, SEEK_END);
+ save_errno = errno;
(void) lseek(fd, 0L, SEEK_SET);
if (end < 0) {
- fprintf(stderr, "%s: unable to seek map '%s'\n", OUT_TAG, fileName);
- goto fail;
+ fprintf(stderr, "%s: unable to seek map '%s' %s\n",
+ OUT_TAG, fileName, strerror(save_errno));
+ goto fail_close;
}
- newTagMap->mapAddr = mmap(NULL, end, PROT_READ | PROT_WRITE, MAP_PRIVATE,
- fd, 0);
- if (newTagMap->mapAddr == MAP_FAILED) {
- fprintf(stderr, "%s: mmap(%s) failed: %s\n",
- OUT_TAG, fileName, strerror(errno));
- goto fail;
+ newTagMap = (EventTagMap*)calloc(1, sizeof(EventTagMap));
+ if (newTagMap == NULL) {
+ save_errno = errno;
+ goto fail_close;
}
+
+ newTagMap->mapAddr = mmap(NULL, end, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+ save_errno = errno;
+ close(fd);
+ fd = -1;
+ if ((newTagMap->mapAddr == MAP_FAILED) || (newTagMap->mapAddr == NULL)) {
+ fprintf(stderr, "%s: mmap(%s) failed: %s\n",
+ OUT_TAG, fileName, strerror(save_errno));
+ goto fail_free;
+ }
+
newTagMap->mapLen = end;
- if (processFile(newTagMap) != 0)
- goto fail;
-
- if (fd >= 0)
- close(fd);
+ if (processFile(newTagMap) != 0) goto fail_unmap;
return newTagMap;
+fail_unmap:
+ munmap(newTagMap->mapAddr, newTagMap->mapLen);
+ save_errno = EINVAL;
+fail_free:
+ free(newTagMap);
+fail_close:
+ close(fd);
+fail_errno:
+ errno = save_errno;
fail:
- android_closeEventTagMap(newTagMap);
- if (fd >= 0)
- close(fd);
return NULL;
}
@@ -116,10 +127,10 @@
*/
LIBLOG_ABI_PUBLIC void android_closeEventTagMap(EventTagMap* map)
{
- if (map == NULL)
- return;
+ if (map == NULL) return;
munmap(map->mapAddr, map->mapLen);
+ free(map->tagArray);
free(map);
}
@@ -129,18 +140,15 @@
* The entries are sorted by tag number, so we can do a binary search.
*/
LIBLOG_ABI_PUBLIC const char* android_lookupEventTag(const EventTagMap* map,
- int tag)
+ unsigned int tag)
{
- int hi, lo, mid;
-
- lo = 0;
- hi = map->numTags-1;
+ int lo = 0;
+ int hi = map->numTags - 1;
while (lo <= hi) {
- int cmp;
+ int mid = (lo + hi) / 2;
+ int cmp = map->tagArray[mid].tagIndex - tag;
- mid = (lo+hi)/2;
- cmp = map->tagArray[mid].tagIndex - tag;
if (cmp < 0) {
/* tag is bigger */
lo = mid + 1;
@@ -153,39 +161,10 @@
}
}
+ errno = ENOENT;
return NULL;
}
-
-
-/*
- * Determine whether "c" is a whitespace char.
- */
-static inline int isCharWhitespace(char c)
-{
- return (c == ' ' || c == '\n' || c == '\r' || c == '\t');
-}
-
-/*
- * Determine whether "c" is a valid tag char.
- */
-static inline int isCharValidTag(char c)
-{
- return ((c >= 'A' && c <= 'Z') ||
- (c >= 'a' && c <= 'z') ||
- (c >= '0' && c <= '9') ||
- (c == '_'));
-}
-
-/*
- * Determine whether "c" is a valid decimal digit.
- */
-static inline int isCharDigit(char c)
-{
- return (c >= '0' && c <= '9');
-}
-
-
/*
* Crunch through the file, parsing the contents and creating a tag index.
*/
@@ -193,25 +172,20 @@
{
/* get a tag count */
map->numTags = countMapLines(map);
- if (map->numTags < 0)
- return -1;
-
- //printf("+++ found %d tags\n", map->numTags);
-
- /* allocate storage for the tag index array */
- map->tagArray = calloc(1, sizeof(EventTag) * map->numTags);
- if (map->tagArray == NULL)
- return -1;
-
- /* parse the file, null-terminating tag strings */
- if (parseMapLines(map) != 0) {
- fprintf(stderr, "%s: file parse failed\n", OUT_TAG);
+ if (map->numTags < 0) {
+ errno = ENOENT;
return -1;
}
+ /* allocate storage for the tag index array */
+ map->tagArray = (EventTag*)calloc(1, sizeof(EventTag) * map->numTags);
+ if (map->tagArray == NULL) return -1;
+
+ /* parse the file, null-terminating tag strings */
+ if (parseMapLines(map) != 0) return -1;
+
/* sort the tags and check for duplicates */
- if (sortTags(map) != 0)
- return -1;
+ if (sortTags(map) != 0) return -1;
return 0;
}
@@ -228,24 +202,20 @@
*/
static int countMapLines(const EventTagMap* map)
{
- int numTags, unknown;
- const char* cp;
- const char* endp;
+ const char* cp = (const char*) map->mapAddr;
+ const char* endp = cp + map->mapLen;
+ int numTags = 0;
+ int unknown = 1;
- cp = (const char*) map->mapAddr;
- endp = cp + map->mapLen;
-
- numTags = 0;
- unknown = 1;
while (cp < endp) {
if (*cp == '\n') {
unknown = 1;
} else if (unknown) {
- if (isCharDigit(*cp)) {
+ if (isdigit(*cp)) {
/* looks like a tag to me */
numTags++;
unknown = 0;
- } else if (isCharWhitespace(*cp)) {
+ } else if (isspace(*cp)) {
/* might be leading whitespace before tag num, keep going */
} else {
/* assume comment; second pass can complain in detail */
@@ -266,15 +236,13 @@
static int parseMapLines(EventTagMap* map)
{
int tagNum, lineStart, lineNum;
- char* cp;
- char* endp;
-
- cp = (char*) map->mapAddr;
- endp = cp + map->mapLen;
+ char* cp = (char*) map->mapAddr;
+ char* endp = cp + map->mapLen;
/* insist on EOL at EOF; simplifies parsing and null-termination */
- if (*(endp-1) != '\n') {
+ if (*(endp - 1) != '\n') {
fprintf(stderr, "%s: map file missing EOL on last line\n", OUT_TAG);
+ errno = EINVAL;
return -1;
}
@@ -282,7 +250,6 @@
lineStart = 1;
lineNum = 1;
while (cp < endp) {
- //printf("{%02x}", *cp); fflush(stdout);
if (*cp == '\n') {
lineStart = 1;
lineNum++;
@@ -290,24 +257,27 @@
if (*cp == '#') {
/* comment; just scan to end */
lineStart = 0;
- } else if (isCharDigit(*cp)) {
+ } else if (isdigit(*cp)) {
/* looks like a tag; scan it out */
if (tagNum >= map->numTags) {
fprintf(stderr,
"%s: more tags than expected (%d)\n", OUT_TAG, tagNum);
+ errno = EMFILE;
return -1;
}
- if (scanTagLine(&cp, &map->tagArray[tagNum], lineNum) != 0)
+ if (scanTagLine(&cp, &map->tagArray[tagNum], lineNum) != 0) {
return -1;
+ }
tagNum++;
lineNum++; // we eat the '\n'
/* leave lineStart==1 */
- } else if (isCharWhitespace(*cp)) {
+ } else if (isspace(*cp)) {
/* looks like leading whitespace; keep scanning */
} else {
fprintf(stderr,
"%s: unexpected chars (0x%02x) in tag number on line %d\n",
OUT_TAG, *cp, lineNum);
+ errno = EINVAL;
return -1;
}
} else {
@@ -319,6 +289,7 @@
if (tagNum != map->numTags) {
fprintf(stderr, "%s: parsed %d tags, expected %d\n",
OUT_TAG, tagNum, map->numTags);
+ errno = EINVAL;
return -1;
}
@@ -336,41 +307,41 @@
*/
static int scanTagLine(char** pData, EventTag* tag, int lineNum)
{
- char* cp = *pData;
- char* startp;
- char* endp;
- unsigned long val;
+ char* cp;
- startp = cp;
- while (isCharDigit(*++cp))
- ;
- *cp = '\0';
-
- val = strtoul(startp, &endp, 10);
- assert(endp == cp);
- if (endp != cp)
- fprintf(stderr, "ARRRRGH\n");
+ unsigned long val = strtoul(*pData, &cp, 10);
+ if (cp == *pData) {
+ fprintf(stderr, "%s: malformed tag number on line %d\n", OUT_TAG, lineNum);
+ errno = EINVAL;
+ return -1;
+ }
tag->tagIndex = val;
+ if (tag->tagIndex != val) {
+ fprintf(stderr, "%s: tag number too large on line %d\n", OUT_TAG, lineNum);
+ errno = ERANGE;
+ return -1;
+ }
- while (*++cp != '\n' && isCharWhitespace(*cp))
- ;
+ while ((*++cp != '\n') && isspace(*cp)) {
+ }
if (*cp == '\n') {
- fprintf(stderr,
- "%s: missing tag string on line %d\n", OUT_TAG, lineNum);
+ fprintf(stderr, "%s: missing tag string on line %d\n", OUT_TAG, lineNum);
+ errno = EINVAL;
return -1;
}
tag->tagStr = cp;
- while (isCharValidTag(*++cp))
- ;
+ /* Determine whether "c" is a valid tag char. */
+ while (isalnum(*++cp) || (*cp == '_')) {
+ }
if (*cp == '\n') {
/* null terminate and return */
*cp = '\0';
- } else if (isCharWhitespace(*cp)) {
+ } else if (isspace(*cp)) {
/* CRLF or trailin spaces; zap this char, then scan for the '\n' */
*cp = '\0';
@@ -380,14 +351,13 @@
while (*++cp != '\n') {
}
} else {
- fprintf(stderr,
- "%s: invalid tag chars on line %d\n", OUT_TAG, lineNum);
+ fprintf(stderr, "%s: invalid tag chars on line %d\n", OUT_TAG, lineNum);
+ errno = EINVAL;
return -1;
}
*pData = cp;
- //printf("+++ Line %d: got %d '%s'\n", lineNum, tag->tagIndex, tag->tagStr);
return 0;
}
@@ -415,11 +385,13 @@
qsort(map->tagArray, map->numTags, sizeof(EventTag), compareEventTags);
for (i = 1; i < map->numTags; i++) {
- if (map->tagArray[i].tagIndex == map->tagArray[i-1].tagIndex) {
- fprintf(stderr, "%s: duplicate tag entries (%d:%s and %d:%s)\n",
+ if (map->tagArray[i].tagIndex == map->tagArray[i - 1].tagIndex) {
+ fprintf(stderr,
+ "%s: duplicate tag entries (%" PRIu32 ":%s and %" PRIu32 ":%s)\n",
OUT_TAG,
map->tagArray[i].tagIndex, map->tagArray[i].tagStr,
- map->tagArray[i-1].tagIndex, map->tagArray[i-1].tagStr);
+ map->tagArray[i - 1].tagIndex, map->tagArray[i - 1].tagStr);
+ errno = EMLINK;
return -1;
}
}
diff --git a/liblog/liblog.map.txt b/liblog/liblog.map.txt
new file mode 100644
index 0000000..5f19cc1
--- /dev/null
+++ b/liblog/liblog.map.txt
@@ -0,0 +1,14 @@
+LIBLOG {
+ global:
+ __android_log_assert;
+ __android_log_btwrite;
+ __android_log_buf_print; # introduced-arm=21 introduced-arm64=21 introduced-mips=9 introduced-mips64=21 introduced-x86=9 introduced-x86_64=21
+ __android_log_buf_write; # introduced-arm=21 introduced-arm64=21 introduced-mips=9 introduced-mips64=21 introduced-x86=9 introduced-x86_64=21
+ __android_log_bwrite;
+ __android_log_dev_available;
+ __android_log_print;
+ __android_log_vprint;
+ __android_log_write;
+ local:
+ *;
+};
diff --git a/liblog/logger_write.c b/liblog/logger_write.c
index c7b5a84..08e6348 100644
--- a/liblog/logger_write.c
+++ b/liblog/logger_write.c
@@ -132,12 +132,20 @@
}
return kLogNotAvailable;
}
+
+#if defined(__BIONIC__)
+static atomic_uintptr_t tagMap;
+#endif
+
/*
* Release any logger resources. A new log write will immediately re-acquire.
*/
LIBLOG_ABI_PUBLIC void __android_log_close()
{
struct android_log_transport_write *transport;
+#if defined(__BIONIC__)
+ EventTagMap *m;
+#endif
__android_log_lock();
@@ -165,7 +173,28 @@
}
}
+#if defined(__BIONIC__)
+ /*
+ * Additional risk here somewhat mitigated by immediately unlock flushing
+ * the processor cache. The multi-threaded race that we choose to accept,
+ * to minimize locking, is an atomic_load in a writer picking up a value
+ * just prior to entering this routine. There will be an use after free.
+ *
+ * Again, anyone calling this is doing so to release the logging resources
+ * is most probably going to quiesce then shut down; or to restart after
+ * a fork so the risk should be non-existent. For this reason we
+ * choose a mitigation stance for efficiency instead of incuring the cost
+ * of a lock for every log write.
+ */
+ m = (EventTagMap *)atomic_exchange(&tagMap, (uintptr_t)0);
+#endif
+
__android_log_unlock();
+
+#if defined(__BIONIC__)
+ android_closeEventTagMap(m);
+#endif
+
}
/* log_init_lock assumed */
@@ -250,7 +279,6 @@
return -EPERM;
}
} else if (log_id == LOG_ID_EVENTS) {
- static atomic_uintptr_t map;
const char *tag;
EventTagMap *m, *f;
@@ -260,11 +288,11 @@
tag = NULL;
f = NULL;
- m = (EventTagMap *)atomic_load(&map);
+ m = (EventTagMap *)atomic_load(&tagMap);
if (!m) {
ret = __android_log_trylock();
- m = (EventTagMap *)atomic_load(&map); /* trylock flush cache */
+ m = (EventTagMap *)atomic_load(&tagMap); /* trylock flush cache */
if (!m) {
m = android_openEventTagMap(EVENT_TAG_MAP_FILE);
if (ret) { /* trylock failed, use local copy, mark for close */
@@ -273,7 +301,7 @@
if (!m) { /* One chance to open map file */
m = (EventTagMap *)(uintptr_t)-1LL;
}
- atomic_store(&map, (uintptr_t)m);
+ atomic_store(&tagMap, (uintptr_t)m);
}
}
if (!ret) { /* trylock succeeded, unlock */
diff --git a/libmemunreachable/Tarjan.h b/libmemunreachable/Tarjan.h
index dcd139a..2546341 100644
--- a/libmemunreachable/Tarjan.h
+++ b/libmemunreachable/Tarjan.h
@@ -19,6 +19,7 @@
#ifndef LIBMEMUNREACHABLE_TARJAN_H_
#define LIBMEMUNREACHABLE_TARJAN_H_
+#include <assert.h>
#include <algorithm>
#include "Allocator.h"
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
index 65bbc1e..7c15429 100644
--- a/libprocessgroup/processgroup.cpp
+++ b/libprocessgroup/processgroup.cpp
@@ -203,9 +203,8 @@
{
std::unique_ptr<DIR, decltype(&closedir)> uid(opendir(uid_path), closedir);
if (uid != NULL) {
- struct dirent cur;
- struct dirent *dir;
- while ((readdir_r(uid.get(), &cur, &dir) == 0) && dir) {
+ dirent* dir;
+ while ((dir = readdir(uid.get())) != nullptr) {
char path[PROCESSGROUP_MAX_PATH_LEN];
if (dir->d_type != DT_DIR) {
@@ -231,9 +230,8 @@
if (root == NULL) {
PLOG(ERROR) << "failed to open " << cgroup_root_path;
} else {
- struct dirent cur;
- struct dirent *dir;
- while ((readdir_r(root.get(), &cur, &dir) == 0) && dir) {
+ dirent* dir;
+ while ((dir = readdir(root.get())) != nullptr) {
char path[PROCESSGROUP_MAX_PATH_LEN];
if (dir->d_type != DT_DIR) {
diff --git a/libusbhost/Android.mk b/libusbhost/Android.mk
index 5c12f2c..9439846 100644
--- a/libusbhost/Android.mk
+++ b/libusbhost/Android.mk
@@ -22,11 +22,11 @@
ifeq ($(HOST_OS),linux)
include $(CLEAR_VARS)
-
LOCAL_MODULE := libusbhost
LOCAL_SRC_FILES := usbhost.c
LOCAL_CFLAGS := -Werror
-
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
include $(BUILD_HOST_STATIC_LIBRARY)
endif
@@ -35,24 +35,22 @@
# ========================================================
include $(CLEAR_VARS)
-
LOCAL_MODULE := libusbhost
LOCAL_SRC_FILES := usbhost.c
-
LOCAL_CFLAGS := -g -DUSE_LIBLOG -Werror
-
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
# needed for logcat
LOCAL_SHARED_LIBRARIES := libcutils
-
include $(BUILD_SHARED_LIBRARY)
# Static library for target
# ========================================================
include $(CLEAR_VARS)
-
LOCAL_MODULE := libusbhost
LOCAL_SRC_FILES := usbhost.c
LOCAL_CFLAGS := -Werror
-
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
include $(BUILD_STATIC_LIBRARY)
diff --git a/include/usbhost/usbhost.h b/libusbhost/include/usbhost/usbhost.h
similarity index 99%
rename from include/usbhost/usbhost.h
rename to libusbhost/include/usbhost/usbhost.h
index 88b5b44..84594c8 100644
--- a/include/usbhost/usbhost.h
+++ b/libusbhost/include/usbhost/usbhost.h
@@ -216,7 +216,7 @@
int usb_device_bulk_transfer(struct usb_device *device,
int endpoint,
void* buffer,
- int length,
+ unsigned int length,
unsigned int timeout);
/** Reset USB bus for the device */
diff --git a/libusbhost/usbhost.c b/libusbhost/usbhost.c
index 299fdc4..68aca17 100644
--- a/libusbhost/usbhost.c
+++ b/libusbhost/usbhost.c
@@ -600,7 +600,7 @@
int usb_device_bulk_transfer(struct usb_device *device,
int endpoint,
void* buffer,
- int length,
+ unsigned int length,
unsigned int timeout)
{
struct usbdevfs_bulktransfer ctrl;
diff --git a/libutils/FileMap.cpp b/libutils/FileMap.cpp
index 4f4b889..1afa1ec 100644
--- a/libutils/FileMap.cpp
+++ b/libutils/FileMap.cpp
@@ -98,7 +98,7 @@
}
#if defined(__MINGW32__)
if (mBasePtr && UnmapViewOfFile(mBasePtr) == 0) {
- ALOGD("UnmapViewOfFile(%p) failed, error = %" PRId32 "\n", mBasePtr,
+ ALOGD("UnmapViewOfFile(%p) failed, error = %lu\n", mBasePtr,
GetLastError() );
}
if (mFileMapping != INVALID_HANDLE_VALUE) {
@@ -138,7 +138,7 @@
mFileHandle = (HANDLE) _get_osfhandle(fd);
mFileMapping = CreateFileMapping( mFileHandle, NULL, protect, 0, 0, NULL);
if (mFileMapping == NULL) {
- ALOGE("CreateFileMapping(%p, %" PRIx32 ") failed with error %" PRId32 "\n",
+ ALOGE("CreateFileMapping(%p, %lx) failed with error %lu\n",
mFileHandle, protect, GetLastError() );
return false;
}
@@ -153,7 +153,7 @@
(DWORD)(adjOffset),
adjLength );
if (mBasePtr == NULL) {
- ALOGE("MapViewOfFile(%" PRId64 ", %zu) failed with error %" PRId32 "\n",
+ ALOGE("MapViewOfFile(%" PRId64 ", %zu) failed with error %lu\n",
adjOffset, adjLength, GetLastError() );
CloseHandle(mFileMapping);
mFileMapping = INVALID_HANDLE_VALUE;
diff --git a/libutils/Looper.cpp b/libutils/Looper.cpp
index 952c992..adb0f8d 100644
--- a/libutils/Looper.cpp
+++ b/libutils/Looper.cpp
@@ -677,4 +677,8 @@
eventItem->data.fd = fd;
}
+MessageHandler::~MessageHandler() { }
+
+LooperCallback::~LooperCallback() { }
+
} // namespace android
diff --git a/libutils/ProcessCallStack.cpp b/libutils/ProcessCallStack.cpp
index 4e87a98..73ed4eb 100644
--- a/libutils/ProcessCallStack.cpp
+++ b/libutils/ProcessCallStack.cpp
@@ -131,9 +131,6 @@
}
void ProcessCallStack::update() {
- struct dirent *ep;
- struct dirent entry;
-
std::unique_ptr<DIR, decltype(&closedir)> dp(opendir(PATH_SELF_TASK), closedir);
if (dp == NULL) {
ALOGE("%s: Failed to update the process's call stacks: %s",
@@ -158,8 +155,8 @@
* Each tid is a directory inside of /proc/self/task
* - Read every file in directory => get every tid
*/
- int code;
- while ((code = readdir_r(dp.get(), &entry, &ep)) == 0 && ep != NULL) {
+ dirent* ep;
+ while ((ep = readdir(dp.get())) != NULL) {
pid_t tid = -1;
sscanf(ep->d_name, "%d", &tid);
@@ -194,10 +191,6 @@
ALOGV("%s: Got call stack for tid %d (size %zu)",
__FUNCTION__, tid, threadInfo.callStack.size());
}
- if (code != 0) { // returns positive error value on error
- ALOGE("%s: Failed to readdir from %s: %s",
- __FUNCTION__, PATH_SELF_TASK, strerror(code));
- }
}
void ProcessCallStack::log(const char* logtag, android_LogPriority priority,
diff --git a/libutils/RefBase.cpp b/libutils/RefBase.cpp
index fee9984..1f8395b 100644
--- a/libutils/RefBase.cpp
+++ b/libutils/RefBase.cpp
@@ -770,4 +770,6 @@
ref->mRefs->renameWeakRefId(old_id, new_id);
}
+VirtualLightRefBase::~VirtualLightRefBase() {}
+
}; // namespace android
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index 350be31..4649a75 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -31,6 +31,7 @@
#include <vector>
#include "android-base/file.h"
+#include "android-base/logging.h"
#include "android-base/macros.h" // TEMP_FAILURE_RETRY may or may not be in unistd
#include "android-base/memory.h"
#include "log/log.h"
@@ -1073,3 +1074,10 @@
int GetFileDescriptor(const ZipArchiveHandle handle) {
return reinterpret_cast<ZipArchive*>(handle)->fd;
}
+
+ZipString::ZipString(const char* entry_name)
+ : name(reinterpret_cast<const uint8_t*>(entry_name)) {
+ size_t len = strlen(entry_name);
+ CHECK_LE(len, static_cast<size_t>(UINT16_MAX));
+ name_length = static_cast<uint16_t>(len);
+}
diff --git a/libziparchive/zip_writer.cc b/libziparchive/zip_writer.cc
index 1ebed30..b72ed7f 100644
--- a/libziparchive/zip_writer.cc
+++ b/libziparchive/zip_writer.cc
@@ -243,8 +243,12 @@
// Initialize the z_stream for compression.
z_stream_ = std::unique_ptr<z_stream, void(*)(z_stream*)>(new z_stream(), DeleteZStream);
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wold-style-cast"
int zerr = deflateInit2(z_stream_.get(), Z_BEST_COMPRESSION, Z_DEFLATED, -MAX_WBITS,
DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
+#pragma GCC diagnostic pop
+
if (zerr != Z_OK) {
if (zerr == Z_VERSION_ERROR) {
ALOGE("Installed zlib is not compatible with linked version (%s)", ZLIB_VERSION);
diff --git a/lmkd/Android.mk b/lmkd/Android.mk
index 8c88661..8980d1c 100644
--- a/lmkd/Android.mk
+++ b/lmkd/Android.mk
@@ -2,7 +2,7 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES := lmkd.c
-LOCAL_SHARED_LIBRARIES := liblog libm libc libprocessgroup
+LOCAL_SHARED_LIBRARIES := liblog libm libc libprocessgroup libcutils
LOCAL_CFLAGS := -Werror
LOCAL_MODULE := lmkd
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 43822f3..50ee110 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -355,11 +355,12 @@
# create basic filesystem structure
mkdir /data/misc 01771 system misc
- mkdir /data/misc/bluedroid 02770 bluetooth net_bt_stack
+ mkdir /data/misc/bluedroid 02770 bluetooth bluetooth
# Fix the access permissions and group ownership for 'bt_config.conf'
chmod 0660 /data/misc/bluedroid/bt_config.conf
- chown bluetooth net_bt_stack /data/misc/bluedroid/bt_config.conf
- mkdir /data/misc/bluetooth 0770 system system
+ chown bluetooth bluetooth /data/misc/bluedroid/bt_config.conf
+ mkdir /data/misc/bluetooth 0770 bluetooth bluetooth
+ mkdir /data/misc/bluetooth/logs 0770 bluetooth bluetooth
mkdir /data/misc/keystore 0700 keystore keystore
mkdir /data/misc/gatekeeper 0700 system system
mkdir /data/misc/keychain 0771 system system
@@ -555,6 +556,8 @@
# Define default initial receive window size in segments.
setprop net.tcp.default_init_rwnd 60
+ # Start all binderized HAL daemons
+ start hwservicemanager
class_start core
on nonencrypted
@@ -644,3 +647,13 @@
service flash_recovery /system/bin/install-recovery.sh
class main
oneshot
+
+service hwservicemanager /system/bin/hwservicemanager
+ user system
+ disabled
+ group system readproc
+ critical
+ writepid /dev/cpuset/system-background/tasks
+
+on property:hwservicemanager.ready=true
+ class_start hal
diff --git a/rootdir/ueventd.rc b/rootdir/ueventd.rc
index 6ef491c..8725113 100644
--- a/rootdir/ueventd.rc
+++ b/rootdir/ueventd.rc
@@ -19,6 +19,7 @@
/dev/hw_random 0440 root system
/dev/ashmem 0666 root root
/dev/binder 0666 root root
+/dev/hwbinder 0666 root root
# Anyone can read the logs, but if they're not in the "logs"
# group, then they'll only see log entries for their UID.
@@ -40,8 +41,8 @@
/dev/android_adb 0660 adb adb
/dev/android_adb_enable 0660 adb adb
/dev/ttyMSM0 0600 bluetooth bluetooth
-/dev/uhid 0660 system net_bt_stack
-/dev/uinput 0660 system net_bt_stack
+/dev/uhid 0660 system bluetooth
+/dev/uinput 0660 system bluetooth
/dev/alarm 0664 system radio
/dev/rtc0 0640 system system
/dev/tty0 0660 root system