Merge "Set GC threshold when mounting with checkpointing" into rvc-dev
diff --git a/base/liblog_symbols.h b/base/liblog_symbols.h
index d3134e9..b4ab06a 100644
--- a/base/liblog_symbols.h
+++ b/base/liblog_symbols.h
@@ -36,8 +36,8 @@
void (*__android_log_set_aborter)(__android_aborter_function aborter);
void (*__android_log_call_aborter)(const char* abort_message);
void (*__android_log_default_aborter)(const char* abort_message);
- int (*__android_log_set_minimum_priority)(int priority);
- int (*__android_log_get_minimum_priority)();
+ int32_t (*__android_log_set_minimum_priority)(int32_t priority);
+ int32_t (*__android_log_get_minimum_priority)();
void (*__android_log_set_default_tag)(const char* tag);
};
diff --git a/base/logging.cpp b/base/logging.cpp
index 9360a56..9a6e0fb 100644
--- a/base/logging.cpp
+++ b/base/logging.cpp
@@ -118,7 +118,7 @@
}
#endif
-static LogId log_id_tToLogId(int buffer_id) {
+static LogId log_id_tToLogId(int32_t buffer_id) {
switch (buffer_id) {
case LOG_ID_MAIN:
return MAIN;
@@ -134,7 +134,7 @@
}
}
-static int LogIdTolog_id_t(LogId log_id) {
+static int32_t LogIdTolog_id_t(LogId log_id) {
switch (log_id) {
case MAIN:
return LOG_ID_MAIN;
@@ -171,7 +171,7 @@
}
}
-static android_LogPriority LogSeverityToPriority(LogSeverity severity) {
+static int32_t LogSeverityToPriority(LogSeverity severity) {
switch (severity) {
case VERBOSE:
return ANDROID_LOG_VERBOSE;
@@ -333,12 +333,12 @@
void LogdLogger::operator()(LogId id, LogSeverity severity, const char* tag,
const char* file, unsigned int line,
const char* message) {
- android_LogPriority priority = LogSeverityToPriority(severity);
+ int32_t priority = LogSeverityToPriority(severity);
if (id == DEFAULT) {
id = default_log_id_;
}
- int lg_id = LogIdTolog_id_t(id);
+ int32_t lg_id = LogIdTolog_id_t(id);
char log_message_with_file[4068]; // LOGGER_ENTRY_MAX_PAYLOAD, not available in the NDK.
if (priority == ANDROID_LOG_FATAL && file != nullptr) {
@@ -574,7 +574,7 @@
void LogMessage::LogLine(const char* file, unsigned int line, LogSeverity severity, const char* tag,
const char* message) {
static auto& liblog_functions = GetLibLogFunctions();
- auto priority = LogSeverityToPriority(severity);
+ int32_t priority = LogSeverityToPriority(severity);
if (liblog_functions) {
__android_logger_data logger_data = {
sizeof(__android_logger_data), LOG_ID_DEFAULT, priority, tag, file, line};
@@ -608,7 +608,7 @@
// we need to fall back to using gMinimumLogSeverity, since __android_log_is_loggable() will not
// take into consideration the value from SetMinimumLogSeverity().
if (liblog_functions) {
- int priority = LogSeverityToPriority(severity);
+ int32_t priority = LogSeverityToPriority(severity);
return __android_log_is_loggable(priority, tag, ANDROID_LOG_INFO);
} else {
return severity >= gMinimumLogSeverity;
@@ -618,7 +618,7 @@
LogSeverity SetMinimumLogSeverity(LogSeverity new_severity) {
static auto& liblog_functions = GetLibLogFunctions();
if (liblog_functions) {
- auto priority = LogSeverityToPriority(new_severity);
+ int32_t priority = LogSeverityToPriority(new_severity);
return PriorityToLogSeverity(liblog_functions->__android_log_set_minimum_priority(priority));
} else {
LogSeverity old_severity = gMinimumLogSeverity;
diff --git a/liblog/include/android/log.h b/liblog/include/android/log.h
index 1c4ec64..43a91ab 100644
--- a/liblog/include/android/log.h
+++ b/liblog/include/android/log.h
@@ -56,6 +56,7 @@
#include <stdarg.h>
#include <stddef.h>
+#include <stdint.h>
#include <sys/cdefs.h>
#if !defined(__BIONIC__) && !defined(__INTRODUCED_IN)
@@ -154,14 +155,11 @@
/** The kernel log buffer. */
LOG_ID_KERNEL = 7,
- LOG_ID_MAX
-} log_id_t;
+ LOG_ID_MAX,
-/**
- * Let the logging function choose the best log target.
- * This is not part of the enum since adding either -1 or 0xFFFFFFFF forces the enum to be signed or
- * unsigned, which breaks unfortunately common arithmetic against LOG_ID_MIN and LOG_ID_MAX. */
-#define LOG_ID_DEFAULT -1
+ /** Let the logging function choose the best log target. */
+ LOG_ID_DEFAULT = 0x7FFFFFFF
+} log_id_t;
/**
* Writes the constant string `text` to the log buffer `id`,
@@ -188,11 +186,11 @@
*/
struct __android_logger_data {
size_t struct_size; /* Must be set to sizeof(__android_logger_data) and is used for versioning. */
- int buffer_id; /* log_id_t or -1 to represent 'default'. */
- int priority; /* android_LogPriority values. */
+ int32_t buffer_id; /* log_id_t or -1 to represent 'default'. */
+ int32_t priority; /* android_LogPriority values. */
const char* tag;
const char* file; /* Optional file name, may be set to nullptr. */
- unsigned int line; /* Optional line number, ignore if file is nullptr. */
+ uint32_t line; /* Optional line number, ignore if file is nullptr. */
};
/**
@@ -206,7 +204,7 @@
*/
typedef void (*__android_aborter_function)(const char* abort_message);
-#if __ANDROID_API__ >= 30 || !defined(__ANDROID__)
+#if !defined(__ANDROID__) || __ANDROID_API__ >= 30
/**
* Writes the log message specified with logger_data and msg to the log. logger_data includes
* additional file name and line number information that a logger may use. logger_data is versioned
@@ -276,13 +274,13 @@
*
* This returns the previous set minimum priority, or ANDROID_LOG_DEFAULT if none was set.
*/
-int __android_log_set_minimum_priority(int priority) __INTRODUCED_IN(30);
+int32_t __android_log_set_minimum_priority(int32_t priority) __INTRODUCED_IN(30);
/**
* Gets the minimum priority that will be logged for this process. If none has been set by a
* previous __android_log_set_minimum_priority() call, this returns ANDROID_LOG_DEFAULT.
*/
-int __android_log_get_minimum_priority(void) __INTRODUCED_IN(30);
+int32_t __android_log_get_minimum_priority(void) __INTRODUCED_IN(30);
/**
* Sets the default tag if no tag is provided when writing a log message. Defaults to
diff --git a/liblog/logger_name.cpp b/liblog/logger_name.cpp
index 7d676f4..e72290e 100644
--- a/liblog/logger_name.cpp
+++ b/liblog/logger_name.cpp
@@ -41,7 +41,10 @@
}
static_assert(std::is_same<std::underlying_type<log_id_t>::type, uint32_t>::value,
- "log_id_t must be an unsigned int");
+ "log_id_t must be an uint32_t");
+
+static_assert(std::is_same<std::underlying_type<android_LogPriority>::type, uint32_t>::value,
+ "log_id_t must be an uint32_t");
log_id_t android_name_to_log_id(const char* logName) {
const char* b;
diff --git a/liblog/logger_write.cpp b/liblog/logger_write.cpp
index 454a13b..b420fa0 100644
--- a/liblog/logger_write.cpp
+++ b/liblog/logger_write.cpp
@@ -149,12 +149,12 @@
GetDefaultTag().assign(tag, 0, LOGGER_ENTRY_MAX_PAYLOAD);
}
-static std::atomic_int minimum_log_priority = ANDROID_LOG_DEFAULT;
-int __android_log_set_minimum_priority(int priority) {
+static std::atomic_int32_t minimum_log_priority = ANDROID_LOG_DEFAULT;
+int32_t __android_log_set_minimum_priority(int32_t priority) {
return minimum_log_priority.exchange(priority, std::memory_order_relaxed);
}
-int __android_log_get_minimum_priority() {
+int32_t __android_log_get_minimum_priority() {
return minimum_log_priority;
}
@@ -267,7 +267,7 @@
static const char log_characters[] = "XXVDIWEF";
static_assert(arraysize(log_characters) - 1 == ANDROID_LOG_SILENT,
"Mismatch in size of log_characters and values in android_LogPriority");
- int priority =
+ int32_t priority =
logger_data->priority > ANDROID_LOG_SILENT ? ANDROID_LOG_FATAL : logger_data->priority;
char priority_char = log_characters[priority];
uint64_t tid = GetThreadId();
diff --git a/libstats/socket/include/stats_event.h b/libstats/socket/include/stats_event.h
index ff84283..3576298 100644
--- a/libstats/socket/include/stats_event.h
+++ b/libstats/socket/include/stats_event.h
@@ -29,8 +29,9 @@
* AStatsEvent* event = AStatsEvent_obtain();
*
* AStatsEvent_setAtomId(event, atomId);
+ * AStatsEvent_addBoolAnnotation(event, 5, false); // atom-level annotation
* AStatsEvent_writeInt32(event, 24);
- * AStatsEvent_addBoolAnnotation(event, 1, true); // annotations apply to the previous field
+ * AStatsEvent_addBoolAnnotation(event, 1, true); // annotation for preceding atom field
* AStatsEvent_addInt32Annotation(event, 2, 128);
* AStatsEvent_writeFloat(event, 2.0);
*
@@ -38,13 +39,8 @@
* AStatsEvent_write(event);
* AStatsEvent_release(event);
*
- * Notes:
- * (a) write_<type>() and add_<type>_annotation() should be called in the order that fields
- * and annotations are defined in the atom.
- * (b) set_atom_id() can be called anytime before stats_event_write().
- * (c) add_<type>_annotation() calls apply to the previous field.
- * (d) If errors occur, stats_event_write() will write a bitmask of the errors to the socket.
- * (e) All strings should be encoded using UTF8.
+ * Note that calls to add atom fields and annotations should be made in the
+ * order that they are defined in the atom.
*/
#ifdef __cplusplus
@@ -84,7 +80,7 @@
int AStatsEvent_write(AStatsEvent* event);
/**
- * Frees the memory held by this StatsEvent
+ * Frees the memory held by this StatsEvent.
*
* After calling this, the StatsEvent must not be used or modified in any way.
*/
@@ -92,6 +88,8 @@
/**
* Sets the atom id for this StatsEvent.
+ *
+ * This function should be called immediately after AStatsEvent_obtain.
**/
void AStatsEvent_setAtomId(AStatsEvent* event, uint32_t atomId);
diff --git a/libstats/socket/stats_event.c b/libstats/socket/stats_event.c
index b045d93..24d2ea8 100644
--- a/libstats/socket/stats_event.c
+++ b/libstats/socket/stats_event.c
@@ -29,7 +29,6 @@
#define POS_NUM_ELEMENTS 1
#define POS_TIMESTAMP (POS_NUM_ELEMENTS + sizeof(uint8_t))
#define POS_ATOM_ID (POS_TIMESTAMP + sizeof(uint8_t) + sizeof(uint64_t))
-#define POS_FIRST_FIELD (POS_ATOM_ID + sizeof(uint8_t) + sizeof(uint32_t))
/* LIMITS */
#define MAX_ANNOTATION_COUNT 15
@@ -66,8 +65,11 @@
// within a buf. Also includes other required fields.
struct AStatsEvent {
uint8_t* buf;
- size_t lastFieldPos; // location of last field within the buf
- size_t size; // number of valid bytes within buffer
+ // Location of last field within the buf. Here, field denotes either a
+ // metadata field (e.g. timestamp) or an atom field.
+ size_t lastFieldPos;
+ // Number of valid bytes within the buffer.
+ size_t size;
uint32_t numElements;
uint32_t atomId;
uint32_t errors;
@@ -85,20 +87,21 @@
AStatsEvent* AStatsEvent_obtain() {
AStatsEvent* event = malloc(sizeof(AStatsEvent));
event->buf = (uint8_t*)calloc(MAX_EVENT_PAYLOAD, 1);
- event->buf[0] = OBJECT_TYPE;
+ event->lastFieldPos = 0;
+ event->size = 2; // reserve first two bytes for outer event type and number of elements
+ event->numElements = 0;
event->atomId = 0;
event->errors = 0;
event->truncate = true; // truncate for both pulled and pushed atoms
event->built = false;
- // place the timestamp
- uint64_t timestampNs = get_elapsed_realtime_ns();
- event->buf[POS_TIMESTAMP] = INT64_TYPE;
- memcpy(&event->buf[POS_TIMESTAMP + sizeof(uint8_t)], ×tampNs, sizeof(timestampNs));
+ event->buf[0] = OBJECT_TYPE;
+ AStatsEvent_writeInt64(event, get_elapsed_realtime_ns()); // write the timestamp
- event->numElements = 1;
- event->lastFieldPos = 0; // 0 since we haven't written a field yet
- event->size = POS_FIRST_FIELD;
+ // Force client to set atom id immediately (this is required for atom-level
+ // annotations to be written correctly). All atom field and annotation
+ // writes will fail until the atom id is set because event->errors != 0.
+ event->errors |= ERROR_NO_ATOM_ID;
return event;
}
@@ -109,10 +112,12 @@
}
void AStatsEvent_setAtomId(AStatsEvent* event, uint32_t atomId) {
+ if ((event->errors & ERROR_NO_ATOM_ID) == 0) return;
+
+ // Clear the ERROR_NO_ATOM_ID bit.
+ event->errors &= ~ERROR_NO_ATOM_ID;
event->atomId = atomId;
- event->buf[POS_ATOM_ID] = INT32_TYPE;
- memcpy(&event->buf[POS_ATOM_ID + sizeof(uint8_t)], &atomId, sizeof(atomId));
- event->numElements++;
+ AStatsEvent_writeInt32(event, atomId);
}
// Overwrites the timestamp populated in AStatsEvent_obtain with a custom
@@ -306,23 +311,23 @@
void AStatsEvent_build(AStatsEvent* event) {
if (event->built) return;
- if (event->atomId == 0) event->errors |= ERROR_NO_ATOM_ID;
-
- if (event->numElements > MAX_BYTE_VALUE) {
- event->errors |= ERROR_TOO_MANY_FIELDS;
- } else {
- event->buf[POS_NUM_ELEMENTS] = event->numElements;
- }
+ if (event->numElements > MAX_BYTE_VALUE) event->errors |= ERROR_TOO_MANY_FIELDS;
// If there are errors, rewrite buffer.
if (event->errors) {
- event->buf[POS_NUM_ELEMENTS] = 3;
- event->buf[POS_FIRST_FIELD] = ERROR_TYPE;
- memcpy(&event->buf[POS_FIRST_FIELD + sizeof(uint8_t)], &event->errors,
- sizeof(event->errors));
- event->size = POS_FIRST_FIELD + sizeof(uint8_t) + sizeof(uint32_t);
+ // Discard everything after the atom id (including atom-level
+ // annotations). This leaves only two elements (timestamp and atom id).
+ event->numElements = 2;
+ // Reset number of atom-level annotations to 0.
+ event->buf[POS_ATOM_ID] = INT32_TYPE;
+ // Now, write errors to the buffer immediately after the atom id.
+ event->size = POS_ATOM_ID + sizeof(uint8_t) + sizeof(uint32_t);
+ start_field(event, ERROR_TYPE);
+ append_int32(event, event->errors);
}
+ event->buf[POS_NUM_ELEMENTS] = event->numElements;
+
// Truncate the buffer to the appropriate length in order to limit our
// memory usage.
if (event->truncate) event->buf = (uint8_t*)realloc(event->buf, event->size);
diff --git a/libstats/socket/tests/stats_event_test.cpp b/libstats/socket/tests/stats_event_test.cpp
index 69d0a9b..04eff36 100644
--- a/libstats/socket/tests/stats_event_test.cpp
+++ b/libstats/socket/tests/stats_event_test.cpp
@@ -89,7 +89,7 @@
}
void checkMetadata(uint8_t** buffer, uint8_t numElements, int64_t startTime, int64_t endTime,
- uint32_t atomId) {
+ uint32_t atomId, uint8_t numAtomLevelAnnotations = 0) {
// All events start with OBJECT_TYPE id.
checkTypeHeader(buffer, OBJECT_TYPE);
@@ -104,7 +104,7 @@
EXPECT_LE(timestamp, endTime);
// Check atom id
- checkTypeHeader(buffer, INT32_TYPE);
+ checkTypeHeader(buffer, INT32_TYPE, numAtomLevelAnnotations);
checkScalar(buffer, atomId);
}
@@ -240,7 +240,7 @@
AStatsEvent_release(event);
}
-TEST(StatsEventTest, TestAnnotations) {
+TEST(StatsEventTest, TestFieldAnnotations) {
uint32_t atomId = 100;
// first element information
@@ -259,7 +259,7 @@
int64_t startTime = android::elapsedRealtimeNano();
AStatsEvent* event = AStatsEvent_obtain();
- AStatsEvent_setAtomId(event, 100);
+ AStatsEvent_setAtomId(event, atomId);
AStatsEvent_writeBool(event, boolValue);
AStatsEvent_addBoolAnnotation(event, boolAnnotation1Id, boolAnnotation1Value);
AStatsEvent_addInt32Annotation(event, boolAnnotation2Id, boolAnnotation2Value);
@@ -292,6 +292,45 @@
AStatsEvent_release(event);
}
+TEST(StatsEventTest, TestAtomLevelAnnotations) {
+ uint32_t atomId = 100;
+ // atom-level annotation information
+ uint8_t boolAnnotationId = 1;
+ uint8_t int32AnnotationId = 2;
+ bool boolAnnotationValue = false;
+ int32_t int32AnnotationValue = 5;
+
+ float fieldValue = -3.5;
+
+ int64_t startTime = android::elapsedRealtimeNano();
+ AStatsEvent* event = AStatsEvent_obtain();
+ AStatsEvent_setAtomId(event, atomId);
+ AStatsEvent_addBoolAnnotation(event, boolAnnotationId, boolAnnotationValue);
+ AStatsEvent_addInt32Annotation(event, int32AnnotationId, int32AnnotationValue);
+ AStatsEvent_writeFloat(event, fieldValue);
+ AStatsEvent_build(event);
+ int64_t endTime = android::elapsedRealtimeNano();
+
+ size_t bufferSize;
+ uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
+ uint8_t* bufferEnd = buffer + bufferSize;
+
+ checkMetadata(&buffer, /*numElements=*/1, startTime, endTime, atomId,
+ /*numAtomLevelAnnotations=*/2);
+
+ // check atom-level annotations
+ checkAnnotation(&buffer, boolAnnotationId, BOOL_TYPE, boolAnnotationValue);
+ checkAnnotation(&buffer, int32AnnotationId, INT32_TYPE, int32AnnotationValue);
+
+ // check first element
+ checkTypeHeader(&buffer, FLOAT_TYPE);
+ checkScalar(&buffer, fieldValue);
+
+ EXPECT_EQ(buffer, bufferEnd); // ensure that we have read the entire buffer
+ EXPECT_EQ(AStatsEvent_getErrors(event), 0);
+ AStatsEvent_release(event);
+}
+
TEST(StatsEventTest, TestNoAtomIdError) {
AStatsEvent* event = AStatsEvent_obtain();
// Don't set the atom id in order to trigger the error.