Merge "zip_archive: Improve error message on fallocate failure."
diff --git a/adb/Android.mk b/adb/Android.mk
index 7c029be..3512323 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -111,7 +111,7 @@
# Even though we're building a static library (and thus there's no link step for
# this to take effect), this adds the includes to our path.
-LOCAL_STATIC_LIBRARIES := libcrypto_utils_static libcrypto_static libbase
+LOCAL_STATIC_LIBRARIES := libcrypto_utils libcrypto libbase
include $(BUILD_STATIC_LIBRARY)
@@ -134,7 +134,7 @@
# Even though we're building a static library (and thus there's no link step for
# this to take effect), this adds the includes to our path.
-LOCAL_STATIC_LIBRARIES := libcrypto_utils_static libcrypto_static libbase
+LOCAL_STATIC_LIBRARIES := libcrypto_utils libcrypto libbase
LOCAL_C_INCLUDES_windows := development/host/windows/usb/api/
LOCAL_MULTILIB := first
@@ -154,7 +154,7 @@
shell_service_test.cpp \
LOCAL_SANITIZE := $(adb_target_sanitize)
-LOCAL_STATIC_LIBRARIES := libadbd libcrypto_utils_static libcrypto_static
+LOCAL_STATIC_LIBRARIES := libadbd libcrypto_utils libcrypto
LOCAL_SHARED_LIBRARIES := liblog libbase libcutils
include $(BUILD_NATIVE_TEST)
@@ -194,8 +194,8 @@
LOCAL_SHARED_LIBRARIES := libbase
LOCAL_STATIC_LIBRARIES := \
libadb \
- libcrypto_utils_static \
- libcrypto_static \
+ libcrypto_utils \
+ libcrypto \
libcutils \
libdiagnose_usb \
@@ -257,8 +257,8 @@
LOCAL_STATIC_LIBRARIES := \
libadb \
libbase \
- libcrypto_utils_static \
- libcrypto_static \
+ libcrypto_utils \
+ libcrypto \
libdiagnose_usb \
liblog \
@@ -334,8 +334,8 @@
libsquashfs_utils \
libcutils \
libbase \
- libcrypto_utils_static \
- libcrypto_static \
+ libcrypto_utils \
+ libcrypto \
libminijail \
libdebuggerd_client \
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 725aa91..45d26f8 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -354,21 +354,13 @@
case A_AUTH:
if (p->msg.arg0 == ADB_AUTH_TOKEN) {
t->connection_state = kCsUnauthorized;
- t->key = adb_auth_nextkey(t->key);
- if (t->key) {
- send_auth_response(p->data, p->msg.data_length, t);
- } else {
- /* No more private keys to try, send the public key */
- send_auth_publickey(t);
- }
+ send_auth_response(p->data, p->msg.data_length, t);
} else if (p->msg.arg0 == ADB_AUTH_SIGNATURE) {
- if (adb_auth_verify(t->token, sizeof(t->token),
- p->data, p->msg.data_length)) {
+ if (adb_auth_verify(t->token, sizeof(t->token), p->data, p->msg.data_length)) {
adb_auth_verified(t);
t->failed_auth_attempts = 0;
} else {
- if (t->failed_auth_attempts++ > 10)
- adb_sleep_ms(1000);
+ if (t->failed_auth_attempts++ > 10) adb_sleep_ms(1000);
send_auth_request(t);
}
} else if (p->msg.arg0 == ADB_AUTH_RSAPUBLICKEY) {
diff --git a/adb/adb_auth.cpp b/adb/adb_auth.cpp
index 215bbe6..446c3df 100644
--- a/adb/adb_auth.cpp
+++ b/adb/adb_auth.cpp
@@ -16,8 +16,9 @@
#define TRACE_TAG ADB
-#include "sysdeps.h"
+#include "adb.h"
#include "adb_auth.h"
+#include "transport.h"
#include <errno.h>
#include <stdio.h>
@@ -25,53 +26,28 @@
#include <sys/types.h>
#include <unistd.h>
-#include "adb.h"
-#include "transport.h"
-
bool auth_required = true;
void send_auth_request(atransport *t)
{
- D("Calling send_auth_request");
- apacket *p;
- int ret;
+ LOG(INFO) << "Calling send_auth_request...";
- ret = adb_auth_generate_token(t->token, sizeof(t->token));
- if (ret != sizeof(t->token)) {
- D("Error generating token ret=%d", ret);
+ if (!adb_auth_generate_token(t->token, sizeof(t->token))) {
+ PLOG(ERROR) << "Error generating token";
return;
}
- p = get_apacket();
- memcpy(p->data, t->token, ret);
+ apacket* p = get_apacket();
+ memcpy(p->data, t->token, sizeof(t->token));
p->msg.command = A_AUTH;
p->msg.arg0 = ADB_AUTH_TOKEN;
- p->msg.data_length = ret;
+ p->msg.data_length = sizeof(t->token);
send_packet(p, t);
}
-void send_auth_response(uint8_t *token, size_t token_size, atransport *t)
-{
- D("Calling send_auth_response");
- apacket *p = get_apacket();
- int ret;
+static void send_auth_publickey(atransport* t) {
+ LOG(INFO) << "Calling send_auth_publickey";
- ret = adb_auth_sign(t->key, token, token_size, p->data);
- if (!ret) {
- D("Error signing the token");
- put_apacket(p);
- return;
- }
-
- p->msg.command = A_AUTH;
- p->msg.arg0 = ADB_AUTH_SIGNATURE;
- p->msg.data_length = ret;
- send_packet(p, t);
-}
-
-void send_auth_publickey(atransport *t)
-{
- D("Calling send_auth_publickey");
std::string key = adb_auth_get_userkey();
if (key.empty()) {
D("Failed to get user public key");
@@ -92,6 +68,35 @@
send_packet(p, t);
}
+void send_auth_response(uint8_t* token, size_t token_size, atransport* t) {
+ RSA* key = t->NextKey();
+ if (key == nullptr) {
+ // No more private keys to try, send the public key.
+ send_auth_publickey(t);
+ return;
+ }
+
+ LOG(INFO) << "Calling send_auth_response";
+ apacket* p = get_apacket();
+
+ int ret = adb_auth_sign(key, token, token_size, p->data);
+
+ // Stop sharing this key.
+ RSA_free(key);
+ key = nullptr;
+
+ if (!ret) {
+ D("Error signing the token");
+ put_apacket(p);
+ return;
+ }
+
+ p->msg.command = A_AUTH;
+ p->msg.arg0 = ADB_AUTH_SIGNATURE;
+ p->msg.data_length = ret;
+ send_packet(p, t);
+}
+
void adb_auth_verified(atransport *t)
{
handle_online(t);
diff --git a/adb/adb_auth.h b/adb/adb_auth.h
index 6363bb4..723ded5 100644
--- a/adb/adb_auth.h
+++ b/adb/adb_auth.h
@@ -19,6 +19,10 @@
#include "adb.h"
+#include <deque>
+
+#include <openssl/rsa.h>
+
extern bool auth_required;
int adb_auth_keygen(const char* filename);
@@ -26,7 +30,6 @@
void send_auth_request(atransport *t);
void send_auth_response(uint8_t *token, size_t token_size, atransport *t);
-void send_auth_publickey(atransport *t);
/* AUTH packets first argument */
/* Request */
@@ -37,36 +40,25 @@
#if ADB_HOST
-void adb_auth_init(void);
-int adb_auth_sign(void *key, const unsigned char* token, size_t token_size,
- unsigned char* sig);
-void *adb_auth_nextkey(void *current);
+void adb_auth_init();
+int adb_auth_sign(RSA* key, const unsigned char* token, size_t token_size, unsigned char* sig);
std::string adb_auth_get_userkey();
+std::deque<RSA*> adb_auth_get_private_keys();
-static inline int adb_auth_generate_token(void *token, size_t token_size) {
- return 0;
-}
-static inline int adb_auth_verify(void *token, size_t token_size,
- void *sig, int siglen) {
- return 0;
-}
-static inline void adb_auth_confirm_key(unsigned char *data, size_t len,
- atransport *t) {}
+static inline bool adb_auth_generate_token(void*, size_t) { abort(); }
+static inline bool adb_auth_verify(void*, size_t, void*, int) { abort(); }
+static inline void adb_auth_confirm_key(unsigned char*, size_t, atransport*) { abort(); }
#else // !ADB_HOST
-static inline int adb_auth_sign(void* key, const unsigned char* token,
- size_t token_size, unsigned char* sig) {
- return 0;
-}
-static inline void *adb_auth_nextkey(void *current) { return NULL; }
-static inline std::string adb_auth_get_userkey() { return ""; }
+static inline int adb_auth_sign(void*, const unsigned char*, size_t, unsigned char*) { abort(); }
+static inline std::string adb_auth_get_userkey() { abort(); }
+static inline std::deque<RSA*> adb_auth_get_private_keys() { abort(); }
void adbd_auth_init(void);
void adbd_cloexec_auth_socket();
-int adb_auth_generate_token(void *token, size_t token_size);
-int adb_auth_verify(uint8_t* token, size_t token_size,
- uint8_t* sig, int siglen);
+bool adb_auth_generate_token(void* token, size_t token_size);
+bool adb_auth_verify(uint8_t* token, size_t token_size, uint8_t* sig, int sig_len);
void adb_auth_confirm_key(unsigned char *data, size_t len, atransport *t);
#endif // ADB_HOST
diff --git a/adb/adb_auth_client.cpp b/adb/adb_auth_client.cpp
index 415ab8e..9d8dfc0 100644
--- a/adb/adb_auth_client.cpp
+++ b/adb/adb_auth_client.cpp
@@ -16,37 +16,25 @@
#define TRACE_TAG AUTH
-#include "sysdeps.h"
+#include "adb.h"
#include "adb_auth.h"
+#include "fdevent.h"
+#include "sysdeps.h"
+#include "transport.h"
#include <resolv.h>
#include <stdio.h>
#include <string.h>
+#include <memory>
+
+#include <android-base/file.h>
+#include <android-base/strings.h>
+#include <crypto_utils/android_pubkey.h>
#include <openssl/obj_mac.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>
-#include <crypto_utils/android_pubkey.h>
-
-#include "cutils/list.h"
-#include "cutils/sockets.h"
-
-#include "adb.h"
-#include "fdevent.h"
-#include "transport.h"
-
-struct adb_public_key {
- struct listnode node;
- RSA* key;
-};
-
-static const char *key_paths[] = {
- "/adb_keys",
- "/data/misc/adb/adb_keys",
- NULL
-};
-
static fdevent listener_fde;
static fdevent framework_fde;
static int framework_fd = -1;
@@ -56,135 +44,71 @@
static atransport* usb_transport;
static bool needs_retry = false;
-static void read_keys(const char *file, struct listnode *list)
-{
- FILE *f;
- char buf[MAX_PAYLOAD_V1];
- char *sep;
- int ret;
+bool adb_auth_verify(uint8_t* token, size_t token_size, uint8_t* sig, int sig_len) {
+ static constexpr const char* key_paths[] = { "/adb_keys", "/data/misc/adb/adb_keys", nullptr };
- f = fopen(file, "re");
- if (!f) {
- D("Can't open '%s'", file);
- return;
- }
+ for (const auto& path : key_paths) {
+ if (access(path, R_OK) == 0) {
+ LOG(INFO) << "Loading keys from " << path;
- while (fgets(buf, sizeof(buf), f)) {
- auto key = reinterpret_cast<adb_public_key*>(
- calloc(1, sizeof(adb_public_key)));
- if (key == nullptr) {
- D("Can't malloc key");
- break;
- }
+ std::string content;
+ if (!android::base::ReadFileToString(path, &content)) {
+ PLOG(ERROR) << "Couldn't read " << path;
+ continue;
+ }
- sep = strpbrk(buf, " \t");
- if (sep)
- *sep = '\0';
+ for (const auto& line : android::base::Split(content, "\n")) {
+ // TODO: do we really have to support both ' ' and '\t'?
+ char* sep = strpbrk(const_cast<char*>(line.c_str()), " \t");
+ if (sep) *sep = '\0';
- // b64_pton requires one additional byte in the target buffer for
- // decoding to succeed. See http://b/28035006 for details.
- uint8_t keybuf[ANDROID_PUBKEY_ENCODED_SIZE + 1];
- ret = __b64_pton(buf, keybuf, sizeof(keybuf));
- if (ret != ANDROID_PUBKEY_ENCODED_SIZE) {
- D("%s: Invalid base64 data ret=%d", file, ret);
- free(key);
- continue;
- }
+ // b64_pton requires one additional byte in the target buffer for
+ // decoding to succeed. See http://b/28035006 for details.
+ uint8_t keybuf[ANDROID_PUBKEY_ENCODED_SIZE + 1];
+ if (__b64_pton(line.c_str(), keybuf, sizeof(keybuf)) != ANDROID_PUBKEY_ENCODED_SIZE) {
+ LOG(ERROR) << "Invalid base64 key " << line.c_str() << " in " << path;
+ continue;
+ }
- if (!android_pubkey_decode(keybuf, ret, &key->key)) {
- D("%s: Failed to parse key", file);
- free(key);
- continue;
- }
+ RSA* key = nullptr;
+ if (!android_pubkey_decode(keybuf, ANDROID_PUBKEY_ENCODED_SIZE, &key)) {
+ LOG(ERROR) << "Failed to parse key " << line.c_str() << " in " << path;
+ continue;
+ }
- list_add_tail(list, &key->node);
- }
-
- fclose(f);
-}
-
-static void free_keys(struct listnode *list)
-{
- struct listnode *item;
-
- while (!list_empty(list)) {
- item = list_head(list);
- list_remove(item);
- adb_public_key* key = node_to_item(item, struct adb_public_key, node);
- RSA_free(key->key);
- free(key);
- }
-}
-
-static void load_keys(struct listnode *list)
-{
- const char* path;
- const char** paths = key_paths;
- struct stat buf;
-
- list_init(list);
-
- while ((path = *paths++)) {
- if (!stat(path, &buf)) {
- D("Loading keys from '%s'", path);
- read_keys(path, list);
+ bool verified = (RSA_verify(NID_sha1, token, token_size, sig, sig_len, key) == 1);
+ RSA_free(key);
+ if (verified) return true;
+ }
}
}
+ return false;
}
-int adb_auth_generate_token(void *token, size_t token_size)
-{
- FILE *f;
- int ret;
-
- f = fopen("/dev/urandom", "re");
- if (!f)
- return 0;
-
- ret = fread(token, token_size, 1, f);
-
- fclose(f);
- return ret * token_size;
-}
-
-int adb_auth_verify(uint8_t* token, size_t token_size, uint8_t* sig, int siglen)
-{
- struct listnode *item;
- struct listnode key_list;
- int ret = 0;
-
- load_keys(&key_list);
-
- list_for_each(item, &key_list) {
- adb_public_key* key = node_to_item(item, struct adb_public_key, node);
- ret = RSA_verify(NID_sha1, token, token_size, sig, siglen, key->key);
- if (ret)
- break;
- }
-
- free_keys(&key_list);
-
- return ret;
+bool adb_auth_generate_token(void* token, size_t token_size) {
+ FILE* fp = fopen("/dev/urandom", "re");
+ if (!fp) return false;
+ bool okay = (fread(token, token_size, 1, fp) == 1);
+ fclose(fp);
+ return okay;
}
static void usb_disconnected(void* unused, atransport* t) {
- D("USB disconnect");
+ LOG(INFO) << "USB disconnect";
usb_transport = NULL;
needs_retry = false;
}
static void framework_disconnected() {
- D("Framework disconnect");
+ LOG(INFO) << "Framework disconnect";
fdevent_remove(&framework_fde);
framework_fd = -1;
}
static void adb_auth_event(int fd, unsigned events, void*) {
- char response[2];
- int ret;
-
if (events & FDE_READ) {
- ret = unix_read(fd, response, sizeof(response));
+ char response[2];
+ int ret = unix_read(fd, response, sizeof(response));
if (ret <= 0) {
framework_disconnected();
} else if (ret == 2 && response[0] == 'O' && response[1] == 'K') {
@@ -195,51 +119,43 @@
}
}
-void adb_auth_confirm_key(unsigned char *key, size_t len, atransport *t)
-{
- char msg[MAX_PAYLOAD_V1];
- int ret;
-
+void adb_auth_confirm_key(unsigned char* key, size_t len, atransport* t) {
if (!usb_transport) {
usb_transport = t;
t->AddDisconnect(&usb_disconnect);
}
if (framework_fd < 0) {
- D("Client not connected");
+ LOG(ERROR) << "Client not connected";
needs_retry = true;
return;
}
if (key[len - 1] != '\0') {
- D("Key must be a null-terminated string");
+ LOG(ERROR) << "Key must be a null-terminated string";
return;
}
- ret = snprintf(msg, sizeof(msg), "PK%s", key);
- if (ret >= (signed)sizeof(msg)) {
- D("Key too long. ret=%d", ret);
+ char msg[MAX_PAYLOAD_V1];
+ int msg_len = snprintf(msg, sizeof(msg), "PK%s", key);
+ if (msg_len >= static_cast<int>(sizeof(msg))) {
+ LOG(ERROR) << "Key too long (" << msg_len << ")";
return;
}
- D("Sending '%s'", msg);
+ LOG(DEBUG) << "Sending '" << msg << "'";
- ret = unix_write(framework_fd, msg, ret);
- if (ret < 0) {
- D("Failed to write PK, errno=%d", errno);
+ if (unix_write(framework_fd, msg, msg_len) == -1) {
+ PLOG(ERROR) << "Failed to write PK";
return;
}
}
static void adb_auth_listener(int fd, unsigned events, void* data) {
sockaddr_storage addr;
- socklen_t alen;
- int s;
-
- alen = sizeof(addr);
-
- s = adb_socket_accept(fd, reinterpret_cast<sockaddr*>(&addr), &alen);
+ socklen_t alen = sizeof(addr);
+ int s = adb_socket_accept(fd, reinterpret_cast<sockaddr*>(&addr), &alen);
if (s < 0) {
- D("Failed to accept: errno=%d", errno);
+ PLOG(ERROR) << "Failed to accept";
return;
}
@@ -261,7 +177,7 @@
void adbd_cloexec_auth_socket() {
int fd = android_get_control_socket("adbd");
if (fd == -1) {
- D("Failed to get adbd socket");
+ PLOG(ERROR) << "Failed to get adbd socket";
return;
}
fcntl(fd, F_SETFD, FD_CLOEXEC);
@@ -270,12 +186,12 @@
void adbd_auth_init(void) {
int fd = android_get_control_socket("adbd");
if (fd == -1) {
- D("Failed to get adbd socket");
+ PLOG(ERROR) << "Failed to get adbd socket";
return;
}
if (listen(fd, 4) == -1) {
- D("Failed to listen on '%d'", fd);
+ PLOG(ERROR) << "Failed to listen on '" << fd << "'";
return;
}
diff --git a/adb/adb_auth_host.cpp b/adb/adb_auth_host.cpp
index dff874f..ce269cc 100644
--- a/adb/adb_auth_host.cpp
+++ b/adb/adb_auth_host.cpp
@@ -16,23 +16,22 @@
#define TRACE_TAG AUTH
-#include "sysdeps.h"
#include "adb_auth.h"
+#include "adb.h"
#include "adb_utils.h"
+#include "sysdeps.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "adb.h"
+#include <mutex>
#include <android-base/errors.h>
#include <android-base/file.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <crypto_utils/android_pubkey.h>
-#include <cutils/list.h>
-
#include <openssl/base64.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
@@ -40,18 +39,14 @@
#include <openssl/rsa.h>
#include <openssl/sha.h>
-#define ANDROID_PATH ".android"
-#define ADB_KEY_FILE "adbkey"
+#include "sysdeps/mutex.h"
-struct adb_private_key {
- struct listnode node;
- RSA *rsa;
-};
-
-static struct listnode key_list;
-
+static std::mutex& g_key_list_mutex = *new std::mutex;
+static std::deque<RSA*>& g_key_list = *new std::deque<RSA*>;
static std::string get_user_info() {
+ LOG(INFO) << "get_user_info...";
+
std::string hostname;
if (getenv("HOSTNAME")) hostname = getenv("HOSTNAME");
#if !defined(_WIN32)
@@ -71,6 +66,8 @@
}
static bool write_public_keyfile(RSA* private_key, const std::string& private_key_path) {
+ LOG(INFO) << "write_public_keyfile...";
+
uint8_t binary_key_data[ANDROID_PUBKEY_ENCODED_SIZE];
if (!android_pubkey_encode(private_key, binary_key_data, sizeof(binary_key_data))) {
LOG(ERROR) << "Failed to convert to public key";
@@ -99,19 +96,18 @@
return true;
}
-static int generate_key(const char *file)
-{
- EVP_PKEY* pkey = EVP_PKEY_new();
- BIGNUM* exponent = BN_new();
- RSA* rsa = RSA_new();
+static int generate_key(const std::string& file) {
+ LOG(INFO) << "generate_key(" << file << ")...";
+
mode_t old_mask;
FILE *f = NULL;
int ret = 0;
- D("generate_key '%s'", file);
-
+ EVP_PKEY* pkey = EVP_PKEY_new();
+ BIGNUM* exponent = BN_new();
+ RSA* rsa = RSA_new();
if (!pkey || !exponent || !rsa) {
- D("Failed to allocate key");
+ LOG(ERROR) << "Failed to allocate key";
goto out;
}
@@ -121,9 +117,9 @@
old_mask = umask(077);
- f = fopen(file, "w");
+ f = fopen(file.c_str(), "w");
if (!f) {
- D("Failed to open '%s'", file);
+ PLOG(ERROR) << "Failed to open " << file;
umask(old_mask);
goto out;
}
@@ -143,110 +139,110 @@
ret = 1;
out:
- if (f)
- fclose(f);
+ if (f) fclose(f);
EVP_PKEY_free(pkey);
RSA_free(rsa);
BN_free(exponent);
return ret;
}
-static int read_key(const char *file, struct listnode *list)
-{
- D("read_key '%s'", file);
+static bool read_key(const std::string& file) {
+ LOG(INFO) << "read_key '" << file << "'...";
- FILE* fp = fopen(file, "r");
+ std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(file.c_str(), "r"), fclose);
if (!fp) {
- D("Failed to open '%s': %s", file, strerror(errno));
- return 0;
+ PLOG(ERROR) << "Failed to open '" << file << "'";
+ return false;
}
- adb_private_key* key = new adb_private_key;
- key->rsa = RSA_new();
-
- if (!PEM_read_RSAPrivateKey(fp, &key->rsa, NULL, NULL)) {
- D("Failed to read key");
- fclose(fp);
- RSA_free(key->rsa);
- delete key;
- return 0;
+ RSA* key = RSA_new();
+ if (!PEM_read_RSAPrivateKey(fp.get(), &key, nullptr, nullptr)) {
+ LOG(ERROR) << "Failed to read key";
+ RSA_free(key);
+ return false;
}
- fclose(fp);
- list_add_tail(list, &key->node);
- return 1;
+ g_key_list.push_back(key);
+ return true;
}
-static int get_user_keyfilepath(char *filename, size_t len)
-{
+static std::string get_user_key_path() {
const std::string home = adb_get_homedir_path(true);
- D("home '%s'", home.c_str());
+ LOG(DEBUG) << "adb_get_homedir_path returned '" << home << "'";
- const std::string android_dir =
- android::base::StringPrintf("%s%c%s", home.c_str(),
- OS_PATH_SEPARATOR, ANDROID_PATH);
+ const std::string android_dir = android::base::StringPrintf("%s%c.android", home.c_str(),
+ OS_PATH_SEPARATOR);
struct stat buf;
- if (stat(android_dir.c_str(), &buf)) {
- if (adb_mkdir(android_dir.c_str(), 0750) < 0) {
- D("Cannot mkdir '%s'", android_dir.c_str());
- return -1;
+ if (stat(android_dir.c_str(), &buf) == -1) {
+ if (adb_mkdir(android_dir.c_str(), 0750) == -1) {
+ PLOG(ERROR) << "Cannot mkdir '" << android_dir << "'";
+ return "";
}
}
- return snprintf(filename, len, "%s%c%s",
- android_dir.c_str(), OS_PATH_SEPARATOR, ADB_KEY_FILE);
+ return android_dir + OS_PATH_SEPARATOR + "adbkey";
}
-static int get_user_key(struct listnode *list)
-{
- struct stat buf;
- char path[PATH_MAX];
- int ret;
-
- ret = get_user_keyfilepath(path, sizeof(path));
- if (ret < 0 || ret >= (signed)sizeof(path)) {
- D("Error getting user key filename");
- return 0;
+static bool get_user_key() {
+ std::string path = get_user_key_path();
+ if (path.empty()) {
+ PLOG(ERROR) << "Error getting user key filename";
+ return false;
}
- D("user key '%s'", path);
-
- if (stat(path, &buf) == -1) {
+ struct stat buf;
+ if (stat(path.c_str(), &buf) == -1) {
+ LOG(INFO) << "User key '" << path << "' does not exist...";
if (!generate_key(path)) {
- D("Failed to generate new key");
- return 0;
+ LOG(ERROR) << "Failed to generate new key";
+ return false;
}
}
- return read_key(path, list);
+ return read_key(path);
}
-static void get_vendor_keys(struct listnode* key_list) {
+static void get_vendor_keys() {
const char* adb_keys_path = getenv("ADB_VENDOR_KEYS");
if (adb_keys_path == nullptr) {
return;
}
for (const auto& path : android::base::Split(adb_keys_path, ENV_PATH_SEPARATOR_STR)) {
- if (!read_key(path.c_str(), key_list)) {
- D("Failed to read '%s'", path.c_str());
+ if (!read_key(path.c_str())) {
+ PLOG(ERROR) << "Failed to read '" << path << "'";
}
}
}
-int adb_auth_sign(void *node, const unsigned char* token, size_t token_size,
- unsigned char* sig)
-{
- unsigned int len;
- struct adb_private_key *key = node_to_item(node, struct adb_private_key, node);
+std::deque<RSA*> adb_auth_get_private_keys() {
+ std::deque<RSA*> result;
+ // Copy all the currently known keys, increasing their reference count so they're
+ // usable until both we and the caller have freed our pointers.
+ std::lock_guard<std::mutex> lock(g_key_list_mutex);
+ for (const auto& key : g_key_list) {
+ RSA_up_ref(key); // Since we're handing out another pointer to this key...
+ result.push_back(key);
+ }
+
+ // Add a sentinel to the list. Our caller uses this to mean "out of private keys,
+ // but try using the public key" (the empty deque could otherwise mean this _or_
+ // that this function hasn't been called yet to request the keys).
+ result.push_back(nullptr);
+
+ return result;
+}
+
+int adb_auth_sign(RSA* key, const unsigned char* token, size_t token_size, unsigned char* sig) {
if (token_size != TOKEN_SIZE) {
D("Unexpected token size %zd", token_size);
return 0;
}
- if (!RSA_sign(NID_sha1, token, token_size, sig, &len, key->rsa)) {
+ unsigned int len;
+ if (!RSA_sign(NID_sha1, token, token_size, sig, &len, key)) {
return 0;
}
@@ -254,40 +250,17 @@
return (int)len;
}
-void *adb_auth_nextkey(void *current)
-{
- struct listnode *item;
-
- if (list_empty(&key_list))
- return NULL;
-
- if (!current)
- return list_head(&key_list);
-
- list_for_each(item, &key_list) {
- if (item == current) {
- /* current is the last item, we tried all the keys */
- if (item->next == &key_list)
- return NULL;
- return item->next;
- }
- }
-
- return NULL;
-}
-
std::string adb_auth_get_userkey() {
- char path[PATH_MAX];
- int ret = get_user_keyfilepath(path, sizeof(path) - 4);
- if (ret < 0 || ret >= (signed)(sizeof(path) - 4)) {
- D("Error getting user key filename");
+ std::string path = get_user_key_path();
+ if (path.empty()) {
+ PLOG(ERROR) << "Error getting user key filename";
return "";
}
- strcat(path, ".pub");
+ path += ".pub";
std::string content;
if (!android::base::ReadFileToString(path, &content)) {
- D("Can't load '%s'", path);
+ PLOG(ERROR) << "Can't load '" << path << "'";
return "";
}
return content;
@@ -297,19 +270,14 @@
return (generate_key(filename) == 0);
}
-void adb_auth_init(void)
-{
- int ret;
+void adb_auth_init() {
+ LOG(INFO) << "adb_auth_init...";
- D("adb_auth_init");
-
- list_init(&key_list);
-
- ret = get_user_key(&key_list);
- if (!ret) {
- D("Failed to get user key");
+ if (!get_user_key()) {
+ LOG(ERROR) << "Failed to get user key";
return;
}
- get_vendor_keys(&key_list);
+ std::lock_guard<std::mutex> lock(g_key_list_mutex);
+ get_vendor_keys();
}
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
index d2ca44e..e160169 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -110,7 +110,6 @@
usb_init();
local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
- adb_auth_init();
std::string error;
std::string local_name = android::base::StringPrintf("tcp:%d", server_port);
@@ -118,11 +117,14 @@
fatal("could not install *smartsocket* listener: %s", error.c_str());
}
- // Inform our parent that we are up and running.
if (is_daemon) {
close_stdin();
setup_daemon_logging();
+ }
+ adb_auth_init();
+
+ if (is_daemon) {
#if !defined(_WIN32)
// 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
@@ -132,6 +134,8 @@
}
#endif
+ // Inform our parent that we are up and running.
+
// Any error output written to stderr now goes to adb.log. We could
// keep around a copy of the stderr fd and use that to write any errors
// encountered by the following code, but that is probably overkill.
diff --git a/adb/file_sync_client.cpp b/adb/file_sync_client.cpp
index fbca770..3368b7f 100644
--- a/adb/file_sync_client.cpp
+++ b/adb/file_sync_client.cpp
@@ -28,8 +28,11 @@
#include <unistd.h>
#include <utime.h>
+#include <chrono>
#include <functional>
#include <memory>
+#include <sstream>
+#include <string>
#include <vector>
#include "sysdeps.h"
@@ -94,14 +97,112 @@
}
};
+enum class TransferDirection {
+ push,
+ pull,
+};
+
+struct TransferLedger {
+ std::chrono::steady_clock::time_point start_time;
+ uint64_t files_transferred;
+ uint64_t files_skipped;
+ uint64_t bytes_transferred;
+ uint64_t bytes_expected;
+ bool expect_multiple_files;
+
+ TransferLedger() {
+ Reset();
+ }
+
+ bool operator==(const TransferLedger& other) const {
+ return files_transferred == other.files_transferred &&
+ files_skipped == other.files_skipped && bytes_transferred == other.bytes_transferred;
+ }
+
+ bool operator!=(const TransferLedger& other) const {
+ return !(*this == other);
+ }
+
+ void Reset() {
+ start_time = std::chrono::steady_clock::now();
+ files_transferred = 0;
+ files_skipped = 0;
+ bytes_transferred = 0;
+ bytes_expected = 0;
+ }
+
+ std::string TransferRate() {
+ if (bytes_transferred == 0) return "";
+
+ std::chrono::duration<double> duration;
+ duration = std::chrono::steady_clock::now() - start_time;
+
+ double s = duration.count();
+ if (s == 0) {
+ return "";
+ }
+ double rate = (static_cast<double>(bytes_transferred) / s) / (1024 * 1024);
+ return android::base::StringPrintf(" %.1f MB/s (%" PRIu64 " bytes in %.3fs)", rate,
+ bytes_transferred, s);
+ }
+
+ void ReportProgress(LinePrinter& lp, const std::string& file, uint64_t file_copied_bytes,
+ uint64_t file_total_bytes) {
+ char overall_percentage_str[5] = "?";
+ if (bytes_expected != 0) {
+ int overall_percentage = static_cast<int>(bytes_transferred * 100 / bytes_expected);
+ // If we're pulling symbolic links, we'll pull the target of the link rather than
+ // just create a local link, and that will cause us to go over 100%.
+ if (overall_percentage <= 100) {
+ snprintf(overall_percentage_str, sizeof(overall_percentage_str), "%d%%",
+ overall_percentage);
+ }
+ }
+
+ std::string output;
+ if (file_copied_bytes > file_total_bytes || file_total_bytes == 0) {
+ // This case can happen if we're racing against something that wrote to the file
+ // between our stat and our read, or if we're reading a magic file that lies about
+ // its size. Just show how much we've copied.
+ output = android::base::StringPrintf("[%4s] %s: %" PRId64 "/?", overall_percentage_str,
+ file.c_str(), file_copied_bytes);
+ } else {
+ // If we're transferring multiple files, we want to know how far through the current
+ // file we are, as well as the overall percentage.
+ if (expect_multiple_files) {
+ int file_percentage = static_cast<int>(file_copied_bytes * 100 / file_total_bytes);
+ output = android::base::StringPrintf("[%4s] %s: %d%%", overall_percentage_str,
+ file.c_str(), file_percentage);
+ } else {
+ output =
+ android::base::StringPrintf("[%4s] %s", overall_percentage_str, file.c_str());
+ }
+ }
+ lp.Print(output, LinePrinter::LineType::INFO);
+ }
+
+ void ReportTransferRate(LinePrinter& lp, const std::string& name, TransferDirection direction) {
+ const char* direction_str = (direction == TransferDirection::push) ? "pushed" : "pulled";
+ std::stringstream ss;
+ if (!name.empty()) {
+ ss << name << ": ";
+ }
+ ss << files_transferred << " file" << ((files_transferred == 1) ? "" : "s") << " "
+ << direction_str << ".";
+ if (files_skipped > 0) {
+ ss << " " << files_skipped << " file" << ((files_skipped == 1) ? "" : "s")
+ << " skipped.";
+ }
+ ss << TransferRate();
+
+ lp.Print(ss.str(), LinePrinter::LineType::INFO);
+ lp.KeepInfoLine();
+ }
+};
+
class SyncConnection {
public:
- SyncConnection()
- : total_bytes_(0),
- start_time_ms_(CurrentTimeMs()),
- expected_total_bytes_(0),
- expect_multiple_files_(false),
- expect_done_(false) {
+ SyncConnection() : expect_done_(false) {
max = SYNC_DATA_MAX; // TODO: decide at runtime.
std::string error;
@@ -140,6 +241,40 @@
return rc != 0;
}
+ void NewTransfer() {
+ current_ledger_.Reset();
+ }
+
+ void RecordBytesTransferred(size_t bytes) {
+ current_ledger_.bytes_transferred += bytes;
+ global_ledger_.bytes_transferred += bytes;
+ }
+
+ void RecordFilesTransferred(size_t files) {
+ current_ledger_.files_transferred += files;
+ global_ledger_.files_transferred += files;
+ }
+
+ void RecordFilesSkipped(size_t files) {
+ current_ledger_.files_skipped += files;
+ global_ledger_.files_skipped += files;
+ }
+
+ void ReportProgress(const std::string& file, uint64_t file_copied_bytes,
+ uint64_t file_total_bytes) {
+ current_ledger_.ReportProgress(line_printer_, file, file_copied_bytes, file_total_bytes);
+ }
+
+ void ReportTransferRate(const std::string& file, TransferDirection direction) {
+ current_ledger_.ReportTransferRate(line_printer_, file, direction);
+ }
+
+ void ReportOverallTransferRate(TransferDirection direction) {
+ if (current_ledger_ != global_ledger_) {
+ global_ledger_.ReportTransferRate(line_printer_, "", direction);
+ }
+ }
+
bool SendRequest(int id, const char* path_and_mode) {
size_t path_length = strlen(path_and_mode);
if (path_length > 1024) {
@@ -199,7 +334,9 @@
WriteOrDie(lpath, rpath, &buf[0], (p - &buf[0]));
expect_done_ = true;
- total_bytes_ += data_length;
+
+ // RecordFilesTransferred gets called in CopyDone.
+ RecordBytesTransferred(data_length);
ReportProgress(rpath, data_length, data_length);
return true;
}
@@ -242,7 +379,7 @@
sbuf.size = bytes_read;
WriteOrDie(lpath, rpath, &sbuf, sizeof(SyncRequest) + bytes_read);
- total_bytes_ += bytes_read;
+ RecordBytesTransferred(bytes_read);
bytes_copied += bytes_read;
// Check to see if we've received an error from the other side.
@@ -259,6 +396,8 @@
msg.data.id = ID_DONE;
msg.data.size = mtime;
expect_done_ = true;
+
+ // RecordFilesTransferred gets called in CopyDone.
return WriteOrDie(lpath, rpath, &msg.data, sizeof(msg.data));
}
@@ -271,6 +410,7 @@
if (msg.status.id == ID_OKAY) {
if (expect_done_) {
expect_done_ = false;
+ RecordFilesTransferred(1);
return true;
} else {
Error("failed to copy '%s' to '%s': received premature success", from, to);
@@ -296,44 +436,6 @@
return false;
}
- std::string TransferRate() {
- uint64_t ms = CurrentTimeMs() - start_time_ms_;
- if (total_bytes_ == 0 || ms == 0) return "";
-
- double s = static_cast<double>(ms) / 1000LL;
- double rate = (static_cast<double>(total_bytes_) / s) / (1024*1024);
- return android::base::StringPrintf(" %.1f MB/s (%" PRId64 " bytes in %.3fs)",
- rate, total_bytes_, s);
- }
-
- void ReportProgress(const char* file, uint64_t file_copied_bytes, uint64_t file_total_bytes) {
- char overall_percentage_str[5] = "?";
- if (expected_total_bytes_ != 0) {
- int overall_percentage = static_cast<int>(total_bytes_ * 100 / expected_total_bytes_);
- // If we're pulling symbolic links, we'll pull the target of the link rather than
- // just create a local link, and that will cause us to go over 100%.
- if (overall_percentage <= 100) {
- snprintf(overall_percentage_str, sizeof(overall_percentage_str), "%d%%",
- overall_percentage);
- }
- }
-
- if (file_copied_bytes > file_total_bytes || file_total_bytes == 0) {
- // This case can happen if we're racing against something that wrote to the file
- // between our stat and our read, or if we're reading a magic file that lies about
- // its size. Just show how much we've copied.
- Printf("[%4s] %s: %" PRId64 "/?", overall_percentage_str, file, file_copied_bytes);
- } else {
- // If we're transferring multiple files, we want to know how far through the current
- // file we are, as well as the overall percentage.
- if (expect_multiple_files_) {
- int file_percentage = static_cast<int>(file_copied_bytes * 100 / file_total_bytes);
- Printf("[%4s] %s: %d%%", overall_percentage_str, file, file_percentage);
- } else {
- Printf("[%4s] %s", overall_percentage_str, file);
- }
- }
- }
void Printf(const char* fmt, ...) __attribute__((__format__(ADB_FORMAT_ARCHETYPE, 2, 3))) {
std::string s;
@@ -346,6 +448,18 @@
line_printer_.Print(s, LinePrinter::INFO);
}
+ void Println(const char* fmt, ...) __attribute__((__format__(ADB_FORMAT_ARCHETYPE, 2, 3))) {
+ std::string s;
+
+ va_list ap;
+ va_start(ap, fmt);
+ android::base::StringAppendV(&s, fmt, ap);
+ va_end(ap);
+
+ line_printer_.Print(s, LinePrinter::INFO);
+ line_printer_.KeepInfoLine();
+ }
+
void Error(const char* fmt, ...) __attribute__((__format__(ADB_FORMAT_ARCHETYPE, 2, 3))) {
std::string s = "adb: error: ";
@@ -369,33 +483,29 @@
}
void ComputeExpectedTotalBytes(const std::vector<copyinfo>& file_list) {
- expected_total_bytes_ = 0;
+ current_ledger_.bytes_expected = 0;
for (const copyinfo& ci : file_list) {
// Unfortunately, this doesn't work for symbolic links, because we'll copy the
// target of the link rather than just creating a link. (But ci.size is the link size.)
- if (!ci.skip) expected_total_bytes_ += ci.size;
+ if (!ci.skip) current_ledger_.bytes_expected += ci.size;
}
- expect_multiple_files_ = true;
+ current_ledger_.expect_multiple_files = true;
}
void SetExpectedTotalBytes(uint64_t expected_total_bytes) {
- expected_total_bytes_ = expected_total_bytes;
- expect_multiple_files_ = false;
+ current_ledger_.bytes_expected = expected_total_bytes;
+ current_ledger_.expect_multiple_files = false;
}
- uint64_t total_bytes_;
-
// TODO: add a char[max] buffer here, to replace syncsendbuf...
int fd;
size_t max;
private:
- uint64_t start_time_ms_;
-
- uint64_t expected_total_bytes_;
- bool expect_multiple_files_;
bool expect_done_;
+ TransferLedger global_ledger_;
+ TransferLedger current_ledger_;
LinePrinter line_printer_;
bool SendQuit() {
@@ -422,12 +532,6 @@
}
return true;
}
-
- static uint64_t CurrentTimeMs() {
- struct timeval tv;
- gettimeofday(&tv, 0); // (Not clock_gettime because of Mac/Windows.)
- return static_cast<uint64_t>(tv.tv_sec) * 1000 + tv.tv_usec / 1000;
- }
};
typedef void (sync_ls_cb)(unsigned mode, unsigned size, unsigned time, const char* name);
@@ -570,13 +674,12 @@
return false;
}
- sc.total_bytes_ += msg.data.size;
-
bytes_copied += msg.data.size;
-
+ sc.RecordBytesTransferred(msg.data.size);
sc.ReportProgress(rpath, bytes_copied, size);
}
+ sc.RecordFilesTransferred(1);
adb_close(lfd);
return true;
}
@@ -661,13 +764,14 @@
static bool copy_local_dir_remote(SyncConnection& sc, std::string lpath,
std::string rpath, bool check_timestamps,
bool list_only) {
+ sc.NewTransfer();
+
// Make sure that both directory paths end in a slash.
// Both paths are known to be nonempty, so we don't need to check.
ensure_trailing_separators(lpath, rpath);
// Recursively build the list of files to copy.
std::vector<copyinfo> file_list;
- int pushed = 0;
int skipped = 0;
if (!local_build_list(sc, &file_list, lpath, rpath)) {
return false;
@@ -699,21 +803,19 @@
for (const copyinfo& ci : file_list) {
if (!ci.skip) {
if (list_only) {
- sc.Error("would push: %s -> %s", ci.lpath.c_str(), ci.rpath.c_str());
+ sc.Println("would push: %s -> %s", ci.lpath.c_str(), ci.rpath.c_str());
} else {
if (!sync_send(sc, ci.lpath.c_str(), ci.rpath.c_str(), ci.time, ci.mode)) {
return false;
}
}
- pushed++;
} else {
skipped++;
}
}
- sc.Printf("%s: %d file%s pushed. %d file%s skipped.%s", rpath.c_str(),
- pushed, (pushed == 1) ? "" : "s", skipped,
- (skipped == 1) ? "" : "s", sc.TransferRate().c_str());
+ sc.RecordFilesSkipped(skipped);
+ sc.ReportTransferRate(lpath, TransferDirection::push);
return true;
}
@@ -789,10 +891,14 @@
path_holder += adb_basename(src_path);
dst_path = path_holder.c_str();
}
+
+ sc.NewTransfer();
sc.SetExpectedTotalBytes(st.st_size);
success &= sync_send(sc, src_path, dst_path, st.st_mtime, st.st_mode);
+ sc.ReportTransferRate(src_path, TransferDirection::push);
}
+ sc.ReportOverallTransferRate(TransferDirection::push);
return success;
}
@@ -878,6 +984,8 @@
static bool copy_remote_dir_local(SyncConnection& sc, std::string rpath,
std::string lpath, bool copy_attrs) {
+ sc.NewTransfer();
+
// Make sure that both directory paths end in a slash.
// Both paths are known to be nonempty, so we don't need to check.
ensure_trailing_separators(lpath, rpath);
@@ -891,7 +999,6 @@
sc.ComputeExpectedTotalBytes(file_list);
- int pulled = 0;
int skipped = 0;
for (const copyinfo &ci : file_list) {
if (!ci.skip) {
@@ -903,7 +1010,6 @@
ci.lpath.c_str(), strerror(errno));
return false;
}
- pulled++;
continue;
}
@@ -914,15 +1020,13 @@
if (copy_attrs && set_time_and_mode(ci.lpath, ci.time, ci.mode)) {
return false;
}
- pulled++;
} else {
skipped++;
}
}
- sc.Printf("%s: %d file%s pulled. %d file%s skipped.%s", rpath.c_str(),
- pulled, (pulled == 1) ? "" : "s", skipped,
- (skipped == 1) ? "" : "s", sc.TransferRate().c_str());
+ sc.RecordFilesSkipped(skipped);
+ sc.ReportTransferRate(rpath, TransferDirection::pull);
return true;
}
@@ -1021,6 +1125,7 @@
dst_path = path_holder.c_str();
}
+ sc.NewTransfer();
sc.SetExpectedTotalBytes(src_size);
if (!sync_recv(sc, src_path, dst_path)) {
success = false;
@@ -1031,8 +1136,10 @@
success = false;
continue;
}
+ sc.ReportTransferRate(src_path, TransferDirection::pull);
}
+ sc.ReportOverallTransferRate(TransferDirection::pull);
return success;
}
@@ -1040,5 +1147,9 @@
SyncConnection sc;
if (!sc.IsValid()) return false;
- return copy_local_dir_remote(sc, lpath, rpath, true, list_only);
+ bool success = copy_local_dir_remote(sc, lpath, rpath, true, list_only);
+ if (!list_only) {
+ sc.ReportOverallTransferRate(TransferDirection::push);
+ }
+ return success;
}
diff --git a/adb/line_printer.cpp b/adb/line_printer.cpp
index 4ec8979..64d10b6 100644
--- a/adb/line_printer.cpp
+++ b/adb/line_printer.cpp
@@ -124,4 +124,5 @@
void LinePrinter::KeepInfoLine() {
if (!have_blank_line_) Out("\n");
+ have_blank_line_ = true;
}
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index 04df16f..333b861 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -828,4 +828,9 @@
// configured to drop after 10 missed keepalives. Returns true on success.
bool set_tcp_keepalive(int fd, int interval_sec);
+#if defined(_WIN32)
+// Win32 defines ERROR, which we don't need, but which conflicts with google3 logging.
+#undef ERROR
+#endif
+
#endif /* _ADB_SYSDEPS_H */
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index ee27406..109a548 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -952,7 +952,7 @@
_socket_set_errno(err);
return -1;
}
- std::unique_ptr<struct addrinfo, decltype(freeaddrinfo)*> addrinfo(addrinfo_ptr, freeaddrinfo);
+ std::unique_ptr<struct addrinfo, decltype(&freeaddrinfo)> addrinfo(addrinfo_ptr, freeaddrinfo);
addrinfo_ptr = nullptr;
// TODO: Try all the addresses if there's more than one? This just uses
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 65b05b8..e0216e3 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -35,6 +35,7 @@
#include <android-base/strings.h>
#include "adb.h"
+#include "adb_auth.h"
#include "adb_utils.h"
#include "diagnose_usb.h"
@@ -1074,3 +1075,11 @@
return 0;
}
}
+
+RSA* atransport::NextKey() {
+ if (keys_.empty()) keys_ = adb_auth_get_private_keys();
+
+ RSA* result = keys_[0];
+ keys_.pop_front();
+ return result;
+}
diff --git a/adb/transport.h b/adb/transport.h
index 46d472b..d41c8bd 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -19,12 +19,15 @@
#include <sys/types.h>
+#include <deque>
#include <list>
#include <string>
#include <unordered_set>
#include "adb.h"
+#include <openssl/rsa.h>
+
typedef std::unordered_set<std::string> FeatureSet;
const FeatureSet& supported_features();
@@ -104,7 +107,8 @@
return type == kTransportLocal && local_port_for_emulator_ == -1;
}
- void* key = nullptr;
+ RSA* NextKey();
+
unsigned char token[TOKEN_SIZE] = {};
size_t failed_auth_attempts = 0;
@@ -156,6 +160,8 @@
// A list of adisconnect callbacks called when the transport is kicked.
std::list<adisconnect*> disconnects_;
+ std::deque<RSA*> keys_;
+
DISALLOW_COPY_AND_ASSIGN(atransport);
};
diff --git a/base/include/android-base/logging.h b/base/include/android-base/logging.h
index 56e2dde..66d60c9 100644
--- a/base/include/android-base/logging.h
+++ b/base/include/android-base/logging.h
@@ -53,8 +53,8 @@
typedef std::function<void(LogId, LogSeverity, const char*, const char*,
unsigned int, const char*)> LogFunction;
-extern void StderrLogger(LogId, LogSeverity, const char*, const char*,
- unsigned int, const char*);
+void KernelLogger(LogId, LogSeverity, const char*, const char*, unsigned int, const char*);
+void StderrLogger(LogId, LogSeverity, const char*, const char*, unsigned int, const char*);
#ifdef __ANDROID__
// We expose this even though it is the default because a user that wants to
@@ -79,17 +79,14 @@
// The tag (or '*' for the global level) comes first, followed by a colon and a
// letter indicating the minimum priority level we're expected to log. This can
// be used to reveal or conceal logs with specific tags.
-extern void InitLogging(char* argv[], LogFunction&& logger);
+void InitLogging(char* argv[], LogFunction&& logger);
// Configures logging using the default logger (logd for the device, stderr for
// the host).
-extern void InitLogging(char* argv[]);
+void InitLogging(char* argv[]);
// Replace the current logger.
-extern void SetLogger(LogFunction&& logger);
-
-// Get the minimum severity level for logging.
-extern LogSeverity GetMinimumLogSeverity();
+void SetLogger(LogFunction&& logger);
class ErrnoRestorer {
public:
@@ -334,6 +331,12 @@
DISALLOW_COPY_AND_ASSIGN(LogMessage);
};
+// Get the minimum severity level for logging.
+LogSeverity GetMinimumLogSeverity();
+
+// Set the minimum severity level for logging, returning the old severity.
+LogSeverity SetMinimumLogSeverity(LogSeverity new_severity);
+
// Allows to temporarily change the minimum severity level for logging.
class ScopedLogSeverity {
public:
diff --git a/base/logging.cpp b/base/logging.cpp
index 959bb8b..1f47a9f 100644
--- a/base/logging.cpp
+++ b/base/logging.cpp
@@ -14,12 +14,13 @@
* limitations under the License.
*/
-#ifdef _WIN32
+#if defined(_WIN32)
#include <windows.h>
#endif
#include "android-base/logging.h"
+#include <fcntl.h>
#include <libgen.h>
#include <time.h>
@@ -30,6 +31,10 @@
#include <errno.h>
#endif
+#if defined(__linux__)
+#include <sys/uio.h>
+#endif
+
#include <iostream>
#include <limits>
#include <sstream>
@@ -172,10 +177,6 @@
static LogSeverity gMinimumLogSeverity = INFO;
static auto& gProgramInvocationName = *new std::unique_ptr<std::string>();
-LogSeverity GetMinimumLogSeverity() {
- return gMinimumLogSeverity;
-}
-
static const char* ProgramInvocationName() {
if (gProgramInvocationName == nullptr) {
gProgramInvocationName.reset(new std::string(getprogname()));
@@ -184,6 +185,42 @@
return gProgramInvocationName->c_str();
}
+#if defined(__linux__)
+void KernelLogger(android::base::LogId, android::base::LogSeverity severity,
+ const char* tag, const char*, unsigned int, const char* msg) {
+ static constexpr int kLogSeverityToKernelLogLevel[] = {
+ [android::base::VERBOSE] = 7, // KERN_DEBUG (there is no verbose kernel log level)
+ [android::base::DEBUG] = 7, // KERN_DEBUG
+ [android::base::INFO] = 6, // KERN_INFO
+ [android::base::WARNING] = 4, // KERN_WARNING
+ [android::base::ERROR] = 3, // KERN_ERROR
+ [android::base::FATAL] = 2, // KERN_CRIT
+ };
+ static_assert(arraysize(kLogSeverityToKernelLogLevel) == android::base::FATAL + 1,
+ "Mismatch in size of kLogSeverityToKernelLogLevel and values in LogSeverity");
+
+ static int klog_fd = TEMP_FAILURE_RETRY(open("/dev/kmsg", O_WRONLY | O_CLOEXEC));
+ if (klog_fd == -1) return;
+
+ int level = kLogSeverityToKernelLogLevel[severity];
+
+ // The kernel's printk buffer is only 1024 bytes.
+ // TODO: should we automatically break up long lines into multiple lines?
+ // Or we could log but with something like "..." at the end?
+ char buf[1024];
+ size_t size = snprintf(buf, sizeof(buf), "<%d>%s: %s\n", level, tag, msg);
+ if (size > sizeof(buf)) {
+ size = snprintf(buf, sizeof(buf), "<%d>%s: %zu-byte message too long for printk\n",
+ level, tag, size);
+ }
+
+ iovec iov[1];
+ iov[0].iov_base = buf;
+ iov[0].iov_len = size;
+ TEMP_FAILURE_RETRY(writev(klog_fd, iov, 1));
+}
+#endif
+
void StderrLogger(LogId, LogSeverity severity, const char*, const char* file,
unsigned int line, const char* message) {
struct tm now;
@@ -211,28 +248,26 @@
LogdLogger::LogdLogger(LogId default_log_id) : default_log_id_(default_log_id) {
}
-static const android_LogPriority kLogSeverityToAndroidLogPriority[] = {
- ANDROID_LOG_VERBOSE, ANDROID_LOG_DEBUG, ANDROID_LOG_INFO,
- ANDROID_LOG_WARN, ANDROID_LOG_ERROR, ANDROID_LOG_FATAL,
-};
-static_assert(arraysize(kLogSeverityToAndroidLogPriority) == FATAL + 1,
- "Mismatch in size of kLogSeverityToAndroidLogPriority and values "
- "in LogSeverity");
-
-static const log_id kLogIdToAndroidLogId[] = {
- LOG_ID_MAX, LOG_ID_MAIN, LOG_ID_SYSTEM,
-};
-static_assert(arraysize(kLogIdToAndroidLogId) == SYSTEM + 1,
- "Mismatch in size of kLogIdToAndroidLogId and values in LogId");
-
void LogdLogger::operator()(LogId id, LogSeverity severity, const char* tag,
const char* file, unsigned int line,
const char* message) {
+ static constexpr android_LogPriority kLogSeverityToAndroidLogPriority[] = {
+ ANDROID_LOG_VERBOSE, ANDROID_LOG_DEBUG, ANDROID_LOG_INFO,
+ ANDROID_LOG_WARN, ANDROID_LOG_ERROR, ANDROID_LOG_FATAL,
+ };
+ static_assert(arraysize(kLogSeverityToAndroidLogPriority) == FATAL + 1,
+ "Mismatch in size of kLogSeverityToAndroidLogPriority and values in LogSeverity");
+
int priority = kLogSeverityToAndroidLogPriority[severity];
if (id == DEFAULT) {
id = default_log_id_;
}
+ static constexpr log_id kLogIdToAndroidLogId[] = {
+ LOG_ID_MAX, LOG_ID_MAIN, LOG_ID_SYSTEM,
+ };
+ static_assert(arraysize(kLogIdToAndroidLogId) == SYSTEM + 1,
+ "Mismatch in size of kLogIdToAndroidLogId and values in LogId");
log_id lg_id = kLogIdToAndroidLogId[id];
if (priority == ANDROID_LOG_FATAL) {
@@ -427,13 +462,22 @@
gLogger(id, severity, tag, file, line, message);
}
-ScopedLogSeverity::ScopedLogSeverity(LogSeverity level) {
- old_ = gMinimumLogSeverity;
- gMinimumLogSeverity = level;
+LogSeverity GetMinimumLogSeverity() {
+ return gMinimumLogSeverity;
+}
+
+LogSeverity SetMinimumLogSeverity(LogSeverity new_severity) {
+ LogSeverity old_severity = gMinimumLogSeverity;
+ gMinimumLogSeverity = new_severity;
+ return old_severity;
+}
+
+ScopedLogSeverity::ScopedLogSeverity(LogSeverity new_severity) {
+ old_ = SetMinimumLogSeverity(new_severity);
}
ScopedLogSeverity::~ScopedLogSeverity() {
- gMinimumLogSeverity = old_;
+ SetMinimumLogSeverity(old_);
}
} // namespace base
diff --git a/crash_reporter/Android.mk b/crash_reporter/Android.mk
index ce9dc73..4feb72a 100644
--- a/crash_reporter/Android.mk
+++ b/crash_reporter/Android.mk
@@ -135,9 +135,6 @@
include $(CLEAR_VARS)
LOCAL_MODULE := crash_reporter_tests
LOCAL_CPP_EXTENSION := $(crash_reporter_cpp_extension)
-ifdef BRILLO
-LOCAL_MODULE_TAGS := eng
-endif
LOCAL_SHARED_LIBRARIES := libchrome \
libbrillo \
libcutils \
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index 8a63f3f..f0131b8 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -9,6 +9,12 @@
"-Os",
],
+ target: {
+ android64: {
+ cflags: ["-DTARGET_IS_64_BIT"],
+ },
+ },
+
local_include_dirs: ["include"],
export_include_dirs: ["include"],
diff --git a/debuggerd/client/debuggerd_client.cpp b/debuggerd/client/debuggerd_client.cpp
index 44e92fe..bbc724a 100644
--- a/debuggerd/client/debuggerd_client.cpp
+++ b/debuggerd/client/debuggerd_client.cpp
@@ -185,7 +185,7 @@
return result;
}
-static void send_debuggerd_packet(siginfo_t* info) {
+static void send_debuggerd_packet() {
// Mutex to prevent multiple crashing threads from trying to talk
// to debuggerd at the same time.
static pthread_mutex_t crash_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -222,7 +222,6 @@
msg.abort_msg_address = reinterpret_cast<uintptr_t>(g_callbacks.get_abort_message());
}
- msg.original_si_code = (info != nullptr) ? info->si_code : 0;
ret = TEMP_FAILURE_RETRY(write(s, &msg, sizeof(msg)));
if (ret == sizeof(msg)) {
char debuggerd_ack;
@@ -254,7 +253,7 @@
log_signal_summary(signal_number, info);
- send_debuggerd_packet(info);
+ send_debuggerd_packet();
// We need to return from the signal handler so that debuggerd can dump the
// thread that crashed, but returning here does not guarantee that the signal
diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp
index a82fd07..61cceb0 100644
--- a/debuggerd/debuggerd.cpp
+++ b/debuggerd/debuggerd.cpp
@@ -51,6 +51,8 @@
#include <private/android_filesystem_config.h>
+#include <debuggerd/client.h>
+
#include "backtrace.h"
#include "getevent.h"
#include "signal_sender.h"
@@ -70,7 +72,6 @@
pid_t pid, tid;
uid_t uid, gid;
uintptr_t abort_msg_address;
- int32_t original_si_code;
};
static void wait_for_user_action(const debugger_request_t& request) {
@@ -222,7 +223,6 @@
out_request->uid = cr.uid;
out_request->gid = cr.gid;
out_request->abort_msg_address = msg.abort_msg_address;
- out_request->original_si_code = msg.original_si_code;
if (msg.action == DEBUGGER_ACTION_CRASH) {
// Ensure that the tid reported by the crashing process is valid.
@@ -459,9 +459,10 @@
return false;
}
- int total_sleep_time_usec = 0;
while (true) {
- int signal = wait_for_signal(request.tid, &total_sleep_time_usec);
+ // wait_for_signal waits for forever, but the watchdog process will kill us
+ // if it takes too long.
+ int signal = wait_for_signal(request.tid);
switch (signal) {
case -1:
ALOGE("debuggerd: timed out waiting for signal");
@@ -470,8 +471,8 @@
case SIGSTOP:
if (request.action == DEBUGGER_ACTION_DUMP_TOMBSTONE) {
ALOGV("debuggerd: stopped -- dumping to tombstone");
- engrave_tombstone(tombstone_fd, backtrace_map, request.pid, request.tid, siblings, signal,
- request.original_si_code, request.abort_msg_address, amfd_data);
+ engrave_tombstone(tombstone_fd, backtrace_map, request.pid, request.tid, siblings,
+ request.abort_msg_address, amfd_data);
} else if (request.action == DEBUGGER_ACTION_DUMP_BACKTRACE) {
ALOGV("debuggerd: stopped -- dumping to fd");
dump_backtrace(fd, backtrace_map, request.pid, request.tid, siblings, nullptr);
@@ -496,8 +497,8 @@
case SIGTRAP:
ALOGV("stopped -- fatal signal\n");
*crash_signal = signal;
- engrave_tombstone(tombstone_fd, backtrace_map, request.pid, request.tid, siblings, signal,
- request.original_si_code, request.abort_msg_address, amfd_data);
+ engrave_tombstone(tombstone_fd, backtrace_map, request.pid, request.tid, siblings,
+ request.abort_msg_address, amfd_data);
break;
default:
diff --git a/debuggerd/include/debuggerd/client.h b/debuggerd/include/debuggerd/client.h
index 41b7b3a..8225c73 100644
--- a/debuggerd/include/debuggerd/client.h
+++ b/debuggerd/include/debuggerd/client.h
@@ -44,7 +44,6 @@
int32_t action;
pid_t tid;
uint64_t abort_msg_address;
- int32_t original_si_code;
} debugger_msg_t;
// These callbacks are called in a signal handler, and thus must be async signal safe.
diff --git a/debuggerd/test/tombstone_test.cpp b/debuggerd/test/tombstone_test.cpp
index 58d640e..5ee07cd 100644
--- a/debuggerd/test/tombstone_test.cpp
+++ b/debuggerd/test/tombstone_test.cpp
@@ -595,7 +595,7 @@
si.si_signo = 0;
ptrace_set_fake_getsiginfo(si);
- dump_signal_info(&log_, 123, SIGSEGV, 10);
+ dump_signal_info(&log_, 123);
std::string tombstone_contents;
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
diff --git a/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp
index dfdf29c..9359678 100644
--- a/debuggerd/tombstone.cpp
+++ b/debuggerd/tombstone.cpp
@@ -176,7 +176,7 @@
_LOG(log, logtype::HEADER, "ABI: '%s'\n", ABI_STRING);
}
-static void dump_signal_info(log_t* log, pid_t tid, int signal, int si_code) {
+static void dump_signal_info(log_t* log, pid_t tid) {
siginfo_t si;
memset(&si, 0, sizeof(si));
if (ptrace(PTRACE_GETSIGINFO, tid, 0, &si) == -1) {
@@ -184,18 +184,15 @@
return;
}
- // bionic has to re-raise some signals, which overwrites the si_code with SI_TKILL.
- si.si_code = si_code;
-
char addr_desc[32]; // ", fault addr 0x1234"
- if (signal_has_si_addr(signal)) {
+ if (signal_has_si_addr(si.si_signo)) {
snprintf(addr_desc, sizeof(addr_desc), "%p", si.si_addr);
} else {
snprintf(addr_desc, sizeof(addr_desc), "--------");
}
- _LOG(log, logtype::HEADER, "signal %d (%s), code %d (%s), fault addr %s\n",
- signal, get_signame(signal), si.si_code, get_sigcode(signal, si.si_code), addr_desc);
+ _LOG(log, logtype::HEADER, "signal %d (%s), code %d (%s), fault addr %s\n", si.si_signo,
+ get_signame(si.si_signo), si.si_code, get_sigcode(si.si_signo, si.si_code), addr_desc);
}
static void dump_thread_info(log_t* log, pid_t pid, pid_t tid) {
@@ -445,17 +442,14 @@
}
}
-static void dump_thread(log_t* log, pid_t pid, pid_t tid, BacktraceMap* map, int signal,
- int si_code, uintptr_t abort_msg_address, bool primary_thread) {
+static void dump_thread(log_t* log, pid_t pid, pid_t tid, BacktraceMap* map,
+ uintptr_t abort_msg_address, bool primary_thread) {
log->current_tid = tid;
if (!primary_thread) {
_LOG(log, logtype::THREAD, "--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---\n");
}
dump_thread_info(log, pid, tid);
-
- if (signal) {
- dump_signal_info(log, tid, signal, si_code);
- }
+ dump_signal_info(log, tid);
std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, tid, map));
if (primary_thread) {
@@ -606,8 +600,7 @@
// Dumps all information about the specified pid to the tombstone.
static void dump_crash(log_t* log, BacktraceMap* map, pid_t pid, pid_t tid,
- const std::set<pid_t>& siblings, int signal, int si_code,
- uintptr_t abort_msg_address) {
+ const std::set<pid_t>& siblings, uintptr_t abort_msg_address) {
// don't copy log messages to tombstone unless this is a dev device
char value[PROPERTY_VALUE_MAX];
property_get("ro.debuggable", value, "0");
@@ -616,14 +609,14 @@
_LOG(log, logtype::HEADER,
"*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n");
dump_header_info(log);
- dump_thread(log, pid, tid, map, signal, si_code, abort_msg_address, true);
+ dump_thread(log, pid, tid, map, abort_msg_address, true);
if (want_logs) {
dump_logs(log, pid, 5);
}
if (!siblings.empty()) {
for (pid_t sibling : siblings) {
- dump_thread(log, pid, sibling, map, 0, 0, 0, false);
+ dump_thread(log, pid, sibling, map, 0, false);
}
}
@@ -686,8 +679,8 @@
}
void engrave_tombstone(int tombstone_fd, BacktraceMap* map, pid_t pid, pid_t tid,
- const std::set<pid_t>& siblings, int signal, int original_si_code,
- uintptr_t abort_msg_address, std::string* amfd_data) {
+ const std::set<pid_t>& siblings, uintptr_t abort_msg_address,
+ std::string* amfd_data) {
log_t log;
log.current_tid = tid;
log.crashed_tid = tid;
@@ -699,5 +692,5 @@
log.tfd = tombstone_fd;
log.amfd_data = amfd_data;
- dump_crash(&log, map, pid, tid, siblings, signal, original_si_code, abort_msg_address);
+ dump_crash(&log, map, pid, tid, siblings, abort_msg_address);
}
diff --git a/debuggerd/tombstone.h b/debuggerd/tombstone.h
index 487d950..e1c39c5 100644
--- a/debuggerd/tombstone.h
+++ b/debuggerd/tombstone.h
@@ -33,7 +33,7 @@
/* Creates a tombstone file and writes the crash dump to it. */
void engrave_tombstone(int tombstone_fd, BacktraceMap* map, pid_t pid, pid_t tid,
- const std::set<pid_t>& siblings, int signal, int original_si_code,
- uintptr_t abort_msg_address, std::string* amfd_data);
+ const std::set<pid_t>& siblings, uintptr_t abort_msg_address,
+ std::string* amfd_data);
#endif // _DEBUGGERD_TOMBSTONE_H
diff --git a/debuggerd/utility.cpp b/debuggerd/utility.cpp
index bd06095..7fabf69 100644
--- a/debuggerd/utility.cpp
+++ b/debuggerd/utility.cpp
@@ -31,9 +31,6 @@
#include <backtrace/Backtrace.h>
#include <log/log.h>
-constexpr int SLEEP_TIME_USEC = 50000; // 0.05 seconds
-constexpr int MAX_TOTAL_SLEEP_USEC = 10000000; // 10 seconds
-
// Whitelist output desired in the logcat output.
bool is_allowed_in_logcat(enum logtype ltype) {
if ((ltype == HEADER)
@@ -74,10 +71,10 @@
}
}
-int wait_for_signal(pid_t tid, int* total_sleep_time_usec) {
+int wait_for_signal(pid_t tid) {
while (true) {
int status;
- pid_t n = TEMP_FAILURE_RETRY(waitpid(tid, &status, __WALL | WNOHANG));
+ pid_t n = TEMP_FAILURE_RETRY(waitpid(tid, &status, __WALL));
if (n == -1) {
ALOGE("waitpid failed: tid %d, %s", tid, strerror(errno));
return -1;
@@ -91,14 +88,6 @@
return -1;
}
}
-
- if (*total_sleep_time_usec > MAX_TOTAL_SLEEP_USEC) {
- ALOGE("timed out waiting for stop signal: tid=%d", tid);
- return -1;
- }
-
- usleep(SLEEP_TIME_USEC);
- *total_sleep_time_usec += SLEEP_TIME_USEC;
}
}
diff --git a/debuggerd/utility.h b/debuggerd/utility.h
index cd01188..d820f0f 100644
--- a/debuggerd/utility.h
+++ b/debuggerd/utility.h
@@ -77,7 +77,7 @@
void _LOG(log_t* log, logtype ltype, const char *fmt, ...)
__attribute__ ((format(printf, 3, 4)));
-int wait_for_signal(pid_t tid, int* total_sleep_time_usec);
+int wait_for_signal(pid_t tid);
void dump_memory(log_t* log, Backtrace* backtrace, uintptr_t addr, const char* fmt, ...);
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index dde21d5..c097d04 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -519,6 +519,7 @@
ZipEntry zip_entry;
if (FindEntry(zip, zip_entry_name, &zip_entry) != 0) {
fprintf(stderr, "archive does not contain '%s'\n", entry_name);
+ fclose(fp);
return -1;
}
@@ -526,10 +527,12 @@
int error = ExtractEntryToFile(zip, &zip_entry, fd);
if (error != 0) {
fprintf(stderr, "failed to extract '%s': %s\n", entry_name, ErrorCodeString(error));
+ fclose(fp);
return -1;
}
lseek(fd, 0, SEEK_SET);
+ // TODO: We're leaking 'fp' here.
return fd;
}
diff --git a/fs_mgr/Android.mk b/fs_mgr/Android.mk
index 7da3ca4..d6b699b 100644
--- a/fs_mgr/Android.mk
+++ b/fs_mgr/Android.mk
@@ -7,8 +7,8 @@
libfec \
libfec_rs \
libbase \
- libcrypto_utils_static \
- libcrypto_static \
+ libcrypto_utils \
+ libcrypto \
libext4_utils_static \
libsquashfs_utils \
libselinux
diff --git a/include/utils/Condition.h b/include/utils/Condition.h
index a420185..5650598 100644
--- a/include/utils/Condition.h
+++ b/include/utils/Condition.h
@@ -54,7 +54,7 @@
};
Condition();
- Condition(int type);
+ explicit Condition(int type);
~Condition();
// Wait on the condition variable. Lock the mutex before calling.
status_t wait(Mutex& mutex);
diff --git a/include/utils/Mutex.h b/include/utils/Mutex.h
index f027c79..8b720b9 100644
--- a/include/utils/Mutex.h
+++ b/include/utils/Mutex.h
@@ -48,8 +48,8 @@
};
Mutex();
- Mutex(const char* name);
- Mutex(int type, const char* name = NULL);
+ explicit Mutex(const char* name);
+ explicit Mutex(int type, const char* name = NULL);
~Mutex();
// lock or unlock the mutex
@@ -73,8 +73,8 @@
// constructed and released when Autolock goes out of scope.
class Autolock {
public:
- inline Autolock(Mutex& mutex) : mLock(mutex) { mLock.lock(); }
- inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); }
+ inline explicit Autolock(Mutex& mutex) : mLock(mutex) { mLock.lock(); }
+ inline explicit Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); }
inline ~Autolock() { mLock.unlock(); }
private:
Mutex& mLock;
diff --git a/include/utils/RWLock.h b/include/utils/RWLock.h
index e743b1c..d5b81d3 100644
--- a/include/utils/RWLock.h
+++ b/include/utils/RWLock.h
@@ -47,8 +47,8 @@
};
RWLock();
- RWLock(const char* name);
- RWLock(int type, const char* name = NULL);
+ explicit RWLock(const char* name);
+ explicit RWLock(int type, const char* name = NULL);
~RWLock();
status_t readLock();
@@ -59,7 +59,7 @@
class AutoRLock {
public:
- inline AutoRLock(RWLock& rwlock) : mLock(rwlock) { mLock.readLock(); }
+ inline explicit AutoRLock(RWLock& rwlock) : mLock(rwlock) { mLock.readLock(); }
inline ~AutoRLock() { mLock.unlock(); }
private:
RWLock& mLock;
@@ -67,7 +67,7 @@
class AutoWLock {
public:
- inline AutoWLock(RWLock& rwlock) : mLock(rwlock) { mLock.writeLock(); }
+ inline explicit AutoWLock(RWLock& rwlock) : mLock(rwlock) { mLock.writeLock(); }
inline ~AutoWLock() { mLock.unlock(); }
private:
RWLock& mLock;
diff --git a/include/utils/RefBase.h b/include/utils/RefBase.h
index c82e7d9..a232a65 100644
--- a/include/utils/RefBase.h
+++ b/include/utils/RefBase.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005 The Android Open Source Project
+ * 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.
@@ -14,6 +14,146 @@
* limitations under the License.
*/
+
+// SOME COMMENTS ABOUT USAGE:
+
+// This provides primarily wp<> weak pointer types and RefBase, which work
+// together with sp<> from <StrongPointer.h>.
+
+// sp<> (and wp<>) are a type of smart pointer that use a well defined protocol
+// to operate. As long as the object they are templated with implements that
+// protocol, these smart pointers work. In several places the platform
+// instantiates sp<> with non-RefBase objects; the two are not tied to each
+// other.
+
+// RefBase is such an implementation and it supports strong pointers, weak
+// pointers and some magic features for the binder.
+
+// So, when using RefBase objects, you have the ability to use strong and weak
+// pointers through sp<> and wp<>.
+
+// Normally, when the last strong pointer goes away, the object is destroyed,
+// i.e. it's destructor is called. HOWEVER, parts of its associated memory is not
+// freed until the last weak pointer is released.
+
+// Weak pointers are essentially "safe" pointers. They are always safe to
+// access through promote(). They may return nullptr if the object was
+// destroyed because it ran out of strong pointers. This makes them good candidates
+// for keys in a cache for instance.
+
+// Weak pointers remain valid for comparison purposes even after the underlying
+// object has been destroyed. Even if object A is destroyed and its memory reused
+// for B, A remaining weak pointer to A will not compare equal to one to B.
+// This again makes them attractive for use as keys.
+
+// How is this supposed / intended to be used?
+
+// Our recommendation is to use strong references (sp<>) when there is an
+// ownership relation. e.g. when an object "owns" another one, use a strong
+// ref. And of course use strong refs as arguments of functions (it's extremely
+// rare that a function will take a wp<>).
+
+// Typically a newly allocated object will immediately be used to initialize
+// a strong pointer, which may then be used to construct or assign to other
+// strong and weak pointers.
+
+// Use weak references when there are no ownership relation. e.g. the keys in a
+// cache (you cannot use plain pointers because there is no safe way to acquire
+// a strong reference from a vanilla pointer).
+
+// This implies that two objects should never (or very rarely) have sp<> on
+// each other, because they can't both own each other.
+
+
+// Caveats with reference counting
+
+// Obviously, circular strong references are a big problem; this creates leaks
+// and it's hard to debug -- except it's in fact really easy because RefBase has
+// tons of debugging code for that. It can basically tell you exactly where the
+// leak is.
+
+// Another problem has to do with destructors with side effects. You must
+// assume that the destructor of reference counted objects can be called AT ANY
+// TIME. For instance code as simple as this:
+
+// void setStuff(const sp<Stuff>& stuff) {
+// std::lock_guard<std::mutex> lock(mMutex);
+// mStuff = stuff;
+// }
+
+// is very dangerous. This code WILL deadlock one day or another.
+
+// What isn't obvious is that ~Stuff() can be called as a result of the
+// assignment. And it gets called with the lock held. First of all, the lock is
+// protecting mStuff, not ~Stuff(). Secondly, if ~Stuff() uses its own internal
+// mutex, now you have mutex ordering issues. Even worse, if ~Stuff() is
+// virtual, now you're calling into "user" code (potentially), by that, I mean,
+// code you didn't even write.
+
+// A correct way to write this code is something like:
+
+// void setStuff(const sp<Stuff>& stuff) {
+// std::unique_lock<std::mutex> lock(mMutex);
+// sp<Stuff> hold = mStuff;
+// mStuff = stuff;
+// lock.unlock();
+// }
+
+// More importantly, reference counted objects should do as little work as
+// possible in their destructor, or at least be mindful that their destructor
+// could be called from very weird and unintended places.
+
+// Other more specific restrictions for wp<> and sp<>:
+
+// Constructing a strong or weak pointer to "this" in its constructors is almost
+// always wrong. In the case of strong pointers. it is always wrong with RefBase
+// because the onFirstRef() callback will be mode on an incompletely constructed
+// object. In either case, it is wrong if such a pointer does not outlive the
+// constructor, since destruction of the smart pointer will attempt to destroy the
+// object before construction is finished, normally resulting in a pointer to a
+// destroyed object being returned from a new expression.
+
+// In the case of weak pointers, this occurs because an object that has never been
+// referenced by a strong pointer is destroyed when the last weak pointer disappears.
+
+// Such strong or weak pointers can be safely created in the RefBase onFirstRef()
+// callback.
+
+// Use of wp::unsafe_get() for any purpose other than debugging is almost
+// always wrong. Unless you somehow know that there is a longer-lived sp<> to
+// the same object, it may well return a pointer to a deallocated object that
+// has since been reallocated for a different purpose. (And if you know there
+// is a longer-lived sp<>, why not use an sp<> directly?) A wp<> should only be
+// dereferenced by using promote().
+
+// Explicitly deleting or otherwise destroying a RefBase object with outstanding
+// wp<> or sp<> pointers to it will result in heap corruption.
+
+// Extra Features:
+
+// RefBase::extendObjectLifetime() can be used to prevent destruction of the
+// object while there are still weak references. This is really special purpose
+// functionality to support Binder.
+
+// Wp::promote(), implemented via the attemptIncStrong() member function, is
+// used to try to convert a weak pointer back to a strong pointer. It's the
+// normal way to try to access the fields of an object referenced only through
+// a wp<>. Binder code also sometimes uses attemptIncStrong() directly.
+
+// RefBase provides a number of additional callbacks for certain reference count
+// events, as well as some debugging facilities.
+
+// Debugging support can be enabled by turning on DEBUG_REFS in RefBase.cpp.
+// Otherwise essentially no checking is provided.
+
+// Thread safety:
+
+// Like std::shared_ptr, sp<> and wp<> allow concurrent accesses to DIFFERENT
+// sp<> and wp<> instances that happen to refer to the same underlying object.
+// They do NOT support concurrent access (where at least one access is a write)
+// to THE SAME sp<> or wp<>. In effect, their thread-safety properties are
+// exactly like those of T*, NOT atomic<T*>.
+
#ifndef ANDROID_REF_BASE_H
#define ANDROID_REF_BASE_H
@@ -142,9 +282,19 @@
FIRST_INC_STRONG = 0x0001
};
+ // Invoked after creation of initial strong pointer/reference.
virtual void onFirstRef();
+ // Invoked when either the last strong reference goes away, or we need to undo
+ // the effect of an unnecessary onIncStrongAttempted.
virtual void onLastStrongRef(const void* id);
+ // Only called in OBJECT_LIFETIME_WEAK case. Returns true if OK to promote to
+ // strong reference. May have side effects if it returns true.
+ // The first flags argument is always FIRST_INC_STRONG.
+ // TODO: Remove initial flag argument.
virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
+ // Invoked in the OBJECT_LIFETIME_WEAK case when the last reference of either
+ // kind goes away. Unused.
+ // TODO: Remove.
virtual void onLastWeakRef(const void* id);
private:
@@ -222,12 +372,12 @@
inline wp() : m_ptr(0) { }
- wp(T* other);
+ wp(T* other); // NOLINT(implicit)
wp(const wp<T>& other);
- wp(const sp<T>& other);
- template<typename U> wp(U* other);
- template<typename U> wp(const sp<U>& other);
- template<typename U> wp(const wp<U>& other);
+ explicit wp(const sp<T>& other);
+ template<typename U> wp(U* other); // NOLINT(implicit)
+ template<typename U> wp(const sp<U>& other); // NOLINT(implicit)
+ template<typename U> wp(const wp<U>& other); // NOLINT(implicit)
~wp();
diff --git a/include/utils/StrongPointer.h b/include/utils/StrongPointer.h
index 50fde35..d90b788 100644
--- a/include/utils/StrongPointer.h
+++ b/include/utils/StrongPointer.h
@@ -60,12 +60,12 @@
public:
inline sp() : m_ptr(0) { }
- sp(T* other);
+ sp(T* other); // NOLINT(implicit)
sp(const sp<T>& other);
sp(sp<T>&& other);
- template<typename U> sp(U* other);
- template<typename U> sp(const sp<U>& other);
- template<typename U> sp(sp<U>&& other);
+ template<typename U> sp(U* other); // NOLINT(implicit)
+ template<typename U> sp(const sp<U>& other); // NOLINT(implicit)
+ template<typename U> sp(sp<U>&& other); // NOLINT(implicit)
~sp();
diff --git a/include/utils/Thread.h b/include/utils/Thread.h
index 1532b7e..0f7ac9f 100644
--- a/include/utils/Thread.h
+++ b/include/utils/Thread.h
@@ -41,7 +41,7 @@
public:
// Create a Thread object, but doesn't create or start the associated
// thread. See the run() method.
- Thread(bool canCallJava = true);
+ explicit Thread(bool canCallJava = true);
virtual ~Thread();
// Start the thread in threadLoop() which needs to be implemented.
diff --git a/include/utils/TypeHelpers.h b/include/utils/TypeHelpers.h
index 61d618e..64d25c5 100644
--- a/include/utils/TypeHelpers.h
+++ b/include/utils/TypeHelpers.h
@@ -240,7 +240,7 @@
key_value_pair_t() { }
key_value_pair_t(const key_value_pair_t& o) : key(o.key), value(o.value) { }
key_value_pair_t(const KEY& k, const VALUE& v) : key(k), value(v) { }
- key_value_pair_t(const KEY& k) : key(k) { }
+ explicit key_value_pair_t(const KEY& k) : key(k) { }
inline bool operator < (const key_value_pair_t& o) const {
return strictly_order_type(key, o.key);
}
diff --git a/include/utils/VectorImpl.h b/include/utils/VectorImpl.h
index 21ad71c..4dd91fd 100644
--- a/include/utils/VectorImpl.h
+++ b/include/utils/VectorImpl.h
@@ -132,7 +132,7 @@
{
public:
SortedVectorImpl(size_t itemSize, uint32_t flags);
- SortedVectorImpl(const VectorImpl& rhs);
+ explicit SortedVectorImpl(const VectorImpl& rhs);
virtual ~SortedVectorImpl();
SortedVectorImpl& operator = (const SortedVectorImpl& rhs);
diff --git a/init/Android.mk b/init/Android.mk
index 7aa3c3f..5888456 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -94,8 +94,8 @@
libc \
libselinux \
liblog \
- libcrypto_utils_static \
- libcrypto_static \
+ libcrypto_utils \
+ libcrypto \
libc++_static \
libdl \
libsparse_static \
diff --git a/init/action.cpp b/init/action.cpp
index f3e362e..ed88f6d 100644
--- a/init/action.cpp
+++ b/init/action.cpp
@@ -118,7 +118,8 @@
Timer t;
int result = command.InvokeFunc();
- if (klog_get_level() >= KLOG_DEBUG_LEVEL) {
+ // TODO: this should probably be changed to "if (failed || took a long time)"...
+ if (android::base::GetMinimumLogSeverity() <= android::base::DEBUG) {
std::string trigger_name = BuildTriggersString();
std::string cmd_str = command.BuildCommandString();
std::string source = command.BuildSourceString();
diff --git a/init/builtins.cpp b/init/builtins.cpp
index d64c3d2..3d220c5 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -482,11 +482,7 @@
* not return.
*/
static int do_mount_all(const std::vector<std::string>& args) {
- pid_t pid;
int ret = -1;
- int child_ret = -1;
- int status;
- struct fstab *fstab;
const char* fstabfile = args[1].c_str();
/*
@@ -495,9 +491,10 @@
* process if anything goes wrong (crash or memory leak), and wait for
* the child to finish in the parent.
*/
- pid = fork();
+ pid_t pid = fork();
if (pid > 0) {
/* Parent. Wait for the child to return */
+ int status;
int wp_ret = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
if (wp_ret == -1) {
// Unexpected error code. We will continue anyway.
@@ -511,9 +508,13 @@
}
} else if (pid == 0) {
/* child, call fs_mgr_mount_all() */
- klog_set_level(6); /* So we can see what fs_mgr_mount_all() does */
- fstab = fs_mgr_read_fstab(fstabfile);
- child_ret = fs_mgr_mount_all(fstab);
+
+ // So we can always see what fs_mgr_mount_all() does.
+ // Only needed if someone explicitly changes the default log level in their init.rc.
+ android::base::ScopedLogSeverity info(android::base::INFO);
+
+ struct fstab* fstab = fs_mgr_read_fstab(fstabfile);
+ int child_ret = fs_mgr_mount_all(fstab);
fs_mgr_free_fstab(fstab);
if (child_ret == -1) {
PLOG(ERROR) << "fs_mgr_mount_all returned an error";
@@ -866,12 +867,23 @@
}
static int do_loglevel(const std::vector<std::string>& args) {
+ // TODO: support names instead/as well?
int log_level = std::stoi(args[1]);
- if (log_level < KLOG_ERROR_LEVEL || log_level > KLOG_DEBUG_LEVEL) {
- LOG(ERROR) << "loglevel: invalid log level " << log_level;
- return -EINVAL;
+ android::base::LogSeverity severity;
+ switch (log_level) {
+ case 7: severity = android::base::DEBUG; break;
+ case 6: severity = android::base::INFO; break;
+ case 5:
+ case 4: severity = android::base::WARNING; break;
+ case 3: severity = android::base::ERROR; break;
+ case 2:
+ case 1:
+ case 0: severity = android::base::FATAL; break;
+ default:
+ LOG(ERROR) << "loglevel: invalid log level " << log_level;
+ return -EINVAL;
}
- klog_set_level(log_level);
+ android::base::SetMinimumLogSeverity(severity);
return 0;
}
diff --git a/init/log.cpp b/init/log.cpp
index 379141a..8618340 100644
--- a/init/log.cpp
+++ b/init/log.cpp
@@ -17,52 +17,16 @@
#include "log.h"
#include <fcntl.h>
-#include <stdlib.h>
#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/uio.h>
#include <selinux/selinux.h>
-static const int kLogSeverityToKLogLevel[] = {
- [android::base::VERBOSE] = KLOG_DEBUG_LEVEL,
- [android::base::DEBUG] = KLOG_DEBUG_LEVEL,
- [android::base::INFO] = KLOG_INFO_LEVEL,
- [android::base::WARNING] = KLOG_WARNING_LEVEL,
- [android::base::ERROR] = KLOG_ERROR_LEVEL,
- [android::base::FATAL] = KLOG_ERROR_LEVEL,
-};
-static_assert(arraysize(kLogSeverityToKLogLevel) == android::base::FATAL + 1,
- "Mismatch in size of kLogSeverityToKLogLevel and values in LogSeverity");
-
-static void KernelLogger(android::base::LogId, android::base::LogSeverity severity,
- const char* tag, const char*, unsigned int, const char* msg) {
- int level = kLogSeverityToKLogLevel[severity];
- if (level > klog_get_level()) return;
-
- // The kernel's printk buffer is only 1024 bytes.
- // TODO: should we automatically break up long lines into multiple lines?
- // Or we could log but with something like "..." at the end?
- char buf[1024];
- size_t size = snprintf(buf, sizeof(buf), "<%d>%s: %s\n", level, tag, msg);
- if (size > sizeof(buf)) {
- size = snprintf(buf, sizeof(buf), "<%d>%s: %zu-byte message too long for printk\n",
- level, tag, size);
- }
-
- iovec iov[1];
- iov[0].iov_base = buf;
- iov[0].iov_len = size;
- klog_writev(level, iov, 1);
-}
-
void InitKernelLogging(char* argv[]) {
// Make stdin/stdout/stderr all point to /dev/null.
int fd = open("/sys/fs/selinux/null", O_RDWR);
if (fd == -1) {
int saved_errno = errno;
- android::base::InitLogging(argv, &KernelLogger);
+ android::base::InitLogging(argv, &android::base::KernelLogger);
errno = saved_errno;
PLOG(FATAL) << "Couldn't open /sys/fs/selinux/null";
}
@@ -71,8 +35,7 @@
dup2(fd, 2);
if (fd > 2) close(fd);
- android::base::InitLogging(argv, &KernelLogger);
- klog_set_level(KLOG_INFO_LEVEL);
+ android::base::InitLogging(argv, &android::base::KernelLogger);
}
int selinux_klog_callback(int type, const char *fmt, ...) {
@@ -87,6 +50,6 @@
va_start(ap, fmt);
vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
- KernelLogger(android::base::MAIN, severity, "selinux", nullptr, 0, buf);
+ android::base::KernelLogger(android::base::MAIN, severity, "selinux", nullptr, 0, buf);
return 0;
}
diff --git a/init/log.h b/init/log.h
index cf552a1..8fa6d74 100644
--- a/init/log.h
+++ b/init/log.h
@@ -19,8 +19,6 @@
#include <android-base/logging.h>
-#include <cutils/klog.h>
-
void InitKernelLogging(char* argv[]);
int selinux_klog_callback(int level, const char* fmt, ...) __printflike(2, 3);
diff --git a/init/readme.txt b/init/readme.txt
index 7260775..4c04f17 100644
--- a/init/readme.txt
+++ b/init/readme.txt
@@ -514,6 +514,3 @@
Alternatively, use the emulator:
emulator -partition-size 1024 -verbose -show-kernel -no-window
-
-You might want to change the klog_set_level call so you see all the kernel
-logging in dmesg (or the emulator output).
diff --git a/init/service.cpp b/init/service.cpp
index 44d9d8c..32aafd6 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -197,11 +197,15 @@
}
void Service::KillProcessGroup(int signal) {
- LOG(VERBOSE) << "Sending signal " << signal
- << " to service '" << name_
- << "' (pid " << pid_ << ") process group...\n",
- kill(pid_, signal);
- killProcessGroup(uid_, pid_, signal);
+ LOG(INFO) << "Sending signal " << signal
+ << " to service '" << name_
+ << "' (pid " << pid_ << ") process group...";
+ if (killProcessGroup(uid_, pid_, signal) == -1) {
+ PLOG(ERROR) << "killProcessGroup(" << uid_ << ", " << pid_ << ", " << signal << ") failed";
+ }
+ if (kill(-pid_, signal) == -1) {
+ PLOG(ERROR) << "kill(" << pid_ << ", " << signal << ") failed";
+ }
}
void Service::CreateSockets(const std::string& context) {
diff --git a/libcrypto_utils/Android.bp b/libcrypto_utils/Android.bp
new file mode 100644
index 0000000..ca7bd31
--- /dev/null
+++ b/libcrypto_utils/Android.bp
@@ -0,0 +1,37 @@
+//
+// 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.
+//
+
+cc_library {
+ name: "libcrypto_utils",
+ host_supported: true,
+ srcs: [
+ "android_pubkey.c",
+ ],
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ "-std=c99",
+ ],
+ local_include_dirs: ["include"],
+ export_include_dirs: ["include"],
+ shared_libs: ["libcrypto"],
+ target: {
+ windows: {
+ enabled: true,
+ },
+ },
+}
diff --git a/libcrypto_utils/Android.mk b/libcrypto_utils/Android.mk
deleted file mode 100644
index b6d2204..0000000
--- a/libcrypto_utils/Android.mk
+++ /dev/null
@@ -1,56 +0,0 @@
-#
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libcrypto_utils
-LOCAL_SRC_FILES := android_pubkey.c
-LOCAL_CFLAGS := -Wall -Werror -Wextra -std=c99
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_SHARED_LIBRARIES := libcrypto
-include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libcrypto_utils
-LOCAL_SRC_FILES := android_pubkey.c
-LOCAL_CFLAGS := -Wall -Werror -Wextra -std=c99
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_SHARED_LIBRARIES := libcrypto
-include $(BUILD_HOST_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libcrypto_utils_static
-LOCAL_SRC_FILES := android_pubkey.c
-LOCAL_CFLAGS := -Wall -Werror -Wextra -std=c99
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_STATIC_LIBRARIES := libcrypto
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libcrypto_utils_static
-LOCAL_MODULE_HOST_OS := darwin linux windows
-LOCAL_SRC_FILES := android_pubkey.c
-LOCAL_CFLAGS := -Wall -Werror -Wextra -std=c99
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_STATIC_LIBRARIES := libcrypto_static
-include $(BUILD_HOST_STATIC_LIBRARY)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/libcutils/sched_policy.c b/libcutils/sched_policy.c
index d7b4b0b..5c68add 100644
--- a/libcutils/sched_policy.c
+++ b/libcutils/sched_policy.c
@@ -45,9 +45,6 @@
#define POLICY_DEBUG 0
-// This prctl is only available in Android kernels.
-#define PR_SET_TIMERSLACK_PID 41
-
// timer slack value in nS enforced when the thread moves to background
#define TIMER_SLACK_BG 40000000
#define TIMER_SLACK_FG 50000
@@ -293,9 +290,9 @@
}
static void set_timerslack_ns(int tid, unsigned long long slack) {
+ // v4.6+ kernels support the /proc/<tid>/timerslack_ns interface.
+ // TODO: once we've backported this, log if the open(2) fails.
char buf[64];
-
- /* v4.6+ kernels support the /proc/<tid>/timerslack_ns interface. */
snprintf(buf, sizeof(buf), "/proc/%d/timerslack_ns", tid);
int fd = open(buf, O_WRONLY | O_CLOEXEC);
if (fd != -1) {
@@ -306,11 +303,6 @@
close(fd);
return;
}
-
- /* If the above fails, try the old common.git PR_SET_TIMERSLACK_PID. */
- if (prctl(PR_SET_TIMERSLACK_PID, slack, tid) == -1) {
- SLOGE("set_timerslack_ns prctl failed: %s\n", strerror(errno));
- }
}
int set_sched_policy(int tid, SchedPolicy policy)
diff --git a/libcutils/tests/Android.bp b/libcutils/tests/Android.bp
index 530c747..ada7d5f 100644
--- a/libcutils/tests/Android.bp
+++ b/libcutils/tests/Android.bp
@@ -21,6 +21,7 @@
srcs: [
"MemsetTest.cpp",
"PropertiesTest.cpp",
+ "sched_policy_test.cpp",
"trace-dev_test.cpp",
],
},
diff --git a/libcutils/tests/sched_policy_test.cpp b/libcutils/tests/sched_policy_test.cpp
new file mode 100644
index 0000000..173174a
--- /dev/null
+++ b/libcutils/tests/sched_policy_test.cpp
@@ -0,0 +1,98 @@
+/*
+ * 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 <algorithm>
+#include <chrono>
+#include <thread>
+#include <vector>
+
+#include <sys/capability.h>
+
+#include <cutils/sched_policy.h>
+
+#include <gtest/gtest.h>
+
+bool hasCapSysNice() {
+ __user_cap_header_struct header;
+ memset(&header, 0, sizeof(header));
+ header.version = _LINUX_CAPABILITY_VERSION_3;
+
+ __user_cap_data_struct caps[_LINUX_CAPABILITY_U32S_3];
+ if (capget(&header, &caps[0])) {
+ GTEST_LOG_(WARNING) << "failed to get process capabilities";
+ return false;
+ }
+
+ auto nice_idx = CAP_TO_INDEX(CAP_SYS_NICE);
+ auto nice_mask = CAP_TO_MASK(CAP_SYS_NICE);
+ return caps[nice_idx].effective & nice_mask;
+}
+
+long long medianSleepTime() {
+ std::vector<long long> sleepTimes;
+ constexpr size_t numSamples = 100;
+
+ for (size_t i = 0; i < numSamples; i++) {
+ auto start = std::chrono::steady_clock::now();
+ std::this_thread::sleep_for(std::chrono::nanoseconds(1));
+ auto end = std::chrono::steady_clock::now();
+
+ auto diff = end - start;
+ sleepTimes.push_back(diff.count());
+ }
+
+ constexpr auto median = numSamples / 2;
+ std::nth_element(sleepTimes.begin(), sleepTimes.begin() + median,
+ sleepTimes.end());
+ return sleepTimes[median];
+}
+
+TEST(SchedPolicy, set_sched_policy) {
+ if (!hasCapSysNice()) {
+ GTEST_LOG_(INFO) << "skipping test that requires CAP_SYS_NICE";
+ return;
+ }
+
+ // A measureable effect of scheduling policy is that the kernel has 800x
+ // greater slack time in waking up a sleeping background thread.
+ //
+ // Look for 100x difference in how long FB and BG threads actually sleep
+ // when trying to sleep for 1 ns. This difference is large enough not
+ // to happen by chance, but small enough (compared to 800x) to keep inherent
+ // fuzziness in scheduler behavior from causing false negatives.
+ const unsigned int BG_FG_SLACK_FACTOR = 100;
+
+ ASSERT_EQ(0, set_sched_policy(0, SP_BACKGROUND));
+ auto bgSleepTime = medianSleepTime();
+
+ ASSERT_EQ(0, set_sched_policy(0, SP_FOREGROUND));
+ auto fgSleepTime = medianSleepTime();
+ ASSERT_GT(bgSleepTime, fgSleepTime * BG_FG_SLACK_FACTOR);
+}
+
+TEST(SchedPolicy, get_sched_policy) {
+ SchedPolicy policy;
+ ASSERT_EQ(0, get_sched_policy(0, &policy));
+
+ const char *policyName = get_sched_policy_name(policy);
+ EXPECT_NE(nullptr, policyName);
+ EXPECT_STRNE("error", policyName);
+
+ ASSERT_EQ(0, set_sched_policy(0, SP_BACKGROUND));
+ SchedPolicy newPolicy;
+ ASSERT_EQ(0, get_sched_policy(0, &newPolicy));
+ EXPECT_EQ(SP_BACKGROUND, newPolicy);
+}
diff --git a/libprocessgroup/Android.mk b/libprocessgroup/Android.mk
index 87985d4..14c76c5 100644
--- a/libprocessgroup/Android.mk
+++ b/libprocessgroup/Android.mk
@@ -3,7 +3,7 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES := processgroup.cpp
LOCAL_MODULE := libprocessgroup
-LOCAL_STATIC_LIBRARIES := liblog
+LOCAL_STATIC_LIBRARIES := libbase
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
LOCAL_CFLAGS := -Wall -Werror
@@ -12,7 +12,7 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES := processgroup.cpp
LOCAL_MODULE := libprocessgroup
-LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_SHARED_LIBRARIES := libbase
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
LOCAL_CFLAGS := -Wall -Werror
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
index da4bb71..1961e76 100644
--- a/libprocessgroup/processgroup.cpp
+++ b/libprocessgroup/processgroup.cpp
@@ -31,7 +31,7 @@
#include <chrono>
#include <memory>
-#include <log/log.h>
+#include <android-base/logging.h>
#include <private/android_filesystem_config.h>
#include <processgroup/processgroup.h>
@@ -73,7 +73,7 @@
int fd = open(path, O_RDONLY);
if (fd < 0) {
ret = -errno;
- SLOGW("failed to open %s: %s", path, strerror(errno));
+ PLOG(WARNING) << "failed to open " << path;
return ret;
}
@@ -82,7 +82,7 @@
ctx->buf_len = 0;
ctx->initialized = true;
- SLOGV("Initialized context for %s", path);
+ LOG(VERBOSE) << "Initialized context for " << path;
return 0;
}
@@ -102,7 +102,7 @@
ctx->buf_len += ret;
ctx->buf[ctx->buf_len] = 0;
- SLOGV("Read %zd to buffer: %s", ret, ctx->buf);
+ LOG(VERBOSE) << "Read " << ret << " to buffer: " << ctx->buf;
assert(ctx->buf_len <= sizeof(ctx->buf));
@@ -178,18 +178,18 @@
}
snprintf(path, sizeof(path), "%s/%s", uid_path, dir->d_name);
- SLOGV("removing %s\n", path);
- rmdir(path);
+ LOG(VERBOSE) << "removing " << path;
+ if (rmdir(path) == -1) PLOG(WARNING) << "failed to remove " << path;
}
}
}
void removeAllProcessGroups()
{
- SLOGV("removeAllProcessGroups()");
+ LOG(VERBOSE) << "removeAllProcessGroups()";
std::unique_ptr<DIR, decltype(&closedir)> root(opendir(PROCESSGROUP_CGROUP_PATH), closedir);
if (root == NULL) {
- SLOGE("failed to open %s: %s", PROCESSGROUP_CGROUP_PATH, strerror(errno));
+ PLOG(ERROR) << "failed to open " << PROCESSGROUP_CGROUP_PATH;
} else {
struct dirent cur;
struct dirent *dir;
@@ -205,8 +205,8 @@
snprintf(path, sizeof(path), "%s/%s", PROCESSGROUP_CGROUP_PATH, dir->d_name);
removeUidProcessGroups(path);
- SLOGV("removing %s\n", path);
- rmdir(path);
+ LOG(VERBOSE) << "removing " << path;
+ if (rmdir(path) == -1) PLOG(WARNING) << "failed to remove " << path;
}
}
}
@@ -224,19 +224,13 @@
if (pid == 0) {
// Should never happen... but if it does, trying to kill this
// will boomerang right back and kill us! Let's not let that happen.
- SLOGW("Yikes, we've been told to kill pid 0! How about we don't do that.");
+ LOG(WARNING) << "Yikes, we've been told to kill pid 0! How about we don't do that?";
continue;
}
- if (pid != initialPid) {
- // We want to be noisy about killing processes so we can understand
- // what is going on in the log; however, don't be noisy about the base
- // process, since that it something we always kill, and we have already
- // logged elsewhere about killing it.
- SLOGI("Killing pid %d in uid %d as part of process group %d", pid, uid, initialPid);
- }
- int ret = kill(pid, signal);
- if (ret == -1) {
- SLOGW("failed to kill pid %d: %s", pid, strerror(errno));
+ LOG(VERBOSE) << "Killing pid " << pid << " in uid " << uid
+ << " as part of process group " << initialPid;
+ if (kill(pid, signal) == -1) {
+ PLOG(WARNING) << "kill(" << pid << ", " << signal << ") failed";
}
}
@@ -254,21 +248,22 @@
int retry = 40;
int processes;
while ((processes = killProcessGroupOnce(uid, initialPid, signal)) > 0) {
- SLOGV("killed %d processes for processgroup %d\n", processes, initialPid);
+ LOG(VERBOSE) << "killed " << processes << " processes for processgroup " << initialPid;
if (retry > 0) {
usleep(5 * 1000); // 5ms
--retry;
} else {
- SLOGE("failed to kill %d processes for processgroup %d\n", processes, initialPid);
+ LOG(ERROR) << "failed to kill " << processes << " processes for processgroup "
+ << initialPid;
break;
}
}
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
- SLOGV("Killed process group uid %d pid %d in %dms, %d procs remain", uid, initialPid,
- static_cast<int>(std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count()),
- processes);
+ auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
+ LOG(VERBOSE) << "Killed process group uid " << uid << " pid " << initialPid << " in "
+ << static_cast<int>(ms) << "ms, " << processes << " procs remain";
if (processes == 0) {
return removeProcessGroup(uid, initialPid);
@@ -277,67 +272,58 @@
}
}
-static int mkdirAndChown(const char *path, mode_t mode, uid_t uid, gid_t gid)
+static bool mkdirAndChown(const char *path, mode_t mode, uid_t uid, gid_t gid)
{
- int ret;
-
- ret = mkdir(path, mode);
- if (ret < 0 && errno != EEXIST) {
- return -errno;
+ if (mkdir(path, mode) == -1 && errno != EEXIST) {
+ return false;
}
- ret = chown(path, uid, gid);
- if (ret < 0) {
- ret = -errno;
+ if (chown(path, uid, gid) == -1) {
+ int saved_errno = errno;
rmdir(path);
- return ret;
+ errno = saved_errno;
+ return false;
}
- return 0;
+ return true;
}
int createProcessGroup(uid_t uid, int initialPid)
{
char path[PROCESSGROUP_MAX_PATH_LEN] = {0};
- int ret;
convertUidToPath(path, sizeof(path), uid);
- ret = mkdirAndChown(path, 0750, AID_SYSTEM, AID_SYSTEM);
- if (ret < 0) {
- SLOGE("failed to make and chown %s: %s", path, strerror(-ret));
- return ret;
+ if (!mkdirAndChown(path, 0750, AID_SYSTEM, AID_SYSTEM)) {
+ PLOG(ERROR) << "failed to make and chown " << path;
+ return -errno;
}
convertUidPidToPath(path, sizeof(path), uid, initialPid);
- ret = mkdirAndChown(path, 0750, AID_SYSTEM, AID_SYSTEM);
- if (ret < 0) {
- SLOGE("failed to make and chown %s: %s", path, strerror(-ret));
- return ret;
+ if (!mkdirAndChown(path, 0750, AID_SYSTEM, AID_SYSTEM)) {
+ PLOG(ERROR) << "failed to make and chown " << path;
+ return -errno;
}
strlcat(path, PROCESSGROUP_CGROUP_PROCS_FILE, sizeof(path));
int fd = open(path, O_WRONLY);
- if (fd < 0) {
- ret = -errno;
- SLOGE("failed to open %s: %s", path, strerror(errno));
+ if (fd == -1) {
+ int ret = -errno;
+ PLOG(ERROR) << "failed to open " << path;
return ret;
}
char pid[PROCESSGROUP_MAX_PID_LEN + 1] = {0};
int len = snprintf(pid, sizeof(pid), "%d", initialPid);
- ret = write(fd, pid, len);
- if (ret < 0) {
+ int ret = 0;
+ if (write(fd, pid, len) < 0) {
ret = -errno;
- SLOGE("failed to write '%s' to %s: %s", pid, path, strerror(errno));
- } else {
- ret = 0;
+ PLOG(ERROR) << "failed to write '" << pid << "' to " << path;
}
close(fd);
return ret;
}
-
diff --git a/libsync/Android.mk b/libsync/Android.mk
index fd1c88c..f407bd1 100644
--- a/libsync/Android.mk
+++ b/libsync/Android.mk
@@ -4,17 +4,27 @@
LOCAL_SRC_FILES := sync.c
LOCAL_MODULE := libsync
LOCAL_MODULE_TAGS := optional
-LOCAL_SHARED_LIBRARIES := liblog
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
LOCAL_CFLAGS := -Werror
include $(BUILD_SHARED_LIBRARY)
+# libsync_recovery is only intended for the recovery binary.
+# Future versions of the kernel WILL require an updated libsync, and will break
+# anything statically linked against the current libsync.
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := sync.c
+LOCAL_MODULE := libsync_recovery
+LOCAL_MODULE_TAGS := optional
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_CFLAGS := -Werror
+include $(BUILD_STATIC_LIBRARY)
+
include $(CLEAR_VARS)
LOCAL_SRC_FILES := sync.c sync_test.c
LOCAL_MODULE := sync_test
LOCAL_MODULE_TAGS := optional tests
-LOCAL_SHARED_LIBRARIES := liblog
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_CFLAGS := -Werror
include $(BUILD_EXECUTABLE)
diff --git a/libutils/RefBase.cpp b/libutils/RefBase.cpp
index 085b314..df49a2f 100644
--- a/libutils/RefBase.cpp
+++ b/libutils/RefBase.cpp
@@ -56,26 +56,32 @@
namespace android {
-// Usage, invariants, etc:
+// Observations, invariants, etc:
-// It is normally OK just to keep weak pointers to an object. The object will
-// be deallocated by decWeak when the last weak reference disappears.
-// Once a a strong reference has been created, the object will disappear once
-// the last strong reference does (decStrong).
-// AttemptIncStrong will succeed if the object has a strong reference, or if it
-// has a weak reference and has never had a strong reference.
-// AttemptIncWeak really does succeed only if there is already a WEAK
-// reference, and thus may fail when attemptIncStrong would succeed.
+// By default, obects are destroyed when the last strong reference disappears
+// or, if the object never had a strong reference, when the last weak reference
+// disappears.
+//
// OBJECT_LIFETIME_WEAK changes this behavior to retain the object
// unconditionally until the last reference of either kind disappears. The
// client ensures that the extendObjectLifetime call happens before the dec
// call that would otherwise have deallocated the object, or before an
// attemptIncStrong call that might rely on it. We do not worry about
// concurrent changes to the object lifetime.
+//
+// AttemptIncStrong will succeed if the object has a strong reference, or if it
+// has a weak reference and has never had a strong reference.
+// AttemptIncWeak really does succeed only if there is already a WEAK
+// reference, and thus may fail when attemptIncStrong would succeed.
+//
// mStrong is the strong reference count. mWeak is the weak reference count.
// Between calls, and ignoring memory ordering effects, mWeak includes strong
// references, and is thus >= mStrong.
//
+// A weakref_impl holds all the information, including both reference counts,
+// required to perform wp<> operations. Thus these can continue to be performed
+// after the RefBase object has been destroyed.
+//
// A weakref_impl is allocated as the value of mRefs in a RefBase object on
// construction.
// In the OBJECT_LIFETIME_STRONG case, it is deallocated in the RefBase
@@ -580,15 +586,14 @@
// grab a strong-reference, which is always safe due to the
// extended life-time.
curCount = impl->mStrong.fetch_add(1, std::memory_order_relaxed);
- }
-
- // If the strong reference count has already been incremented by
- // someone else, the implementor of onIncStrongAttempted() is holding
- // an unneeded reference. So call onLastStrongRef() here to remove it.
- // (No, this is not pretty.) Note that we MUST NOT do this if we
- // are in fact acquiring the first reference.
- if (curCount > 0 && curCount < INITIAL_STRONG_VALUE) {
- impl->mBase->onLastStrongRef(id);
+ // If the strong reference count has already been incremented by
+ // someone else, the implementor of onIncStrongAttempted() is holding
+ // an unneeded reference. So call onLastStrongRef() here to remove it.
+ // (No, this is not pretty.) Note that we MUST NOT do this if we
+ // are in fact acquiring the first reference.
+ if (curCount != 0 && curCount != INITIAL_STRONG_VALUE) {
+ impl->mBase->onLastStrongRef(id);
+ }
}
}
@@ -598,7 +603,7 @@
ALOGD("attemptIncStrong of %p from %p: cnt=%d\n", this, id, curCount);
#endif
- // curCount is the value of mStrong before we increment ed it.
+ // curCount is the value of mStrong before we incremented it.
// Now we need to fix-up the count if it was INITIAL_STRONG_VALUE.
// This must be done safely, i.e.: handle the case where several threads
// were here in attemptIncStrong().
@@ -672,7 +677,8 @@
{
if (mRefs->mStrong.load(std::memory_order_relaxed)
== INITIAL_STRONG_VALUE) {
- // we never acquired a strong (and/or weak) reference on this object.
+ // We never acquired a strong reference on this object.
+ // We assume there are no outstanding weak references.
delete mRefs;
} else {
// life-time of this object is extended to WEAK, in
diff --git a/libutils/SharedBuffer.cpp b/libutils/SharedBuffer.cpp
index f3d6d8f..dc96aef 100644
--- a/libutils/SharedBuffer.cpp
+++ b/libutils/SharedBuffer.cpp
@@ -114,8 +114,9 @@
int32_t SharedBuffer::release(uint32_t flags) const
{
int32_t prev = 1;
- if (onlyOwner() || ((prev = mRefs.fetch_sub(1, std::memory_order_release) == 1)
- && (atomic_thread_fence(std::memory_order_acquire), true))) {
+ if (onlyOwner()
+ || (((prev = mRefs.fetch_sub(1, std::memory_order_release)) == 1)
+ && (atomic_thread_fence(std::memory_order_acquire), true))) {
mRefs.store(0, std::memory_order_relaxed);
if ((flags & eKeepStorage) == 0) {
free(const_cast<SharedBuffer*>(this));
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 5bac717..7e2bac7 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -26,6 +26,7 @@
#include <string>
#include <android-base/file.h>
+#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <cutils/sched_policy.h>
#include <cutils/sockets.h>
@@ -109,29 +110,27 @@
(g_maxRotatedLogs > 0) ? (int) (floor(log10(g_maxRotatedLogs) + 1)) : 0;
for (int i = g_maxRotatedLogs ; i > 0 ; i--) {
- char *file0, *file1;
+ std::string file1 = android::base::StringPrintf(
+ "%s.%.*d", g_outputFileName, maxRotationCountDigits, i);
- asprintf(&file1, "%s.%.*d", g_outputFileName, maxRotationCountDigits, i);
-
+ std::string file0;
if (i - 1 == 0) {
- asprintf(&file0, "%s", g_outputFileName);
+ file0 = android::base::StringPrintf("%s", g_outputFileName);
} else {
- asprintf(&file0, "%s.%.*d", g_outputFileName, maxRotationCountDigits, i - 1);
+ file0 = android::base::StringPrintf(
+ "%s.%.*d", g_outputFileName, maxRotationCountDigits, i - 1);
}
- if (!file0 || !file1) {
+ if ((file0.length() == 0) || (file1.length() == 0)) {
perror("while rotating log files");
break;
}
- err = rename(file0, file1);
+ err = rename(file0.c_str(), file1.c_str());
if (err < 0 && errno != ENOENT) {
perror("while rotating log files");
}
-
- free(file1);
- free(file0);
}
g_outFD = openLogFile(g_outputFileName);
@@ -231,13 +230,15 @@
}
}
-static void setupOutput()
-{
-
+static void setupOutputAndSchedulingPolicy(bool blocking) {
if (g_outputFileName == NULL) {
g_outFD = STDOUT_FILENO;
+ return;
+ }
- } else {
+ if (blocking) {
+ // Lower priority and set to batch scheduling if we are saving
+ // the logs into files and taking continuous content.
if (set_sched_policy(0, SP_BACKGROUND) < 0) {
fprintf(stderr, "failed to set background scheduling policy\n");
}
@@ -251,26 +252,26 @@
if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) {
fprintf(stderr, "failed set to priority\n");
}
-
- g_outFD = openLogFile (g_outputFileName);
-
- if (g_outFD < 0) {
- logcat_panic(false, "couldn't open output file");
- }
-
- struct stat statbuf;
- if (fstat(g_outFD, &statbuf) == -1) {
- close(g_outFD);
- logcat_panic(false, "couldn't get output file stat\n");
- }
-
- if ((size_t) statbuf.st_size > SIZE_MAX || statbuf.st_size < 0) {
- close(g_outFD);
- logcat_panic(false, "invalid output file stat\n");
- }
-
- g_outByteCount = statbuf.st_size;
}
+
+ g_outFD = openLogFile (g_outputFileName);
+
+ if (g_outFD < 0) {
+ logcat_panic(false, "couldn't open output file");
+ }
+
+ struct stat statbuf;
+ if (fstat(g_outFD, &statbuf) == -1) {
+ close(g_outFD);
+ logcat_panic(false, "couldn't get output file stat\n");
+ }
+
+ if ((size_t) statbuf.st_size > SIZE_MAX || statbuf.st_size < 0) {
+ close(g_outFD);
+ logcat_panic(false, "invalid output file stat\n");
+ }
+
+ g_outByteCount = statbuf.st_size;
}
static void show_help(const char *cmd)
@@ -284,6 +285,8 @@
" Rotate log every kbytes. Requires -f option\n"
" -n <count>, --rotate-count=<count>\n"
" Sets max number of rotated logs to <count>, default 4\n"
+ " --id=<id> If the signature id for logging to file changes, then clear\n"
+ " the fileset and continue\n"
" -v <format>, --format=<format>\n"
" Sets log print format verb and adverbs, where <format> is:\n"
" brief long process raw tag thread threadtime time\n"
@@ -443,7 +446,7 @@
return t.strptime(cp, "%s.%q");
}
-// Find last logged line in gestalt of all matching existing output files
+// Find last logged line in <outputFileName>, or <outputFileName>.1
static log_time lastLogTime(char *outputFileName) {
log_time retval(log_time::EPOCH);
if (!outputFileName) {
@@ -468,24 +471,18 @@
return retval;
}
- clockid_t clock_type = android_log_clockid();
- log_time now(clock_type);
- bool monotonic = clock_type == CLOCK_MONOTONIC;
+ log_time now(android_log_clockid());
size_t len = strlen(file);
log_time modulo(0, NS_PER_SEC);
struct dirent *dp;
while ((dp = readdir(dir.get())) != NULL) {
- if ((dp->d_type != DT_REG)
- // If we are using realtime, check all files that match the
- // basename for latest time. If we are using monotonic time
- // then only check the main file because time cycles on
- // every reboot.
- || strncmp(dp->d_name, file, len + monotonic)
- || (dp->d_name[len]
- && ((dp->d_name[len] != '.')
- || !isdigit(dp->d_name[len+1])))) {
+ if ((dp->d_type != DT_REG) ||
+ (strncmp(dp->d_name, file, len) != 0) ||
+ (dp->d_name[len] &&
+ ((dp->d_name[len] != '.') ||
+ (strtoll(dp->d_name + 1, NULL, 10) != 1)))) {
continue;
}
@@ -547,6 +544,7 @@
unsigned long setLogSize = 0;
int getPruneList = 0;
char *setPruneList = NULL;
+ char *setId = NULL;
int printStatistics = 0;
int mode = ANDROID_LOG_RDONLY;
const char *forceFilters = NULL;
@@ -574,6 +572,7 @@
int option_index = 0;
// list of long-argument only strings for later comparison
static const char pid_str[] = "pid";
+ static const char id_str[] = "id";
static const char wrap_str[] = "wrap";
static const char print_str[] = "print";
static const struct option long_options[] = {
@@ -588,6 +587,7 @@
{ "grep", required_argument, NULL, 'e' },
// hidden and undocumented reserved alias for --max-count
{ "head", required_argument, NULL, 'm' },
+ { id_str, required_argument, NULL, 0 },
{ "last", no_argument, NULL, 'L' },
{ "max-count", required_argument, NULL, 'm' },
{ pid_str, required_argument, NULL, 0 },
@@ -613,7 +613,7 @@
switch (ret) {
case 0:
- // One of the long options
+ // only long options
if (long_options[option_index].name == pid_str) {
// ToDo: determine runtime PID_MAX?
if (!getSizeTArg(optarg, &pid, 1)) {
@@ -644,6 +644,10 @@
g_printItAnyways = true;
break;
}
+ if (long_options[option_index].name == id_str) {
+ setId = optarg && optarg[0] ? optarg : NULL;
+ break;
+ }
break;
case 's':
@@ -657,7 +661,7 @@
break;
case 'L':
- mode |= ANDROID_LOG_PSTORE;
+ mode |= ANDROID_LOG_RDONLY | ANDROID_LOG_PSTORE | ANDROID_LOG_NONBLOCK;
break;
case 'd':
@@ -968,7 +972,20 @@
logcat_panic(true, "-r requires -f as well\n");
}
- setupOutput();
+ if (setId != NULL) {
+ if (g_outputFileName == NULL) {
+ logcat_panic(true, "--id='%s' requires -f as well\n", setId);
+ }
+
+ std::string file_name = android::base::StringPrintf("%s.id", g_outputFileName);
+ std::string file;
+ bool file_ok = android::base::ReadFileToString(file_name, &file);
+ android::base::WriteStringToFile(setId, file_name,
+ S_IRUSR | S_IWUSR, getuid(), getgid());
+ if (!file_ok || (file.compare(setId) == 0)) {
+ setId = NULL;
+ }
+ }
if (hasSetLogFormat == 0) {
const char* logFormat = getenv("ANDROID_PRINTF_LOG");
@@ -1034,34 +1051,33 @@
continue;
}
- if (clearLog) {
+ if (clearLog || setId) {
if (g_outputFileName) {
int maxRotationCountDigits =
(g_maxRotatedLogs > 0) ? (int) (floor(log10(g_maxRotatedLogs) + 1)) : 0;
for (int i = g_maxRotatedLogs ; i >= 0 ; --i) {
- char *file;
+ std::string file;
if (i == 0) {
- asprintf(&file, "%s", g_outputFileName);
+ file = android::base::StringPrintf("%s", g_outputFileName);
} else {
- asprintf(&file, "%s.%.*d", g_outputFileName, maxRotationCountDigits, i);
+ file = android::base::StringPrintf("%s.%.*d",
+ g_outputFileName, maxRotationCountDigits, i);
}
- if (!file) {
+ if (file.length() == 0) {
perror("while clearing log files");
clearFail = clearFail ?: dev->device;
break;
}
- err = unlink(file);
+ err = unlink(file.c_str());
if (err < 0 && errno != ENOENT && clearFail == NULL) {
perror("while clearing log files");
clearFail = dev->device;
}
-
- free(file);
}
} else if (android_logger_clear(dev->logger)) {
clearFail = clearFail ?: dev->device;
@@ -1177,7 +1193,6 @@
return EXIT_SUCCESS;
}
-
if (getLogSize) {
return EXIT_SUCCESS;
}
@@ -1188,6 +1203,8 @@
return EXIT_SUCCESS;
}
+ setupOutputAndSchedulingPolicy((mode & ANDROID_LOG_NONBLOCK) == 0);
+
//LOG_EVENT_INT(10, 12345);
//LOG_EVENT_LONG(11, 0x1122334455667788LL);
//LOG_EVENT_STRING(0, "whassup, doc?");
diff --git a/logcat/logcatd.rc b/logcat/logcatd.rc
index ce1a451..1da1942 100644
--- a/logcat/logcatd.rc
+++ b/logcat/logcatd.rc
@@ -35,7 +35,7 @@
# all exec/services are called with umask(077), so no gain beyond 0700
mkdir /data/misc/logd 0700 logd log
# logd for write to /data/misc/logd, log group for read from pstore (-L)
- exec - logd log -- /system/bin/logcat -L -b ${logd.logpersistd.buffer:-all} -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 1024 -n ${logd.logpersistd.size:-256}
+ exec - logd log -- /system/bin/logcat -L -b ${logd.logpersistd.buffer:-all} -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 1024 -n ${logd.logpersistd.size:-256} --id=${ro.build.id}
start logcatd
# stop logcatd service and clear data
@@ -56,7 +56,7 @@
stop logcatd
# logcatd service
-service logcatd /system/bin/logcat -b ${logd.logpersistd.buffer:-all} -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 1024 -n ${logd.logpersistd.size:-256}
+service logcatd /system/bin/logcat -b ${logd.logpersistd.buffer:-all} -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 1024 -n ${logd.logpersistd.size:-256} --id=${ro.build.id}
class late_start
disabled
# logd for write to /data/misc/logd, log group for read from log daemon
diff --git a/logcat/logpersist b/logcat/logpersist
index f0e7d42..c09b6b2 100755
--- a/logcat/logpersist
+++ b/logcat/logpersist
@@ -17,8 +17,9 @@
;;
esac
+log_uid=logd
log_tag_property=persist.log.tag
-data=/data/misc/logd
+data=/data/misc/logd/logcat
service=logcatd
size_default=256
buffer_default=all
@@ -74,11 +75,12 @@
if [ -n "${size}${buffer}" -o "true" = "${clear}" ]; then
echo WARNING: Can not use --clear, --size or --buffer with ${progname%.*}.cat >&2
fi
- su logd ls "${data}" |
+ su ${log_uid} ls "${data%/*}" |
tr -d '\r' |
sort -ru |
- sed "s#^#${data}/#" |
- su logd xargs cat
+ sed "s#^#${data%/*}/#" |
+ grep "${data}[.]*[0-9]*\$" |
+ su ${log_uid} xargs cat
;;
*.start)
current_buffer="`getprop ${property#persist.}.buffer`"
@@ -139,7 +141,7 @@
sleep 1
getprop ${property#persist.}
# also generate an error return code if not found running
- pgrep -u ${data##*/} ${service%d}
+ pgrep -u ${log_uid} ${service%d}
;;
*.stop)
if [ -n "${size}${buffer}" ]; then
@@ -171,6 +173,6 @@
if [ X"${log_tag}" != X"`getprop ${log_tag_property}`" ] ||
[ X"${logd_logpersistd}" != X"`getprop ${property}`" ]; then
- echo "WARNING: killing Settings" >&2
+ echo "WARNING: killing Settings application to pull in new values" >&2
am force-stop com.android.settings
fi
diff --git a/logcat/tests/logcat_test.cpp b/logcat/tests/logcat_test.cpp
index 0043d1b..3daee13 100644
--- a/logcat/tests/logcat_test.cpp
+++ b/logcat/tests/logcat_test.cpp
@@ -20,6 +20,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
@@ -848,6 +849,75 @@
EXPECT_FALSE(system(command));
}
+static int logrotate_count_id(const char *logcat_cmd, const char *tmp_out_dir) {
+
+ static const char log_filename[] = "log.txt";
+ char command[strlen(tmp_out_dir) + strlen(logcat_cmd) + strlen(log_filename) + 32];
+
+ snprintf(command, sizeof(command), logcat_cmd, tmp_out_dir, log_filename);
+
+ int ret;
+ EXPECT_FALSE((ret = system(command)));
+ if (ret) {
+ return -1;
+ }
+ std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(tmp_out_dir), closedir);
+ EXPECT_NE(nullptr, dir);
+ if (!dir) {
+ return -1;
+ }
+ struct dirent *entry;
+ int count = 0;
+ while ((entry = readdir(dir.get()))) {
+ if (strncmp(entry->d_name, log_filename, sizeof(log_filename) - 1)) {
+ continue;
+ }
+ ++count;
+ }
+ return count;
+}
+
+TEST(logcat, logrotate_id) {
+ static const char logcat_cmd[] = "logcat -b all -d -f %s/%s -n 32 -r 1 --id=test";
+ static const char logcat_short_cmd[] = "logcat -b all -t 10 -f %s/%s -n 32 -r 1 --id=test";
+ static const char tmp_out_dir_form[] = "/data/local/tmp/logcat.logrotate.XXXXXX";
+ static const char log_filename[] = "log.txt";
+ char tmp_out_dir[strlen(tmp_out_dir_form) + 1];
+ ASSERT_TRUE(NULL != mkdtemp(strcpy(tmp_out_dir, tmp_out_dir_form)));
+
+ EXPECT_EQ(34, logrotate_count_id(logcat_cmd, tmp_out_dir));
+ EXPECT_EQ(34, logrotate_count_id(logcat_short_cmd, tmp_out_dir));
+
+ char id_file[strlen(tmp_out_dir_form) + strlen(log_filename) + 5];
+ snprintf(id_file, sizeof(id_file), "%s/%s.id", tmp_out_dir, log_filename);
+ if (getuid() != 0) {
+ chmod(id_file, 0);
+ EXPECT_EQ(34, logrotate_count_id(logcat_short_cmd, tmp_out_dir));
+ }
+ unlink(id_file);
+ EXPECT_EQ(34, logrotate_count_id(logcat_short_cmd, tmp_out_dir));
+
+ FILE *fp = fopen(id_file, "w");
+ if (fp) {
+ fprintf(fp, "not_a_test");
+ fclose(fp);
+ }
+ if (getuid() != 0) {
+ chmod(id_file, 0); // API to preserve content even with signature change
+ ASSERT_EQ(34, logrotate_count_id(logcat_short_cmd, tmp_out_dir));
+ chmod(id_file, 0600);
+ }
+
+ int new_signature;
+ EXPECT_LE(2, (new_signature = logrotate_count_id(logcat_short_cmd, tmp_out_dir)));
+ EXPECT_GT(34, new_signature);
+
+ static const char cleanup_cmd[] = "rm -rf %s";
+ char command[strlen(cleanup_cmd) + strlen(tmp_out_dir_form)];
+ snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
+ EXPECT_FALSE(system(command));
+}
+
TEST(logcat, logrotate_nodir) {
// expect logcat to error out on writing content and exit(1) for nodir
EXPECT_EQ(W_EXITCODE(1, 0),
diff --git a/logd/CommandListener.h b/logd/CommandListener.h
index 3877675..cbcd601 100644
--- a/logd/CommandListener.h
+++ b/logd/CommandListener.h
@@ -49,7 +49,7 @@
class name##Cmd : public LogCommand { \
LogBuffer &mBuf; \
public: \
- name##Cmd(LogBuffer *buf); \
+ explicit name##Cmd(LogBuffer *buf); \
virtual ~name##Cmd() {} \
int runCommand(SocketClient *c, int argc, char ** argv); \
};
diff --git a/logd/LogKlog.cpp b/logd/LogKlog.cpp
index ac2b128..ef6c1ae 100644
--- a/logd/LogKlog.cpp
+++ b/logd/LogKlog.cpp
@@ -26,6 +26,7 @@
#include <syslog.h>
#include <log/logger.h>
+#include <private/android_filesystem_config.h>
#include "LogBuffer.h"
#include "LogKlog.h"
@@ -589,7 +590,12 @@
// Parse pid, tid and uid
const pid_t pid = sniffPid(p, len - (p - buf));
const pid_t tid = pid;
- const uid_t uid = pid ? logbuf->pidToUid(pid) : 0;
+ uid_t uid = AID_ROOT;
+ if (pid) {
+ logbuf->lock();
+ uid = logbuf->pidToUid(pid);
+ logbuf->unlock();
+ }
// Parse (rules at top) to pull out a tag from the incoming kernel message.
// Some may view the following as an ugly heuristic, the desire is to
@@ -605,126 +611,124 @@
const char *tag = "";
const char *etag = tag;
size_t taglen = len - (p - buf);
- if (!isspace(*p) && *p) {
- const char *bt, *et, *cp;
+ const char *bt = p;
- bt = p;
- if ((taglen >= 6) && !fast<strncmp>(p, "[INFO]", 6)) {
- // <PRI>[<TIME>] "[INFO]"<tag> ":" message
- bt = p + 6;
- taglen -= 6;
- }
- for(et = bt; taglen && *et && (*et != ':') && !isspace(*et); ++et, --taglen) {
- // skip ':' within [ ... ]
- if (*et == '[') {
- while (taglen && *et && *et != ']') {
- ++et;
- --taglen;
- }
- }
- }
- for(cp = et; taglen && isspace(*cp); ++cp, --taglen);
- size_t size;
+ static const char infoBrace[] = "[INFO]";
+ static const size_t infoBraceLen = strlen(infoBrace);
+ if ((taglen >= infoBraceLen) && !fast<strncmp>(p, infoBrace, infoBraceLen)) {
+ // <PRI>[<TIME>] "[INFO]"<tag> ":" message
+ bt = p + infoBraceLen;
+ taglen -= infoBraceLen;
+ }
+ const char *et;
+ for (et = bt; taglen && *et && (*et != ':') && !isspace(*et); ++et, --taglen) {
+ // skip ':' within [ ... ]
+ if (*et == '[') {
+ while (taglen && *et && *et != ']') {
+ ++et;
+ --taglen;
+ }
+ if (!taglen) {
+ break;
+ }
+ }
+ }
+ const char *cp;
+ for (cp = et; taglen && isspace(*cp); ++cp, --taglen);
+
+ // Validate tag
+ size_t size = et - bt;
+ if (taglen && size) {
if (*cp == ':') {
+ // ToDo: handle case insensitive colon separated logging stutter:
+ // <tag> : <tag>: ...
+
// One Word
tag = bt;
etag = et;
p = cp + 1;
- } else if (taglen) {
- size = et - bt;
- if ((taglen > size) && // enough space for match plus trailing :
- (*bt == *cp) && // ubber fast<strncmp> pair
- fast<strncmp>(bt + 1, cp + 1, size - 1)) {
- // <PRI>[<TIME>] <tag>_host '<tag>.<num>' : message
- if (!fast<strncmp>(bt + size - 5, "_host", 5)
- && !fast<strncmp>(bt + 1, cp + 1, size - 6)) {
+ } else if ((taglen > size) && (tolower(*bt) == tolower(*cp))) {
+ // clean up any tag stutter
+ if (!fast<strncasecmp>(bt + 1, cp + 1, size - 1)) { // no match
+ // <PRI>[<TIME>] <tag> <tag> : message
+ // <PRI>[<TIME>] <tag> <tag>: message
+ // <PRI>[<TIME>] <tag> '<tag>.<num>' : message
+ // <PRI>[<TIME>] <tag> '<tag><num>' : message
+ // <PRI>[<TIME>] <tag> '<tag><stuff>' : message
+ const char *b = cp;
+ cp += size;
+ taglen -= size;
+ while (--taglen && !isspace(*++cp) && (*cp != ':'));
+ const char *e;
+ for (e = cp; taglen && isspace(*cp); ++cp, --taglen);
+ if (taglen && (*cp == ':')) {
+ tag = b;
+ etag = e;
+ p = cp + 1;
+ }
+ } else {
+ // what about <PRI>[<TIME>] <tag>_host '<tag><stuff>' : message
+ static const char host[] = "_host";
+ static const size_t hostlen = strlen(host);
+ if ((size > hostlen) &&
+ !fast<strncmp>(bt + size - hostlen, host, hostlen) &&
+ !fast<strncmp>(bt + 1, cp + 1, size - hostlen - 1)) {
const char *b = cp;
- cp += size - 5;
- taglen -= size - 5;
+ cp += size - hostlen;
+ taglen -= size - hostlen;
if (*cp == '.') {
while (--taglen && !isspace(*++cp) && (*cp != ':'));
const char *e;
- for(e = cp; taglen && isspace(*cp); ++cp, --taglen);
- if (*cp == ':') {
+ for (e = cp; taglen && isspace(*cp); ++cp, --taglen);
+ if (taglen && (*cp == ':')) {
tag = b;
etag = e;
p = cp + 1;
}
}
} else {
- while (--taglen && !isspace(*++cp) && (*cp != ':'));
- const char *e;
- for(e = cp; taglen && isspace(*cp); ++cp, --taglen);
- // Two words
- if (*cp == ':') {
- tag = bt;
- etag = e;
- p = cp + 1;
- }
- }
- } else if (isspace(cp[size])) {
- cp += size;
- taglen -= size;
- while (--taglen && isspace(*++cp));
- // <PRI>[<TIME>] <tag> <tag> : message
- if (*cp == ':') {
- tag = bt;
- etag = et;
- p = cp + 1;
- }
- } else if (cp[size] == ':') {
- // <PRI>[<TIME>] <tag> <tag> : message
- tag = bt;
- etag = et;
- p = cp + size + 1;
- } else if ((cp[size] == '.') || isdigit(cp[size])) {
- // <PRI>[<TIME>] <tag> '<tag>.<num>' : message
- // <PRI>[<TIME>] <tag> '<tag><num>' : message
- const char *b = cp;
- cp += size;
- taglen -= size;
- while (--taglen && !isspace(*++cp) && (*cp != ':'));
- const char *e = cp;
- while (taglen && isspace(*cp)) {
- ++cp;
- --taglen;
- }
- if (*cp == ':') {
- tag = b;
- etag = e;
- p = cp + 1;
- }
- } else {
- while (--taglen && !isspace(*++cp) && (*cp != ':'));
- const char *e = cp;
- while (taglen && isspace(*cp)) {
- ++cp;
- --taglen;
- }
- // Two words
- if (*cp == ':') {
- tag = bt;
- etag = e;
- p = cp + 1;
+ goto twoWord;
}
}
- } /* else no tag */
- size = etag - tag;
- if ((size <= 1)
- // register names like x9
- || ((size == 2) && (isdigit(tag[0]) || isdigit(tag[1])))
- // register names like x18 but not driver names like en0
- || ((size == 3) && (isdigit(tag[1]) && isdigit(tag[2])))
- // blacklist
- || ((size == 3) && !fast<strncmp>(tag, "CPU", 3))
- || ((size == 7) && !fast<strncasecmp>(tag, "WARNING", 7))
- || ((size == 5) && !fast<strncasecmp>(tag, "ERROR", 5))
- || ((size == 4) && !fast<strncasecmp>(tag, "INFO", 4))) {
- p = start;
- etag = tag = "";
+ } else {
+ // <PRI>[<TIME>] <tag> <stuff>' : message
+twoWord: while (--taglen && !isspace(*++cp) && (*cp != ':'));
+ const char *e;
+ for (e = cp; taglen && isspace(*cp); ++cp, --taglen);
+ // Two words
+ if (taglen && (*cp == ':')) {
+ tag = bt;
+ etag = e;
+ p = cp + 1;
+ }
}
+ } // else no tag
+
+ static const char cpu[] = "CPU";
+ static const size_t cpuLen = strlen(cpu);
+ static const char warning[] = "WARNING";
+ static const size_t warningLen = strlen(warning);
+ static const char error[] = "ERROR";
+ static const size_t errorLen = strlen(error);
+ static const char info[] = "INFO";
+ static const size_t infoLen = strlen(info);
+
+ size = etag - tag;
+ if ((size <= 1)
+ // register names like x9
+ || ((size == 2) && (isdigit(tag[0]) || isdigit(tag[1])))
+ // register names like x18 but not driver names like en0
+ || ((size == 3) && (isdigit(tag[1]) && isdigit(tag[2])))
+ // blacklist
+ || ((size == cpuLen) && !fast<strncmp>(tag, cpu, cpuLen))
+ || ((size == warningLen) && !fast<strncasecmp>(tag, warning, warningLen))
+ || ((size == errorLen) && !fast<strncasecmp>(tag, error, errorLen))
+ || ((size == infoLen) && !fast<strncasecmp>(tag, info, infoLen))) {
+ p = start;
+ etag = tag = "";
}
+
// Suppress additional stutter in tag:
// eg: [143:healthd]healthd -> [143:healthd]
taglen = etag - tag;
diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h
index 71ad73a..878c333 100644
--- a/logd/LogStatistics.h
+++ b/logd/LogStatistics.h
@@ -166,7 +166,7 @@
size_t size;
EntryBase():size(0) { }
- EntryBase(LogBufferElement *element):size(element->getMsgLen()) { }
+ explicit EntryBase(LogBufferElement *element):size(element->getMsgLen()) { }
size_t getSizes() const { return size; }
@@ -201,7 +201,7 @@
size_t dropped;
EntryBaseDropped():dropped(0) { }
- EntryBaseDropped(LogBufferElement *element):
+ explicit EntryBaseDropped(LogBufferElement *element):
EntryBase(element),
dropped(element->getDropped()) {
}
@@ -226,7 +226,7 @@
const uid_t uid;
pid_t pid;
- UidEntry(LogBufferElement *element):
+ explicit UidEntry(LogBufferElement *element):
EntryBaseDropped(element),
uid(element->getUid()),
pid(element->getPid()) {
@@ -256,13 +256,13 @@
uid_t uid;
char *name;
- PidEntry(pid_t pid):
+ explicit PidEntry(pid_t pid):
EntryBaseDropped(),
pid(pid),
uid(android::pidToUid(pid)),
name(android::pidToName(pid)) {
}
- PidEntry(LogBufferElement *element):
+ explicit PidEntry(LogBufferElement *element):
EntryBaseDropped(element),
pid(element->getPid()),
uid(element->getUid()),
@@ -320,7 +320,7 @@
uid(android::pidToUid(tid)),
name(android::tidToName(tid)) {
}
- TidEntry(LogBufferElement *element):
+ explicit TidEntry(LogBufferElement *element):
EntryBaseDropped(element),
tid(element->getTid()),
pid(element->getPid()),
@@ -375,7 +375,7 @@
pid_t pid;
uid_t uid;
- TagEntry(LogBufferElement *element):
+ explicit TagEntry(LogBufferElement *element):
EntryBaseDropped(element),
tag(element->getTag()),
pid(element->getPid()),
@@ -407,7 +407,7 @@
public:
- LogFindWorst(std::unique_ptr<const TEntry *[]> &&sorted) : sorted(std::move(sorted)) { }
+ explicit LogFindWorst(std::unique_ptr<const TEntry *[]> &&sorted) : sorted(std::move(sorted)) { }
void findWorst(int &worst,
size_t &worst_sizes, size_t &second_worst_sizes,
diff --git a/metricsd/Android.mk b/metricsd/Android.mk
index bb262b4..65ca1f6 100644
--- a/metricsd/Android.mk
+++ b/metricsd/Android.mk
@@ -199,9 +199,6 @@
LOCAL_SHARED_LIBRARIES := $(metricsd_shared_libraries)
LOCAL_SRC_FILES := $(metricsd_tests_sources) $(metricsd_common)
LOCAL_STATIC_LIBRARIES := libBionicGtestMain libgmock metricsd_protos metricsd_binder_proxy
-ifdef BRILLO
-LOCAL_MODULE_TAGS := eng
-endif
include $(BUILD_NATIVE_TEST)
# Unit tests for metrics_collector.
@@ -217,9 +214,6 @@
$(metrics_collector_common)
LOCAL_STATIC_LIBRARIES := libBionicGtestMain libgmock metricsd_binder_proxy \
$(metrics_collector_static_libraries)
-ifdef BRILLO
-LOCAL_MODULE_TAGS := eng
-endif
include $(BUILD_NATIVE_TEST)
# Weave schema files