Revert "Revert "Start auto-generating the stats log API.""
Test: builds successfully
This reverts commit 9319453998.
Change-Id: I22bca4a32adf86040b9d72ad5b45999aba28f586
This commit is contained in:
11
Android.mk
11
Android.mk
@@ -587,6 +587,17 @@ LOCAL_SRC_FILES += \
|
||||
lowpan/java/android/net/lowpan/ILowpanManagerListener.aidl \
|
||||
lowpan/java/android/net/lowpan/ILowpanManager.aidl
|
||||
|
||||
# StatsLog generated functions
|
||||
statslog_src_dir := $(call intermediates-dir-for,JAVA_LIBRARIES,framework,,COMMON)/statslog
|
||||
gen := $(statslog_src_dir)/android/util/StatsLog.java
|
||||
$(gen): PRIVATE_PATH := $(LOCAL_PATH)
|
||||
$(gen): PRIVATE_CUSTOM_TOOL = $(HOST_OUT_EXECUTABLES)/stats-log-api-gen --java $@
|
||||
$(gen): $(HOST_OUT_EXECUTABLES)/stats-log-api-gen
|
||||
$(transform-generated-source)
|
||||
LOCAL_GENERATED_SOURCES += $(gen)
|
||||
statslog_src_dir:=
|
||||
gen:=
|
||||
|
||||
# FRAMEWORKS_BASE_JAVA_SRC_DIRS comes from build/core/pathmap.mk
|
||||
LOCAL_AIDL_INCLUDES += \
|
||||
$(FRAMEWORKS_BASE_JAVA_SRC_DIRS) \
|
||||
|
||||
37
cmds/statsd/Android.bp
Normal file
37
cmds/statsd/Android.bp
Normal file
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// Copyright (C) 2015 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
// ==========================================================
|
||||
// Build the library for use on the host
|
||||
// ==========================================================
|
||||
cc_library_host_shared {
|
||||
name: "libstats_proto_host",
|
||||
srcs: [
|
||||
"src/stats_events.proto",
|
||||
"src/stats_log.proto",
|
||||
"src/statsd_config.proto",
|
||||
],
|
||||
|
||||
shared_libs: [
|
||||
"libplatformprotos",
|
||||
],
|
||||
|
||||
proto: {
|
||||
type: "full",
|
||||
export_proto_headers: true,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -14,22 +14,51 @@
|
||||
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
|
||||
# ================
|
||||
# proto static lib
|
||||
# ================
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := statsd_proto
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
statsd_common_src := \
|
||||
../../core/java/android/os/IStatsCompanionService.aidl \
|
||||
../../core/java/android/os/IStatsManager.aidl \
|
||||
src/stats_log.proto \
|
||||
src/statsd_config.proto \
|
||||
src/stats_events.proto \
|
||||
src/condition/CombinationConditionTracker.cpp \
|
||||
src/condition/condition_util.cpp \
|
||||
src/condition/SimpleConditionTracker.cpp \
|
||||
src/matchers/CombinationLogMatchingTracker.cpp \
|
||||
src/matchers/matcher_util.cpp \
|
||||
src/matchers/SimpleLogMatchingTracker.cpp \
|
||||
src/metrics/CountAnomalyTracker.cpp \
|
||||
src/metrics/CountMetricProducer.cpp \
|
||||
src/metrics/MetricsManager.cpp \
|
||||
src/metrics/metrics_manager_util.cpp \
|
||||
src/AnomalyMonitor.cpp \
|
||||
src/DropboxReader.cpp \
|
||||
src/DropboxWriter.cpp \
|
||||
src/KernelWakelockPuller.cpp \
|
||||
src/LogEntryPrinter.cpp \
|
||||
src/LogReader.cpp \
|
||||
src/StatsLogProcessor.cpp \
|
||||
src/StatsPullerManager.cpp \
|
||||
src/StatsService.cpp \
|
||||
src/stats_util.cpp \
|
||||
src/UidMap.cpp
|
||||
|
||||
LOCAL_SRC_FILES := $(call all-proto-files-under, src)
|
||||
statsd_common_c_includes := \
|
||||
$(LOCAL_PATH)/src
|
||||
|
||||
LOCAL_PROTOC_FLAGS :=
|
||||
LOCAL_PROTOC_OPTIMIZE_TYPE := lite-static
|
||||
statsd_common_aidl_includes := \
|
||||
$(LOCAL_PATH)/../../core/java
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
STATSD_PROTO_INCLUDES := $(local-generated-sources-dir)/src/$(LOCAL_PATH)
|
||||
statsd_common_shared_libraries := \
|
||||
libbase \
|
||||
libbinder \
|
||||
libcutils \
|
||||
libincident \
|
||||
liblog \
|
||||
libselinux \
|
||||
libutils \
|
||||
libservices \
|
||||
libandroidfw
|
||||
|
||||
# =========
|
||||
# statsd
|
||||
@@ -40,9 +69,8 @@ include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := statsd
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
../../core/java/android/os/IStatsCompanionService.aidl \
|
||||
../../core/java/android/os/IStatsManager.aidl \
|
||||
$(call all-cpp-files-under,src) \
|
||||
$(statsd_common_src) \
|
||||
src/main.cpp
|
||||
|
||||
LOCAL_CFLAGS += \
|
||||
-Wall \
|
||||
@@ -60,24 +88,12 @@ else
|
||||
LOCAL_CFLAGS += \
|
||||
-Os
|
||||
endif
|
||||
LOCAL_PROTOC_OPTIMIZE_TYPE := lite-static
|
||||
|
||||
LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/../../core/java
|
||||
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src \
|
||||
STATSD_PROTO_INCLUDES
|
||||
LOCAL_AIDL_INCLUDES := $(statsd_common_c_includes)
|
||||
LOCAL_C_INCLUDES += $(statsd_common_c_includes)
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := statsd_proto
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libbase \
|
||||
libbinder \
|
||||
libcutils \
|
||||
libincident \
|
||||
liblog \
|
||||
libselinux \
|
||||
libutils \
|
||||
libservices \
|
||||
libandroidfw \
|
||||
libprotobuf-cpp-lite \
|
||||
LOCAL_SHARED_LIBRARIES := $(statsd_common_shared_libraries)
|
||||
|
||||
LOCAL_MODULE_CLASS := EXECUTABLES
|
||||
|
||||
@@ -85,6 +101,7 @@ LOCAL_MODULE_CLASS := EXECUTABLES
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
|
||||
# ==============
|
||||
# statsd_test
|
||||
# ==============
|
||||
@@ -95,8 +112,8 @@ LOCAL_MODULE := statsd_test
|
||||
LOCAL_COMPATIBILITY_SUITE := device-tests
|
||||
LOCAL_MODULE_TAGS := tests
|
||||
|
||||
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src \
|
||||
STATSD_PROTO_INCLUDES
|
||||
LOCAL_AIDL_INCLUDES := $(statsd_common_c_includes)
|
||||
LOCAL_C_INCLUDES += $(statsd_common_c_includes)
|
||||
|
||||
LOCAL_CFLAGS += \
|
||||
-Wall \
|
||||
@@ -107,38 +124,25 @@ LOCAL_CFLAGS += \
|
||||
-Wno-unused-parameter
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
src/stats_log.proto \
|
||||
src/statsd_config.proto \
|
||||
../../core/java/android/os/IStatsCompanionService.aidl \
|
||||
../../core/java/android/os/IStatsManager.aidl \
|
||||
src/StatsService.cpp \
|
||||
src/AnomalyMonitor.cpp \
|
||||
src/stats_util.cpp \
|
||||
src/LogEntryPrinter.cpp \
|
||||
src/LogReader.cpp \
|
||||
src/matchers/matcher_util.cpp \
|
||||
src/condition/SimpleConditionTracker.cpp \
|
||||
src/condition/CombinationConditionTracker.cpp \
|
||||
src/matchers/SimpleLogMatchingTracker.cpp \
|
||||
src/matchers/CombinationLogMatchingTracker.cpp \
|
||||
src/metrics/metrics_manager_util.cpp \
|
||||
src/metrics/CountMetricProducer.cpp \
|
||||
src/metrics/CountAnomalyTracker.cpp \
|
||||
src/condition/condition_util.cpp \
|
||||
src/UidMap.cpp \
|
||||
$(call all-cpp-files-under, tests) \
|
||||
$(statsd_common_src) \
|
||||
tests/indexed_priority_queue_test.cpp \
|
||||
tests/LogReader_test.cpp \
|
||||
tests/MetricsManager_test.cpp \
|
||||
tests/UidMap_test.cpp \
|
||||
tests/LogEntryMatcher_test.cpp \
|
||||
tests/AnomalyMonitor_test.cpp \
|
||||
tests/ConditionTracker_test.cpp
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := \
|
||||
libgmock \
|
||||
statsd_proto \
|
||||
libgmock
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libbase \
|
||||
libbinder \
|
||||
libcutils \
|
||||
liblog \
|
||||
libselinux \
|
||||
libutils \
|
||||
libprotobuf-cpp-lite \
|
||||
LOCAL_SHARED_LIBRARIES := $(statsd_common_shared_libraries)
|
||||
|
||||
LOCAL_PROTOC_OPTIMIZE_TYPE := lite
|
||||
|
||||
statsd_common_src:=
|
||||
statsd_common_aidl_includes:=
|
||||
statsd_common_c_includes:=
|
||||
|
||||
include $(BUILD_NATIVE_TEST)
|
||||
|
||||
|
||||
@@ -20,6 +20,11 @@
|
||||
#include <log/logprint.h>
|
||||
#include <utils/Errors.h>
|
||||
|
||||
#include "matchers/matcher_util.h"
|
||||
|
||||
#define PRINT_WITH_LIBLOG 0
|
||||
#define PRINT_WITH_LOG_EVENT_WRAPPER 1
|
||||
|
||||
using namespace android;
|
||||
|
||||
namespace android {
|
||||
@@ -44,16 +49,24 @@ LogEntryPrinter::~LogEntryPrinter() {
|
||||
}
|
||||
|
||||
void LogEntryPrinter::OnLogEvent(const log_msg& msg) {
|
||||
status_t err;
|
||||
AndroidLogEntry entry;
|
||||
char buf[1024];
|
||||
if (PRINT_WITH_LIBLOG) {
|
||||
status_t err;
|
||||
AndroidLogEntry entry;
|
||||
char buf[1024];
|
||||
|
||||
err = android_log_processBinaryLogBuffer(&(const_cast<log_msg*>(&msg)->entry_v1), &entry,
|
||||
m_tags, buf, sizeof(buf));
|
||||
if (err == NO_ERROR) {
|
||||
android_log_printLogLine(m_format, m_out, &entry);
|
||||
} else {
|
||||
printf("log entry: %s\n", buf);
|
||||
err = android_log_processBinaryLogBuffer(&(const_cast<log_msg*>(&msg)->entry_v1), &entry,
|
||||
m_tags, buf, sizeof(buf));
|
||||
if (err == NO_ERROR) {
|
||||
android_log_printLogLine(m_format, m_out, &entry);
|
||||
} else {
|
||||
printf("log entry: %s\n", buf);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
if (PRINT_WITH_LOG_EVENT_WRAPPER) {
|
||||
LogEventWrapper event = parseLogEvent(msg);
|
||||
printf("event: %s\n", event.toString().c_str());
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,8 +26,11 @@
|
||||
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
|
||||
#include "stats_util.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
using std::set;
|
||||
using std::string;
|
||||
using std::ostringstream;
|
||||
using std::unordered_map;
|
||||
using std::vector;
|
||||
|
||||
@@ -35,6 +38,42 @@ namespace android {
|
||||
namespace os {
|
||||
namespace statsd {
|
||||
|
||||
string LogEventWrapper::toString() const {
|
||||
std::ostringstream result;
|
||||
result << "{ " << timestamp_ns << " (" << tagId << ")";
|
||||
for (int index = 1; ; index++) {
|
||||
auto intVal = intMap.find(index);
|
||||
auto strVal = strMap.find(index);
|
||||
auto boolVal = boolMap.find(index);
|
||||
auto floatVal = floatMap.find(index);
|
||||
if (intVal != intMap.end()) {
|
||||
result << " ";
|
||||
result << std::to_string(index);
|
||||
result << "->";
|
||||
result << std::to_string(intVal->second);
|
||||
} else if (strVal != strMap.end()) {
|
||||
result << " ";
|
||||
result << std::to_string(index);
|
||||
result << "->";
|
||||
result << strVal->second;
|
||||
} else if (boolVal != boolMap.end()) {
|
||||
result << " ";
|
||||
result << std::to_string(index);
|
||||
result << "->";
|
||||
result << std::to_string(boolVal->second);
|
||||
} else if (floatVal != floatMap.end()) {
|
||||
result << " ";
|
||||
result << std::to_string(index);
|
||||
result << "->";
|
||||
result << std::to_string(floatVal->second);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
result << " }";
|
||||
return result.str();
|
||||
}
|
||||
|
||||
LogEventWrapper parseLogEvent(log_msg msg) {
|
||||
LogEventWrapper wrapper;
|
||||
wrapper.timestamp_ns = msg.entry_v1.sec * NS_PER_SEC + msg.entry_v1.nsec;
|
||||
@@ -48,38 +87,32 @@ LogEventWrapper parseLogEvent(log_msg msg) {
|
||||
|
||||
if (context) {
|
||||
memset(&elem, 0, sizeof(elem));
|
||||
size_t index = 0;
|
||||
int32_t key = -1;
|
||||
// TODO: The log is actually structured inside one list. This is convenient
|
||||
// because we'll be able to use it to put the attribution (WorkSource) block first
|
||||
// without doing our own tagging scheme. Until that change is in, just drop the
|
||||
// list-related log elements and the order we get there is our index-keyed data
|
||||
// structure.
|
||||
int32_t key = 1;
|
||||
do {
|
||||
elem = android_log_read_next(context);
|
||||
switch ((int)elem.type) {
|
||||
case EVENT_TYPE_INT:
|
||||
if (index % 2 == 0) {
|
||||
key = elem.data.int32;
|
||||
} else {
|
||||
wrapper.intMap[key] = elem.data.int32;
|
||||
}
|
||||
index++;
|
||||
wrapper.intMap[key] = elem.data.int32;
|
||||
key++;
|
||||
break;
|
||||
case EVENT_TYPE_FLOAT:
|
||||
if (index % 2 == 1) {
|
||||
wrapper.floatMap[key] = elem.data.float32;
|
||||
}
|
||||
index++;
|
||||
wrapper.floatMap[key] = elem.data.float32;
|
||||
key++;
|
||||
break;
|
||||
case EVENT_TYPE_STRING:
|
||||
if (index % 2 == 1) {
|
||||
// without explicit calling string() constructor, there will be an
|
||||
// additional 0 in the end of the string.
|
||||
wrapper.strMap[key] = string(elem.data.string);
|
||||
}
|
||||
index++;
|
||||
// without explicit calling string() constructor, there will be an
|
||||
// additional 0 in the end of the string.
|
||||
wrapper.strMap[key] = string(elem.data.string);
|
||||
key++;
|
||||
break;
|
||||
case EVENT_TYPE_LONG:
|
||||
if (index % 2 == 1) {
|
||||
wrapper.intMap[key] = elem.data.int64;
|
||||
}
|
||||
index++;
|
||||
wrapper.intMap[key] = elem.data.int64;
|
||||
key++;
|
||||
break;
|
||||
case EVENT_TYPE_LIST:
|
||||
break;
|
||||
@@ -91,10 +124,6 @@ LogEventWrapper parseLogEvent(log_msg msg) {
|
||||
elem.complete = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (elem.complete) {
|
||||
break;
|
||||
}
|
||||
} while ((elem.type != EVENT_TYPE_UNKNOWN) && !elem.complete);
|
||||
|
||||
android_log_destroy(&context);
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <log/log_read.h>
|
||||
#include <log/logprint.h>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include "frameworks/base/cmds/statsd/src/stats_log.pb.h"
|
||||
@@ -36,6 +37,8 @@ typedef struct {
|
||||
std::unordered_map<int, std::string> strMap;
|
||||
std::unordered_map<int, bool> boolMap;
|
||||
std::unordered_map<int, float> floatMap;
|
||||
|
||||
std::string toString() const;
|
||||
} LogEventWrapper;
|
||||
|
||||
enum MatchingState {
|
||||
|
||||
@@ -15,49 +15,116 @@
|
||||
*/
|
||||
|
||||
syntax = "proto2";
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
|
||||
// TODO: Not the right package and class name
|
||||
package android.os.statsd;
|
||||
|
||||
option java_package = "com.android.os";
|
||||
option java_outer_classname = "StatsEventProto";
|
||||
|
||||
/**
|
||||
* The master event class. This message defines all of the available
|
||||
* raw stats log events from the Android system, also known as "atoms."
|
||||
*
|
||||
* This field contains a single oneof with all of the available messages.
|
||||
* The stats-log-api-gen tool runs as part of the Android build and
|
||||
* generates the android.util.StatsLog class, which contains the constants
|
||||
* and methods that Android uses to log.
|
||||
*
|
||||
* This StatsEvent class is not actually built into the Android system.
|
||||
* Instead, statsd on Android constructs these messages synthetically,
|
||||
* in the format defined here and in stats_log.proto.
|
||||
*/
|
||||
message StatsEvent {
|
||||
oneof event {
|
||||
// Screen state change.
|
||||
ScreenStateChange screen_state_change = 2;
|
||||
// Process state change.
|
||||
ProcessStateChange process_state_change = 1112;
|
||||
}
|
||||
oneof event {
|
||||
ScreenStateChanged screen_state_changed = 1;
|
||||
ProcessStateChanged process_state_changed = 2;
|
||||
WakeLockChanged wakelock_changed = 3;
|
||||
}
|
||||
}
|
||||
|
||||
// Logs changes in screen state. This event is logged in
|
||||
// frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java
|
||||
message ScreenStateChange {
|
||||
// Screen state enums follow the values defined in below file.
|
||||
// frameworks/base/core/java/android/view/Display.java
|
||||
enum State {
|
||||
STATE_UNKNOWN = 0;
|
||||
STATE_OFF = 1;
|
||||
STATE_ON = 2;
|
||||
STATE_DOZE = 3;
|
||||
STATE_DOZE_SUSPEND = 4;
|
||||
STATE_VR = 5;
|
||||
}
|
||||
// New screen state.
|
||||
optional State display_state = 1;
|
||||
/**
|
||||
* A WorkSource represents the chained attribution of applications that
|
||||
* resulted in a particular bit of work being done.
|
||||
*/
|
||||
message WorkSource {
|
||||
// TODO
|
||||
}
|
||||
|
||||
// Logs changes in process state. This event is logged in
|
||||
// frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java
|
||||
message ProcessStateChange {
|
||||
// Type of process event.
|
||||
enum State {
|
||||
START = 1;
|
||||
CRASH = 2;
|
||||
}
|
||||
optional State state = 1;
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Below are all of the individual atoms that are logged by Android via statsd
|
||||
* and Westworld.
|
||||
*
|
||||
* RULES:
|
||||
* - The field ids for each atom must start at 1, and count upwards by 1.
|
||||
* Skipping field ids is not allowed.
|
||||
* - These form an API, so renaming, renumbering or removing fields is
|
||||
* not allowed between android releases. (This is not currently enforced,
|
||||
* but there will be a tool to enforce this restriction).
|
||||
* - The types must be built-in protocol buffer types, namely, no sub-messages
|
||||
* are allowed (yet). The bytes type is also not allowed.
|
||||
* - The CamelCase name of the message type should match the
|
||||
* underscore_separated name as defined in StatsEvent.
|
||||
* - If an atom represents work that can be attributed to an app, there can
|
||||
* be exactly one WorkSource field. It must be field number 1.
|
||||
* - A field that is a uid should be a string field, tagged with the [xxx]
|
||||
* annotation. The generated code on android will be represented by UIDs,
|
||||
* and those UIDs will be translated in xxx to those strings.
|
||||
*
|
||||
* CONVENTIONS:
|
||||
* - Events are past tense. e.g. ScreenStateChanged, not ScreenStateChange
|
||||
* - If there is a UID, it goes first. Think in an object-oriented fashion.
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
// UID associated with the package.
|
||||
optional int32 uid = 2;
|
||||
/**
|
||||
* Logs when the screen state changes.
|
||||
*
|
||||
* Logged from:
|
||||
* frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java
|
||||
*/
|
||||
message ScreenStateChanged {
|
||||
// TODO: Use the real screen state.
|
||||
enum State {
|
||||
STATE_UNKNOWN = 0;
|
||||
STATE_OFF = 1;
|
||||
STATE_ON = 2;
|
||||
STATE_DOZE = 3;
|
||||
STATE_DOZE_SUSPEND = 4;
|
||||
STATE_VR = 5;
|
||||
}
|
||||
// New screen state.
|
||||
optional State display_state = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs that the state of a process state, as per the activity manager has changed.
|
||||
*
|
||||
* Logged from:
|
||||
* frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java
|
||||
*/
|
||||
message ProcessStateChanged {
|
||||
// TODO: Use the real (mapped) process states.
|
||||
optional int32 uid = 1; // TODO: should be a string tagged w/ uid annotation
|
||||
|
||||
// The state.
|
||||
optional int32 state = 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs that the state of a wakelock has changed.
|
||||
*
|
||||
* Logged from:
|
||||
* TODO
|
||||
*/
|
||||
message WakeLockChanged {
|
||||
// TODO: Add attribution instead of uid.
|
||||
optional int32 uid = 1;
|
||||
|
||||
// The wakelock tag (Called tag in the Java API, sometimes name elsewhere).
|
||||
optional string tag = 2;
|
||||
|
||||
// TODO: Use a constant instead of boolean?
|
||||
optional bool state = 3;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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.
|
||||
*/
|
||||
|
||||
package android.util;
|
||||
|
||||
/**
|
||||
* Logging access for platform metrics.
|
||||
*
|
||||
* <p>This is <b>not</b> the main "logcat" debugging log ({@link android.util.Log})!
|
||||
* These diagnostic stats are for system integrators, not application authors.
|
||||
*
|
||||
* <p>Stats use integer tag codes.
|
||||
* They carry a payload of one or more int, long, or String values.
|
||||
* @hide
|
||||
*/
|
||||
public class StatsLog {
|
||||
/** @hide */ public StatsLog() {}
|
||||
|
||||
private static final String TAG = "StatsLog";
|
||||
|
||||
// We assume that the native methods deal with any concurrency issues.
|
||||
|
||||
/**
|
||||
* Records an stats log message.
|
||||
* @param tag The stats type tag code
|
||||
* @param value A value to log
|
||||
* @return The number of bytes written
|
||||
*/
|
||||
public static native int writeInt(int tag, int value);
|
||||
|
||||
/**
|
||||
* Records an stats log message.
|
||||
* @param tag The stats type tag code
|
||||
* @param value A value to log
|
||||
* @return The number of bytes written
|
||||
*/
|
||||
public static native int writeLong(int tag, long value);
|
||||
|
||||
/**
|
||||
* Records an stats log message.
|
||||
* @param tag The stats type tag code
|
||||
* @param value A value to log
|
||||
* @return The number of bytes written
|
||||
*/
|
||||
public static native int writeFloat(int tag, float value);
|
||||
|
||||
/**
|
||||
* Records an stats log message.
|
||||
* @param tag The stats type tag code
|
||||
* @param str A value to log
|
||||
* @return The number of bytes written
|
||||
*/
|
||||
public static native int writeString(int tag, String str);
|
||||
|
||||
/**
|
||||
* Records an stats log message.
|
||||
* @param tag The stats type tag code
|
||||
* @param list A list of values to log. All values should
|
||||
* be of type int, long, float or String.
|
||||
* @return The number of bytes written
|
||||
*/
|
||||
public static native int writeArray(int tag, Object... list);
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// THIS FILE IS AUTO-GENERATED.
|
||||
// DO NOT MODIFY.
|
||||
|
||||
package android.util;
|
||||
|
||||
/** @hide */
|
||||
public class StatsLogKey {
|
||||
private StatsLogKey() {}
|
||||
|
||||
/** Constants for android.os.statsd.ScreenStateChange. */
|
||||
|
||||
/** display_state */
|
||||
public static final int SCREEN_STATE_CHANGE__DISPLAY_STATE = 1;
|
||||
|
||||
/** Constants for android.os.statsd.ProcessStateChange. */
|
||||
|
||||
/** state */
|
||||
public static final int PROCESS_STATE_CHANGE__STATE = 1;
|
||||
|
||||
/** uid */
|
||||
public static final int PROCESS_STATE_CHANGE__UID = 2;
|
||||
|
||||
/** package_name */
|
||||
public static final int PROCESS_STATE_CHANGE__PACKAGE_NAME = 1002;
|
||||
|
||||
/** package_version */
|
||||
public static final int PROCESS_STATE_CHANGE__PACKAGE_VERSION = 3;
|
||||
|
||||
/** package_version_string */
|
||||
public static final int PROCESS_STATE_CHANGE__PACKAGE_VERSION_STRING = 4;
|
||||
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// THIS FILE IS AUTO-GENERATED.
|
||||
// DO NOT MODIFY.
|
||||
|
||||
package android.util;
|
||||
|
||||
/** @hide */
|
||||
public class StatsLogTag {
|
||||
private StatsLogTag() {}
|
||||
|
||||
/** android.os.statsd.ScreenStateChange. */
|
||||
public static final int SCREEN_STATE_CHANGE = 2;
|
||||
|
||||
/** android.os.statsd.ProcessStateChange. */
|
||||
public static final int PROCESS_STATE_CHANGE = 1112;
|
||||
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// THIS FILE IS AUTO-GENERATED.
|
||||
// DO NOT MODIFY.
|
||||
|
||||
package android.util;
|
||||
|
||||
/** @hide */
|
||||
public class StatsLogValue {
|
||||
private StatsLogValue() {}
|
||||
|
||||
/** Constants for android.os.statsd.ScreenStateChange. */
|
||||
|
||||
/** display_state: STATE_UNKNOWN */
|
||||
public static final int SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_UNKNOWN = 0;
|
||||
|
||||
/** display_state: STATE_OFF */
|
||||
public static final int SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_OFF = 1;
|
||||
|
||||
/** display_state: STATE_ON */
|
||||
public static final int SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON = 2;
|
||||
|
||||
/** display_state: STATE_DOZE */
|
||||
public static final int SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_DOZE = 3;
|
||||
|
||||
/** display_state: STATE_DOZE_SUSPEND */
|
||||
public static final int SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_DOZE_SUSPEND = 4;
|
||||
|
||||
/** display_state: STATE_VR */
|
||||
public static final int SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_VR = 5;
|
||||
|
||||
/** Constants for android.os.statsd.ProcessStateChange. */
|
||||
|
||||
/** state: START */
|
||||
public static final int PROCESS_STATE_CHANGE__STATE__START = 1;
|
||||
|
||||
/** state: CRASH */
|
||||
public static final int PROCESS_STATE_CHANGE__STATE__CRASH = 2;
|
||||
|
||||
}
|
||||
@@ -1,3 +1,13 @@
|
||||
|
||||
genrule {
|
||||
name: "android_util_StatsLog.cpp",
|
||||
tools: ["stats-log-api-gen"],
|
||||
cmd: "$(location stats-log-api-gen) --jni $(genDir)/android_util_StatsLog.cpp",
|
||||
out: [
|
||||
"android_util_StatsLog.cpp",
|
||||
],
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "libandroid_runtime",
|
||||
|
||||
@@ -104,7 +114,6 @@ cc_library_shared {
|
||||
"android_nio_utils.cpp",
|
||||
"android_util_AssetManager.cpp",
|
||||
"android_util_Binder.cpp",
|
||||
"android_util_StatsLog.cpp",
|
||||
"android_util_EventLog.cpp",
|
||||
"android_util_MemoryIntArray.cpp",
|
||||
"android_util_Log.cpp",
|
||||
@@ -271,11 +280,13 @@ cc_library_shared {
|
||||
"libhwbinder",
|
||||
"libvintf",
|
||||
"libnativewindow",
|
||||
|
||||
"libhwui",
|
||||
"libdl",
|
||||
"libstatslog",
|
||||
],
|
||||
|
||||
generated_sources: ["android_util_StatsLog.cpp"],
|
||||
|
||||
local_include_dirs: ["android/graphics"],
|
||||
export_include_dirs: [
|
||||
".",
|
||||
|
||||
@@ -1324,10 +1324,10 @@ static const RegJNIRec gRegJNI[] = {
|
||||
REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit),
|
||||
REG_JNI(register_android_os_SystemClock),
|
||||
REG_JNI(register_android_util_EventLog),
|
||||
REG_JNI(register_android_util_StatsLog),
|
||||
REG_JNI(register_android_util_Log),
|
||||
REG_JNI(register_android_util_MemoryIntArray),
|
||||
REG_JNI(register_android_util_PathParser),
|
||||
REG_JNI(register_android_util_StatsLog),
|
||||
REG_JNI(register_android_app_admin_SecurityLog),
|
||||
REG_JNI(register_android_content_AssetManager),
|
||||
REG_JNI(register_android_content_StringBlock),
|
||||
|
||||
@@ -1,201 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007-2014 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 <fcntl.h>
|
||||
#include <log/log_event_list.h>
|
||||
|
||||
#include <log/log.h>
|
||||
|
||||
#include <nativehelper/JNIHelp.h>
|
||||
#include "core_jni_helpers.h"
|
||||
#include "jni.h"
|
||||
|
||||
#define UNUSED __attribute__((__unused__))
|
||||
|
||||
namespace android {
|
||||
|
||||
static jclass gCollectionClass;
|
||||
static jmethodID gCollectionAddID;
|
||||
|
||||
static jclass gIntegerClass;
|
||||
static jfieldID gIntegerValueID;
|
||||
|
||||
static jclass gLongClass;
|
||||
static jfieldID gLongValueID;
|
||||
|
||||
static jclass gFloatClass;
|
||||
static jfieldID gFloatValueID;
|
||||
|
||||
static jclass gStringClass;
|
||||
|
||||
/*
|
||||
* In class android.util.StatsLog:
|
||||
* static native int writeInt(int tag, int value)
|
||||
*/
|
||||
static jint android_util_StatsLog_write_Integer(JNIEnv* env UNUSED,
|
||||
jobject clazz UNUSED,
|
||||
jint tag, jint value)
|
||||
{
|
||||
android_log_event_list ctx(tag);
|
||||
ctx << (int32_t)value;
|
||||
return ctx.write(LOG_ID_STATS);
|
||||
}
|
||||
|
||||
/*
|
||||
* In class android.util.StatsLog:
|
||||
* static native int writeLong(long tag, long value)
|
||||
*/
|
||||
static jint android_util_StatsLog_write_Long(JNIEnv* env UNUSED,
|
||||
jobject clazz UNUSED,
|
||||
jint tag, jlong value)
|
||||
{
|
||||
android_log_event_list ctx(tag);
|
||||
ctx << (int64_t)value;
|
||||
return ctx.write(LOG_ID_STATS);
|
||||
}
|
||||
|
||||
/*
|
||||
* In class android.util.StatsLog:
|
||||
* static native int writeFloat(long tag, float value)
|
||||
*/
|
||||
static jint android_util_StatsLog_write_Float(JNIEnv* env UNUSED,
|
||||
jobject clazz UNUSED,
|
||||
jint tag, jfloat value)
|
||||
{
|
||||
android_log_event_list ctx(tag);
|
||||
ctx << (float)value;
|
||||
return ctx.write(LOG_ID_STATS);
|
||||
}
|
||||
|
||||
/*
|
||||
* In class android.util.StatsLog:
|
||||
* static native int writeString(int tag, String value)
|
||||
*/
|
||||
static jint android_util_StatsLog_write_String(JNIEnv* env,
|
||||
jobject clazz UNUSED,
|
||||
jint tag, jstring value) {
|
||||
android_log_event_list ctx(tag);
|
||||
// Don't throw NPE -- I feel like it's sort of mean for a logging function
|
||||
// to be all crashy if you pass in NULL -- but make the NULL value explicit.
|
||||
if (value != NULL) {
|
||||
const char *str = env->GetStringUTFChars(value, NULL);
|
||||
ctx << str;
|
||||
env->ReleaseStringUTFChars(value, str);
|
||||
} else {
|
||||
ctx << "NULL";
|
||||
}
|
||||
return ctx.write(LOG_ID_STATS);
|
||||
}
|
||||
|
||||
/*
|
||||
* In class android.util.StatsLog:
|
||||
* static native int writeArray(long tag, Object... value)
|
||||
*/
|
||||
static jint android_util_StatsLog_write_Array(JNIEnv* env, jobject clazz,
|
||||
jint tag, jobjectArray value) {
|
||||
android_log_event_list ctx(tag);
|
||||
|
||||
if (value == NULL) {
|
||||
ctx << "[NULL]";
|
||||
return ctx.write(LOG_ID_STATS);
|
||||
}
|
||||
|
||||
jsize copied = 0, num = env->GetArrayLength(value);
|
||||
for (; copied < num && copied < 255; ++copied) {
|
||||
if (ctx.status()) break;
|
||||
jobject item = env->GetObjectArrayElement(value, copied);
|
||||
if (item == NULL) {
|
||||
ctx << "NULL";
|
||||
} else if (env->IsInstanceOf(item, gStringClass)) {
|
||||
const char *str = env->GetStringUTFChars((jstring) item, NULL);
|
||||
ctx << str;
|
||||
env->ReleaseStringUTFChars((jstring) item, str);
|
||||
} else if (env->IsInstanceOf(item, gIntegerClass)) {
|
||||
ctx << (int32_t)env->GetIntField(item, gIntegerValueID);
|
||||
} else if (env->IsInstanceOf(item, gLongClass)) {
|
||||
ctx << (int64_t)env->GetLongField(item, gLongValueID);
|
||||
} else if (env->IsInstanceOf(item, gFloatClass)) {
|
||||
ctx << (float)env->GetFloatField(item, gFloatValueID);
|
||||
} else {
|
||||
jniThrowException(env,
|
||||
"java/lang/IllegalArgumentException",
|
||||
"Invalid payload item type");
|
||||
return -1;
|
||||
}
|
||||
env->DeleteLocalRef(item);
|
||||
}
|
||||
return ctx.write(LOG_ID_STATS);
|
||||
}
|
||||
|
||||
/*
|
||||
* JNI registration.
|
||||
*/
|
||||
static const JNINativeMethod gRegisterMethods[] = {
|
||||
/* name, signature, funcPtr */
|
||||
{ "writeInt", "(II)I", (void*) android_util_StatsLog_write_Integer },
|
||||
{ "writeLong", "(IJ)I", (void*) android_util_StatsLog_write_Long },
|
||||
{ "writeFloat", "(IF)I", (void*) android_util_StatsLog_write_Float },
|
||||
{ "writeString",
|
||||
"(ILjava/lang/String;)I",
|
||||
(void*) android_util_StatsLog_write_String
|
||||
},
|
||||
{ "writeArray",
|
||||
"(I[Ljava/lang/Object;)I",
|
||||
(void*) android_util_StatsLog_write_Array
|
||||
},
|
||||
};
|
||||
|
||||
static struct { const char *name; jclass *clazz; } gClasses[] = {
|
||||
{ "java/lang/Integer", &gIntegerClass },
|
||||
{ "java/lang/Long", &gLongClass },
|
||||
{ "java/lang/Float", &gFloatClass },
|
||||
{ "java/lang/String", &gStringClass },
|
||||
{ "java/util/Collection", &gCollectionClass },
|
||||
};
|
||||
|
||||
static struct { jclass *c; const char *name, *ft; jfieldID *id; } gFields[] = {
|
||||
{ &gIntegerClass, "value", "I", &gIntegerValueID },
|
||||
{ &gLongClass, "value", "J", &gLongValueID },
|
||||
{ &gFloatClass, "value", "F", &gFloatValueID },
|
||||
};
|
||||
|
||||
static struct { jclass *c; const char *name, *mt; jmethodID *id; } gMethods[] = {
|
||||
{ &gCollectionClass, "add", "(Ljava/lang/Object;)Z", &gCollectionAddID },
|
||||
};
|
||||
|
||||
int register_android_util_StatsLog(JNIEnv* env) {
|
||||
for (int i = 0; i < NELEM(gClasses); ++i) {
|
||||
jclass clazz = FindClassOrDie(env, gClasses[i].name);
|
||||
*gClasses[i].clazz = MakeGlobalRefOrDie(env, clazz);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NELEM(gFields); ++i) {
|
||||
*gFields[i].id = GetFieldIDOrDie(env,
|
||||
*gFields[i].c, gFields[i].name, gFields[i].ft);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NELEM(gMethods); ++i) {
|
||||
*gMethods[i].id = GetMethodIDOrDie(env,
|
||||
*gMethods[i].c, gMethods[i].name, gMethods[i].mt);
|
||||
}
|
||||
|
||||
return RegisterMethodsOrDie(
|
||||
env,
|
||||
"android/util/StatsLog",
|
||||
gRegisterMethods, NELEM(gRegisterMethods));
|
||||
}
|
||||
|
||||
}; // namespace android
|
||||
@@ -297,26 +297,12 @@ public final class BatteryStatsService extends IBatteryStats.Stub
|
||||
void noteProcessStart(String name, int uid) {
|
||||
synchronized (mStats) {
|
||||
mStats.noteProcessStartLocked(name, uid);
|
||||
|
||||
// TODO: remove this once we figure out properly where and how
|
||||
// PROCESS_EVENT = 1112
|
||||
// KEY_STATE = 1
|
||||
// KEY_PACKAGE_NAME: 1002
|
||||
// KEY_UID: 2
|
||||
StatsLog.writeArray(1112, 1, 1, 1002, name, 2, uid);
|
||||
}
|
||||
}
|
||||
|
||||
void noteProcessCrash(String name, int uid) {
|
||||
synchronized (mStats) {
|
||||
mStats.noteProcessCrashLocked(name, uid);
|
||||
|
||||
// TODO: remove this once we figure out properly where and how
|
||||
// PROCESS_EVENT = 1112
|
||||
// KEY_STATE = 1
|
||||
// KEY_PACKAGE_NAME: 1002
|
||||
// KEY_UID: 2
|
||||
StatsLog.writeArray(1112, 1, 2, 1002, name, 2, uid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -334,6 +320,9 @@ public final class BatteryStatsService extends IBatteryStats.Stub
|
||||
|
||||
void noteUidProcessState(int uid, int state) {
|
||||
synchronized (mStats) {
|
||||
// TODO: remove this once we figure out properly where and how
|
||||
StatsLog.write(StatsLog.PROCESS_STATE_CHANGED, uid, state);
|
||||
|
||||
mStats.noteUidProcessStateLocked(uid, state);
|
||||
}
|
||||
}
|
||||
@@ -548,12 +537,10 @@ public final class BatteryStatsService extends IBatteryStats.Stub
|
||||
enforceCallingPermission();
|
||||
if (DBG) Slog.d(TAG, "begin noteScreenState");
|
||||
synchronized (mStats) {
|
||||
mStats.noteScreenStateLocked(state);
|
||||
// TODO: remove this once we figure out properly where and how
|
||||
// SCREEN_EVENT = 2
|
||||
// KEY_STATE: 1
|
||||
// State value: state. We can change this to our own def later.
|
||||
StatsLog.writeArray(2, 1, state);
|
||||
StatsLog.write(StatsLog.SCREEN_STATE_CHANGED, state);
|
||||
|
||||
mStats.noteScreenStateLocked(state);
|
||||
}
|
||||
if (DBG) Slog.d(TAG, "end noteScreenState");
|
||||
}
|
||||
|
||||
98
tools/stats_log_api_gen/Android.bp
Normal file
98
tools/stats_log_api_gen/Android.bp
Normal file
@@ -0,0 +1,98 @@
|
||||
//
|
||||
// Copyright (C) 2017 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
// ==========================================================
|
||||
// Build the host executable: stats-log-api-gen
|
||||
// ==========================================================
|
||||
cc_binary_host {
|
||||
name: "stats-log-api-gen",
|
||||
srcs: [
|
||||
"Collation.cpp",
|
||||
"main.cpp",
|
||||
],
|
||||
|
||||
shared_libs: [
|
||||
"libstats_proto_host",
|
||||
"libprotobuf-cpp-full",
|
||||
],
|
||||
|
||||
proto: {
|
||||
type: "full",
|
||||
},
|
||||
}
|
||||
|
||||
// ==========================================================
|
||||
// Build the host test executable: stats-log-api-gen
|
||||
// ==========================================================
|
||||
cc_test_host {
|
||||
name: "stats-log-api-gen-test",
|
||||
cflags: [
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Werror",
|
||||
"-g",
|
||||
"-DUNIT_TEST",
|
||||
],
|
||||
srcs: [
|
||||
"Collation.cpp",
|
||||
"test_collation.cpp",
|
||||
"test.proto",
|
||||
],
|
||||
|
||||
static_libs: [
|
||||
"libgmock_host",
|
||||
],
|
||||
|
||||
shared_libs: [
|
||||
"libstats_proto_host",
|
||||
],
|
||||
|
||||
proto: {
|
||||
type: "full",
|
||||
},
|
||||
}
|
||||
|
||||
// ==========================================================
|
||||
// Native library
|
||||
// ==========================================================
|
||||
genrule {
|
||||
name: "statslog.h",
|
||||
tools: ["stats-log-api-gen"],
|
||||
cmd: "$(location stats-log-api-gen) --header $(genDir)/statslog.h",
|
||||
out: [
|
||||
"statslog.h",
|
||||
],
|
||||
}
|
||||
|
||||
genrule {
|
||||
name: "statslog.cpp",
|
||||
tools: ["stats-log-api-gen"],
|
||||
cmd: "$(location stats-log-api-gen) --cpp $(genDir)/statslog.cpp",
|
||||
out: [
|
||||
"statslog.cpp",
|
||||
],
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "libstatslog",
|
||||
generated_sources: ["statslog.cpp"],
|
||||
generated_headers: ["statslog.h"],
|
||||
export_generated_headers: ["statslog.h"],
|
||||
shared_libs: [
|
||||
"liblog",
|
||||
],
|
||||
}
|
||||
|
||||
265
tools/stats_log_api_gen/Collation.cpp
Normal file
265
tools/stats_log_api_gen/Collation.cpp
Normal file
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
* Copyright (C) 2017, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "Collation.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <map>
|
||||
|
||||
namespace android {
|
||||
namespace stats_log_api_gen {
|
||||
|
||||
using google::protobuf::FieldDescriptor;
|
||||
using google::protobuf::FileDescriptor;
|
||||
using google::protobuf::SourceLocation;
|
||||
using std::map;
|
||||
|
||||
|
||||
//
|
||||
// AtomDecl class
|
||||
//
|
||||
|
||||
AtomDecl::AtomDecl()
|
||||
:code(0),
|
||||
name()
|
||||
{
|
||||
}
|
||||
|
||||
AtomDecl::AtomDecl(const AtomDecl& that)
|
||||
:code(that.code),
|
||||
name(that.name),
|
||||
message(that.message),
|
||||
fields(that.fields)
|
||||
{
|
||||
}
|
||||
|
||||
AtomDecl::AtomDecl(int c, const string& n, const string& m)
|
||||
:code(c),
|
||||
name(n),
|
||||
message(m)
|
||||
{
|
||||
}
|
||||
|
||||
AtomDecl::~AtomDecl()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Print an error message for a FieldDescriptor, including the file name and line number.
|
||||
*/
|
||||
static void
|
||||
print_error(const FieldDescriptor* field, const char* format, ...)
|
||||
{
|
||||
const Descriptor* message = field->containing_type();
|
||||
const FileDescriptor* file = message->file();
|
||||
|
||||
SourceLocation loc;
|
||||
if (field->GetSourceLocation(&loc)) {
|
||||
// TODO: this will work if we can figure out how to pass --include_source_info to protoc
|
||||
fprintf(stderr, "%s:%d: ", file->name().c_str(), loc.start_line);
|
||||
} else {
|
||||
fprintf(stderr, "%s: ", file->name().c_str());
|
||||
}
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vfprintf(stderr, format, args);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a protobuf type into a java type.
|
||||
*/
|
||||
static java_type_t
|
||||
java_type(const FieldDescriptor* field)
|
||||
{
|
||||
int protoType = field->type();
|
||||
switch (protoType) {
|
||||
case FieldDescriptor::TYPE_DOUBLE:
|
||||
return JAVA_TYPE_DOUBLE;
|
||||
case FieldDescriptor::TYPE_FLOAT:
|
||||
return JAVA_TYPE_FLOAT;
|
||||
case FieldDescriptor::TYPE_INT64:
|
||||
return JAVA_TYPE_LONG;
|
||||
case FieldDescriptor::TYPE_UINT64:
|
||||
return JAVA_TYPE_LONG;
|
||||
case FieldDescriptor::TYPE_INT32:
|
||||
return JAVA_TYPE_INT;
|
||||
case FieldDescriptor::TYPE_FIXED64:
|
||||
return JAVA_TYPE_LONG;
|
||||
case FieldDescriptor::TYPE_FIXED32:
|
||||
return JAVA_TYPE_INT;
|
||||
case FieldDescriptor::TYPE_BOOL:
|
||||
return JAVA_TYPE_BOOLEAN;
|
||||
case FieldDescriptor::TYPE_STRING:
|
||||
return JAVA_TYPE_STRING;
|
||||
case FieldDescriptor::TYPE_GROUP:
|
||||
return JAVA_TYPE_UNKNOWN;
|
||||
case FieldDescriptor::TYPE_MESSAGE:
|
||||
// TODO: not the final package name
|
||||
if (field->message_type()->full_name() == "android.os.statsd.WorkSource") {
|
||||
return JAVA_TYPE_WORK_SOURCE;
|
||||
} else {
|
||||
return JAVA_TYPE_OBJECT;
|
||||
}
|
||||
case FieldDescriptor::TYPE_BYTES:
|
||||
return JAVA_TYPE_BYTE_ARRAY;
|
||||
case FieldDescriptor::TYPE_UINT32:
|
||||
return JAVA_TYPE_INT;
|
||||
case FieldDescriptor::TYPE_ENUM:
|
||||
return JAVA_TYPE_INT;
|
||||
case FieldDescriptor::TYPE_SFIXED32:
|
||||
return JAVA_TYPE_INT;
|
||||
case FieldDescriptor::TYPE_SFIXED64:
|
||||
return JAVA_TYPE_LONG;
|
||||
case FieldDescriptor::TYPE_SINT32:
|
||||
return JAVA_TYPE_INT;
|
||||
case FieldDescriptor::TYPE_SINT64:
|
||||
return JAVA_TYPE_LONG;
|
||||
default:
|
||||
return JAVA_TYPE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gather the info about the atoms.
|
||||
*/
|
||||
int
|
||||
collate_atoms(const Descriptor* descriptor, Atoms* atoms)
|
||||
{
|
||||
int errorCount = 0;
|
||||
const bool dbg = false;
|
||||
|
||||
for (int i=0; i<descriptor->field_count(); i++) {
|
||||
const FieldDescriptor* atomField = descriptor->field(i);
|
||||
|
||||
if (dbg) {
|
||||
printf(" %s (%d)\n", atomField->name().c_str(), atomField->number());
|
||||
}
|
||||
|
||||
// StatsEvent only has one oneof, which contains only messages. Don't allow other types.
|
||||
if (atomField->type() != FieldDescriptor::TYPE_MESSAGE) {
|
||||
print_error(atomField,
|
||||
"Bad type for atom. StatsEvent can only have message type fields: %s\n",
|
||||
atomField->name().c_str());
|
||||
errorCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
const Descriptor* atom = atomField->message_type();
|
||||
|
||||
// Build a sorted list of the fields. Descriptor has them in source file order.
|
||||
map<int,const FieldDescriptor*> fields;
|
||||
for (int j=0; j<atom->field_count(); j++) {
|
||||
const FieldDescriptor* field = atom->field(j);
|
||||
fields[field->number()] = field;
|
||||
}
|
||||
|
||||
// Check that the parameters start at 1 and go up sequentially.
|
||||
int expectedNumber = 1;
|
||||
for (map<int,const FieldDescriptor*>::const_iterator it = fields.begin();
|
||||
it != fields.end(); it++) {
|
||||
const int number = it->first;
|
||||
const FieldDescriptor* field = it->second;
|
||||
if (number != expectedNumber) {
|
||||
print_error(field, "Fields must be numbered consecutively starting at 1:"
|
||||
" '%s' is %d but should be %d\n",
|
||||
field->name().c_str(), number, expectedNumber);
|
||||
errorCount++;
|
||||
expectedNumber = number;
|
||||
continue;
|
||||
}
|
||||
expectedNumber++;
|
||||
}
|
||||
|
||||
// Check that only allowed types are present. Remove any invalid ones.
|
||||
for (map<int,const FieldDescriptor*>::const_iterator it = fields.begin();
|
||||
it != fields.end(); it++) {
|
||||
const FieldDescriptor* field = it->second;
|
||||
|
||||
java_type_t javaType = java_type(field);
|
||||
|
||||
if (javaType == JAVA_TYPE_UNKNOWN) {
|
||||
print_error(field, "Unkown type for field: %s\n", field->name().c_str());
|
||||
errorCount++;
|
||||
continue;
|
||||
} else if (javaType == JAVA_TYPE_OBJECT) {
|
||||
// Allow WorkSources, but only at position 1.
|
||||
print_error(field, "Message type not allowed for field: %s\n",
|
||||
field->name().c_str());
|
||||
errorCount++;
|
||||
continue;
|
||||
} else if (javaType == JAVA_TYPE_BYTE_ARRAY) {
|
||||
print_error(field, "Raw bytes type not allowed for field: %s\n",
|
||||
field->name().c_str());
|
||||
errorCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Check that if there's a WorkSource, it's at position 1.
|
||||
for (map<int,const FieldDescriptor*>::const_iterator it = fields.begin();
|
||||
it != fields.end(); it++) {
|
||||
int number = it->first;
|
||||
if (number != 1) {
|
||||
const FieldDescriptor* field = it->second;
|
||||
java_type_t javaType = java_type(field);
|
||||
if (javaType == JAVA_TYPE_WORK_SOURCE) {
|
||||
print_error(field, "WorkSource fields must have field id 1, in message: '%s'\n",
|
||||
atom->name().c_str());
|
||||
errorCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AtomDecl atomDecl(atomField->number(), atomField->name(), atom->name());
|
||||
|
||||
// Build the type signature
|
||||
vector<java_type_t> signature;
|
||||
for (map<int,const FieldDescriptor*>::const_iterator it = fields.begin();
|
||||
it != fields.end(); it++) {
|
||||
const FieldDescriptor* field = it->second;
|
||||
java_type_t javaType = java_type(field);
|
||||
|
||||
atomDecl.fields.push_back(AtomField(field->name(), javaType));
|
||||
signature.push_back(javaType);
|
||||
}
|
||||
|
||||
atoms->signatures.insert(signature);
|
||||
atoms->decls.insert(atomDecl);
|
||||
}
|
||||
|
||||
if (dbg) {
|
||||
printf("signatures = [\n");
|
||||
for (set<vector<java_type_t>>::const_iterator it = atoms->signatures.begin();
|
||||
it != atoms->signatures.end(); it++) {
|
||||
printf(" ");
|
||||
for (vector<java_type_t>::const_iterator jt = it->begin(); jt != it->end(); jt++) {
|
||||
printf(" %d", (int)*jt);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
printf("]\n");
|
||||
}
|
||||
|
||||
return errorCount;
|
||||
}
|
||||
|
||||
} // namespace stats_log_api_gen
|
||||
} // namespace android
|
||||
|
||||
|
||||
100
tools/stats_log_api_gen/Collation.h
Normal file
100
tools/stats_log_api_gen/Collation.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (C) 2017, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_STATS_LOG_API_GEN_COLLATION_H
|
||||
#define ANDROID_STATS_LOG_API_GEN_COLLATION_H
|
||||
|
||||
|
||||
#include <google/protobuf/descriptor.h>
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace android {
|
||||
namespace stats_log_api_gen {
|
||||
|
||||
using std::set;
|
||||
using std::string;
|
||||
using std::vector;
|
||||
using google::protobuf::Descriptor;
|
||||
|
||||
/**
|
||||
* The types for atom parameters.
|
||||
*/
|
||||
typedef enum {
|
||||
JAVA_TYPE_UNKNOWN = 0,
|
||||
|
||||
JAVA_TYPE_WORK_SOURCE = 1,
|
||||
JAVA_TYPE_BOOLEAN = 2,
|
||||
JAVA_TYPE_INT = 3,
|
||||
JAVA_TYPE_LONG = 4,
|
||||
JAVA_TYPE_FLOAT = 5,
|
||||
JAVA_TYPE_DOUBLE = 6,
|
||||
JAVA_TYPE_STRING = 7,
|
||||
|
||||
JAVA_TYPE_OBJECT = -1,
|
||||
JAVA_TYPE_BYTE_ARRAY = -2,
|
||||
} java_type_t;
|
||||
|
||||
|
||||
/**
|
||||
* The name and type for an atom field.
|
||||
*/
|
||||
struct AtomField {
|
||||
string name;
|
||||
java_type_t javaType;
|
||||
|
||||
inline AtomField() :name(), javaType(JAVA_TYPE_UNKNOWN) {}
|
||||
inline AtomField(const AtomField& that) :name(that.name), javaType(that.javaType) {}
|
||||
inline AtomField(string n, java_type_t jt) :name(n), javaType(jt) {}
|
||||
inline ~AtomField() {}
|
||||
};
|
||||
|
||||
/**
|
||||
* The name and code for an atom.
|
||||
*/
|
||||
struct AtomDecl {
|
||||
int code;
|
||||
string name;
|
||||
|
||||
string message;
|
||||
vector<AtomField> fields;
|
||||
|
||||
AtomDecl();
|
||||
AtomDecl(const AtomDecl& that);
|
||||
AtomDecl(int code, const string& name, const string& message);
|
||||
~AtomDecl();
|
||||
|
||||
inline bool operator<(const AtomDecl& that) const {
|
||||
return (code == that.code) ? (name < that.name) : (code < that.code);
|
||||
}
|
||||
};
|
||||
|
||||
struct Atoms {
|
||||
set<vector<java_type_t>> signatures;
|
||||
set<AtomDecl> decls;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gather the information about the atoms. Returns the number of errors.
|
||||
*/
|
||||
int collate_atoms(const Descriptor* descriptor, Atoms* atoms);
|
||||
|
||||
} // namespace stats_log_api_gen
|
||||
} // namespace android
|
||||
|
||||
|
||||
#endif // ANDROID_STATS_LOG_API_GEN_COLLATION_H
|
||||
623
tools/stats_log_api_gen/main.cpp
Normal file
623
tools/stats_log_api_gen/main.cpp
Normal file
@@ -0,0 +1,623 @@
|
||||
|
||||
|
||||
#include "Collation.h"
|
||||
|
||||
#include "frameworks/base/cmds/statsd/src/stats_events.pb.h"
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
using namespace google::protobuf;
|
||||
using namespace std;
|
||||
|
||||
namespace android {
|
||||
namespace stats_log_api_gen {
|
||||
|
||||
using android::os::statsd::StatsEvent;
|
||||
|
||||
// TODO: Support WorkSources
|
||||
|
||||
/**
|
||||
* Turn lower and camel case into upper case with underscores.
|
||||
*/
|
||||
static string
|
||||
make_constant_name(const string& str)
|
||||
{
|
||||
string result;
|
||||
const int N = str.size();
|
||||
bool underscore_next = false;
|
||||
for (int i=0; i<N; i++) {
|
||||
char c = str[i];
|
||||
if (c >= 'A' && c <= 'Z') {
|
||||
if (underscore_next) {
|
||||
result += '_';
|
||||
underscore_next = false;
|
||||
}
|
||||
} else if (c >= 'a' && c <= 'z') {
|
||||
c = 'A' + c - 'a';
|
||||
underscore_next = true;
|
||||
} else if (c == '_') {
|
||||
underscore_next = false;
|
||||
}
|
||||
result += c;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static const char*
|
||||
cpp_type_name(java_type_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case JAVA_TYPE_BOOLEAN:
|
||||
return "bool";
|
||||
case JAVA_TYPE_INT:
|
||||
return "int32_t";
|
||||
case JAVA_TYPE_LONG:
|
||||
return "int64_t";
|
||||
case JAVA_TYPE_FLOAT:
|
||||
return "float";
|
||||
case JAVA_TYPE_DOUBLE:
|
||||
return "double";
|
||||
case JAVA_TYPE_STRING:
|
||||
return "char const*";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
static const char*
|
||||
java_type_name(java_type_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case JAVA_TYPE_BOOLEAN:
|
||||
return "boolean";
|
||||
case JAVA_TYPE_INT:
|
||||
return "int";
|
||||
case JAVA_TYPE_LONG:
|
||||
return "long";
|
||||
case JAVA_TYPE_FLOAT:
|
||||
return "float";
|
||||
case JAVA_TYPE_DOUBLE:
|
||||
return "double";
|
||||
case JAVA_TYPE_STRING:
|
||||
return "java.lang.String";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
write_stats_log_cpp(FILE* out, const Atoms& atoms)
|
||||
{
|
||||
int errorCount;
|
||||
|
||||
// Print prelude
|
||||
fprintf(out, "// This file is autogenerated\n");
|
||||
fprintf(out, "\n");
|
||||
|
||||
fprintf(out, "#include <log/log_event_list.h>\n");
|
||||
fprintf(out, "#include <log/log.h>\n");
|
||||
fprintf(out, "#include <statslog.h>\n");
|
||||
fprintf(out, "\n");
|
||||
|
||||
fprintf(out, "namespace android {\n");
|
||||
fprintf(out, "namespace util {\n");
|
||||
|
||||
// Print write methods
|
||||
fprintf(out, "\n");
|
||||
for (set<vector<java_type_t>>::const_iterator signature = atoms.signatures.begin();
|
||||
signature != atoms.signatures.end(); signature++) {
|
||||
int argIndex;
|
||||
|
||||
fprintf(out, "void\n");
|
||||
fprintf(out, "stats_write(int code");
|
||||
argIndex = 1;
|
||||
for (vector<java_type_t>::const_iterator arg = signature->begin();
|
||||
arg != signature->end(); arg++) {
|
||||
fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
|
||||
argIndex++;
|
||||
}
|
||||
fprintf(out, ")\n");
|
||||
|
||||
fprintf(out, "{\n");
|
||||
argIndex = 1;
|
||||
fprintf(out, " android_log_event_list event(code);\n");
|
||||
for (vector<java_type_t>::const_iterator arg = signature->begin();
|
||||
arg != signature->end(); arg++) {
|
||||
if (*arg == JAVA_TYPE_STRING) {
|
||||
fprintf(out, " if (arg%d == NULL) {\n", argIndex);
|
||||
fprintf(out, " arg%d = \"\";\n", argIndex);
|
||||
fprintf(out, " }\n");
|
||||
}
|
||||
fprintf(out, " event << arg%d;\n", argIndex);
|
||||
argIndex++;
|
||||
}
|
||||
|
||||
fprintf(out, " event.write(LOG_ID_STATS);\n");
|
||||
fprintf(out, "}\n");
|
||||
fprintf(out, "\n");
|
||||
}
|
||||
|
||||
// Print footer
|
||||
fprintf(out, "\n");
|
||||
fprintf(out, "} // namespace util\n");
|
||||
fprintf(out, "} // namespace android\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
write_stats_log_header(FILE* out, const Atoms& atoms)
|
||||
{
|
||||
int errorCount;
|
||||
|
||||
// Print prelude
|
||||
fprintf(out, "// This file is autogenerated\n");
|
||||
fprintf(out, "\n");
|
||||
fprintf(out, "#pragma once\n");
|
||||
fprintf(out, "\n");
|
||||
fprintf(out, "#include <stdint.h>\n");
|
||||
fprintf(out, "\n");
|
||||
|
||||
fprintf(out, "namespace android {\n");
|
||||
fprintf(out, "namespace util {\n");
|
||||
fprintf(out, "\n");
|
||||
fprintf(out, "/*\n");
|
||||
fprintf(out, " * API For logging statistics events.\n");
|
||||
fprintf(out, " */\n");
|
||||
fprintf(out, "\n");
|
||||
fprintf(out, "/**\n");
|
||||
fprintf(out, " * Constants for event codes.\n");
|
||||
fprintf(out, " */\n");
|
||||
fprintf(out, "enum {\n");
|
||||
|
||||
size_t i = 0;
|
||||
// Print constants
|
||||
for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
|
||||
atom != atoms.decls.end(); atom++) {
|
||||
string constant = make_constant_name(atom->name);
|
||||
fprintf(out, "\n");
|
||||
fprintf(out, " /**\n");
|
||||
fprintf(out, " * %s %s\n", atom->message.c_str(), atom->name.c_str());
|
||||
fprintf(out, " * Usage: stats_write(StatsLog.%s", constant.c_str());
|
||||
for (vector<AtomField>::const_iterator field = atom->fields.begin();
|
||||
field != atom->fields.end(); field++) {
|
||||
fprintf(out, ", %s %s", cpp_type_name(field->javaType), field->name.c_str());
|
||||
}
|
||||
fprintf(out, ");\n");
|
||||
fprintf(out, " */\n");
|
||||
char const* const comma = (i == atoms.decls.size() - 1) ? "" : ",";
|
||||
fprintf(out, " %s = %d%s\n", constant.c_str(), atom->code, comma);
|
||||
i++;
|
||||
}
|
||||
fprintf(out, "\n");
|
||||
fprintf(out, "};\n");
|
||||
fprintf(out, "\n");
|
||||
|
||||
// Print write methods
|
||||
fprintf(out, "//\n");
|
||||
fprintf(out, "// Write methods\n");
|
||||
fprintf(out, "//\n");
|
||||
for (set<vector<java_type_t>>::const_iterator signature = atoms.signatures.begin();
|
||||
signature != atoms.signatures.end(); signature++) {
|
||||
|
||||
fprintf(out, "void stats_write(int code");
|
||||
int argIndex = 1;
|
||||
for (vector<java_type_t>::const_iterator arg = signature->begin();
|
||||
arg != signature->end(); arg++) {
|
||||
fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
|
||||
argIndex++;
|
||||
}
|
||||
fprintf(out, ");\n");
|
||||
}
|
||||
|
||||
fprintf(out, "\n");
|
||||
fprintf(out, "} // namespace util\n");
|
||||
fprintf(out, "} // namespace android\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
write_stats_log_java(FILE* out, const Atoms& atoms)
|
||||
{
|
||||
int errorCount;
|
||||
|
||||
// Print prelude
|
||||
fprintf(out, "// This file is autogenerated\n");
|
||||
fprintf(out, "\n");
|
||||
fprintf(out, "package android.util;\n");
|
||||
fprintf(out, "\n");
|
||||
fprintf(out, "\n");
|
||||
fprintf(out, "/**\n");
|
||||
fprintf(out, " * API For logging statistics events.\n");
|
||||
fprintf(out, " * @hide\n");
|
||||
fprintf(out, " */\n");
|
||||
fprintf(out, "public final class StatsLog {\n");
|
||||
fprintf(out, " // Constants for event codes.\n");
|
||||
|
||||
// Print constants
|
||||
for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
|
||||
atom != atoms.decls.end(); atom++) {
|
||||
string constant = make_constant_name(atom->name);
|
||||
fprintf(out, "\n");
|
||||
fprintf(out, " /**\n");
|
||||
fprintf(out, " * %s %s\n", atom->message.c_str(), atom->name.c_str());
|
||||
fprintf(out, " * Usage: StatsLog.write(StatsLog.%s", constant.c_str());
|
||||
for (vector<AtomField>::const_iterator field = atom->fields.begin();
|
||||
field != atom->fields.end(); field++) {
|
||||
fprintf(out, ", %s %s", java_type_name(field->javaType), field->name.c_str());
|
||||
}
|
||||
fprintf(out, ");\n");
|
||||
fprintf(out, " */\n");
|
||||
fprintf(out, " public static final int %s = %d;\n", constant.c_str(), atom->code);
|
||||
}
|
||||
fprintf(out, "\n");
|
||||
|
||||
// Print write methods
|
||||
fprintf(out, " // Write methods\n");
|
||||
for (set<vector<java_type_t>>::const_iterator signature = atoms.signatures.begin();
|
||||
signature != atoms.signatures.end(); signature++) {
|
||||
fprintf(out, " public static native void write(int code");
|
||||
int argIndex = 1;
|
||||
for (vector<java_type_t>::const_iterator arg = signature->begin();
|
||||
arg != signature->end(); arg++) {
|
||||
fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex);
|
||||
argIndex++;
|
||||
}
|
||||
fprintf(out, ");\n");
|
||||
}
|
||||
|
||||
fprintf(out, "}\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char*
|
||||
jni_type_name(java_type_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case JAVA_TYPE_BOOLEAN:
|
||||
return "jboolean";
|
||||
case JAVA_TYPE_INT:
|
||||
return "jint";
|
||||
case JAVA_TYPE_LONG:
|
||||
return "jlong";
|
||||
case JAVA_TYPE_FLOAT:
|
||||
return "jfloat";
|
||||
case JAVA_TYPE_DOUBLE:
|
||||
return "jdouble";
|
||||
case JAVA_TYPE_STRING:
|
||||
return "jstring";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
static string
|
||||
jni_function_name(const vector<java_type_t>& signature)
|
||||
{
|
||||
string result("StatsLog_write");
|
||||
for (vector<java_type_t>::const_iterator arg = signature.begin();
|
||||
arg != signature.end(); arg++) {
|
||||
switch (*arg) {
|
||||
case JAVA_TYPE_BOOLEAN:
|
||||
result += "_boolean";
|
||||
break;
|
||||
case JAVA_TYPE_INT:
|
||||
result += "_int";
|
||||
break;
|
||||
case JAVA_TYPE_LONG:
|
||||
result += "_long";
|
||||
break;
|
||||
case JAVA_TYPE_FLOAT:
|
||||
result += "_float";
|
||||
break;
|
||||
case JAVA_TYPE_DOUBLE:
|
||||
result += "_double";
|
||||
break;
|
||||
case JAVA_TYPE_STRING:
|
||||
result += "_String";
|
||||
break;
|
||||
default:
|
||||
result += "_UNKNOWN";
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static const char*
|
||||
java_type_signature(java_type_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case JAVA_TYPE_BOOLEAN:
|
||||
return "Z";
|
||||
case JAVA_TYPE_INT:
|
||||
return "I";
|
||||
case JAVA_TYPE_LONG:
|
||||
return "J";
|
||||
case JAVA_TYPE_FLOAT:
|
||||
return "F";
|
||||
case JAVA_TYPE_DOUBLE:
|
||||
return "D";
|
||||
case JAVA_TYPE_STRING:
|
||||
return "Ljava/lang/String;";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
static string
|
||||
jni_function_signature(const vector<java_type_t>& signature)
|
||||
{
|
||||
string result("(I");
|
||||
for (vector<java_type_t>::const_iterator arg = signature.begin();
|
||||
arg != signature.end(); arg++) {
|
||||
result += java_type_signature(*arg);
|
||||
}
|
||||
result += ")V";
|
||||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
write_stats_log_jni(FILE* out, const Atoms& atoms)
|
||||
{
|
||||
int errorCount;
|
||||
|
||||
// Print prelude
|
||||
fprintf(out, "// This file is autogenerated\n");
|
||||
fprintf(out, "\n");
|
||||
|
||||
fprintf(out, "#include <statslog.h>\n");
|
||||
fprintf(out, "\n");
|
||||
fprintf(out, "#include <nativehelper/JNIHelp.h>\n");
|
||||
fprintf(out, "#include \"core_jni_helpers.h\"\n");
|
||||
fprintf(out, "#include \"jni.h\"\n");
|
||||
fprintf(out, "\n");
|
||||
fprintf(out, "#define UNUSED __attribute__((__unused__))\n");
|
||||
fprintf(out, "\n");
|
||||
|
||||
fprintf(out, "namespace android {\n");
|
||||
fprintf(out, "\n");
|
||||
|
||||
// Print write methods
|
||||
for (set<vector<java_type_t>>::const_iterator signature = atoms.signatures.begin();
|
||||
signature != atoms.signatures.end(); signature++) {
|
||||
int argIndex;
|
||||
|
||||
fprintf(out, "static void\n");
|
||||
fprintf(out, "%s(JNIEnv* env, jobject clazz UNUSED, jint code",
|
||||
jni_function_name(*signature).c_str());
|
||||
argIndex = 1;
|
||||
for (vector<java_type_t>::const_iterator arg = signature->begin();
|
||||
arg != signature->end(); arg++) {
|
||||
fprintf(out, ", %s arg%d", jni_type_name(*arg), argIndex);
|
||||
argIndex++;
|
||||
}
|
||||
fprintf(out, ")\n");
|
||||
|
||||
fprintf(out, "{\n");
|
||||
|
||||
// Prepare strings
|
||||
argIndex = 1;
|
||||
bool hadString = false;
|
||||
for (vector<java_type_t>::const_iterator arg = signature->begin();
|
||||
arg != signature->end(); arg++) {
|
||||
if (*arg == JAVA_TYPE_STRING) {
|
||||
fprintf(out, " const char* str%d;\n", argIndex);
|
||||
fprintf(out, " if (arg%d != NULL) {\n", argIndex);
|
||||
fprintf(out, " str%d = env->GetStringUTFChars(arg%d, NULL);\n",
|
||||
argIndex, argIndex);
|
||||
fprintf(out, " } else {\n");
|
||||
fprintf(out, " str%d = NULL;\n", argIndex);
|
||||
fprintf(out, " }\n");
|
||||
hadString = true;
|
||||
}
|
||||
argIndex++;
|
||||
}
|
||||
|
||||
// Emit this to quiet the unused parameter warning if there were no strings.
|
||||
if (!hadString) {
|
||||
fprintf(out, " (void)env;\n");
|
||||
}
|
||||
|
||||
// stats_write call
|
||||
argIndex = 1;
|
||||
fprintf(out, " android::util::stats_write(code");
|
||||
for (vector<java_type_t>::const_iterator arg = signature->begin();
|
||||
arg != signature->end(); arg++) {
|
||||
const char* argName = (*arg == JAVA_TYPE_STRING) ? "str" : "arg";
|
||||
fprintf(out, ", (%s)%s%d", cpp_type_name(*arg), argName, argIndex);
|
||||
argIndex++;
|
||||
}
|
||||
fprintf(out, ");\n");
|
||||
|
||||
// Clean up strings
|
||||
argIndex = 1;
|
||||
for (vector<java_type_t>::const_iterator arg = signature->begin();
|
||||
arg != signature->end(); arg++) {
|
||||
if (*arg == JAVA_TYPE_STRING) {
|
||||
fprintf(out, " if (str%d != NULL) {\n", argIndex);
|
||||
fprintf(out, " env->ReleaseStringUTFChars(arg%d, str%d);\n",
|
||||
argIndex, argIndex);
|
||||
fprintf(out, " }\n");
|
||||
}
|
||||
argIndex++;
|
||||
}
|
||||
|
||||
fprintf(out, "}\n");
|
||||
fprintf(out, "\n");
|
||||
}
|
||||
|
||||
// Print registration function table
|
||||
fprintf(out, "/*\n");
|
||||
fprintf(out, " * JNI registration.\n");
|
||||
fprintf(out, " */\n");
|
||||
fprintf(out, "static const JNINativeMethod gRegisterMethods[] = {\n");
|
||||
for (set<vector<java_type_t>>::const_iterator signature = atoms.signatures.begin();
|
||||
signature != atoms.signatures.end(); signature++) {
|
||||
fprintf(out, " { \"write\", \"%s\", (void*)%s },\n",
|
||||
jni_function_signature(*signature).c_str(),
|
||||
jni_function_name(*signature).c_str());
|
||||
}
|
||||
fprintf(out, "};\n");
|
||||
fprintf(out, "\n");
|
||||
|
||||
// Print registration function
|
||||
fprintf(out, "int register_android_util_StatsLog(JNIEnv* env) {\n");
|
||||
fprintf(out, " return RegisterMethodsOrDie(\n");
|
||||
fprintf(out, " env,\n");
|
||||
fprintf(out, " \"android/util/StatsLog\",\n");
|
||||
fprintf(out, " gRegisterMethods, NELEM(gRegisterMethods));\n");
|
||||
fprintf(out, "}\n");
|
||||
|
||||
fprintf(out, "\n");
|
||||
fprintf(out, "} // namespace android\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
print_usage()
|
||||
{
|
||||
fprintf(stderr, "usage: stats-log-api-gen OPTIONS\n");
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "OPTIONS\n");
|
||||
fprintf(stderr, " --cpp FILENAME the header file to output\n");
|
||||
fprintf(stderr, " --header FILENAME the cpp file to output\n");
|
||||
fprintf(stderr, " --help this message\n");
|
||||
fprintf(stderr, " --java FILENAME the java file to output\n");
|
||||
fprintf(stderr, " --jni FILENAME the jni file to output\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Do the argument parsing and execute the tasks.
|
||||
*/
|
||||
static int
|
||||
run(int argc, char const*const* argv)
|
||||
{
|
||||
string cppFilename;
|
||||
string headerFilename;
|
||||
string javaFilename;
|
||||
string jniFilename;
|
||||
|
||||
int index = 1;
|
||||
while (index < argc) {
|
||||
if (0 == strcmp("--help", argv[index])) {
|
||||
print_usage();
|
||||
return 0;
|
||||
} else if (0 == strcmp("--cpp", argv[index])) {
|
||||
index++;
|
||||
if (index >= argc) {
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
cppFilename = argv[index];
|
||||
} else if (0 == strcmp("--header", argv[index])) {
|
||||
index++;
|
||||
if (index >= argc) {
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
headerFilename = argv[index];
|
||||
} else if (0 == strcmp("--java", argv[index])) {
|
||||
index++;
|
||||
if (index >= argc) {
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
javaFilename = argv[index];
|
||||
} else if (0 == strcmp("--jni", argv[index])) {
|
||||
index++;
|
||||
if (index >= argc) {
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
jniFilename = argv[index];
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
if (cppFilename.size() == 0
|
||||
&& headerFilename.size() == 0
|
||||
&& javaFilename.size() == 0
|
||||
&& jniFilename.size() == 0) {
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Collate the parameters
|
||||
Atoms atoms;
|
||||
int errorCount = collate_atoms(StatsEvent::descriptor(), &atoms);
|
||||
if (errorCount != 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Write the .cpp file
|
||||
if (cppFilename.size() != 0) {
|
||||
FILE* out = fopen(cppFilename.c_str(), "w");
|
||||
if (out == NULL) {
|
||||
fprintf(stderr, "Unable to open file for write: %s\n", cppFilename.c_str());
|
||||
return 1;
|
||||
}
|
||||
errorCount = android::stats_log_api_gen::write_stats_log_cpp(out, atoms);
|
||||
fclose(out);
|
||||
}
|
||||
|
||||
// Write the .h file
|
||||
if (headerFilename.size() != 0) {
|
||||
FILE* out = fopen(headerFilename.c_str(), "w");
|
||||
if (out == NULL) {
|
||||
fprintf(stderr, "Unable to open file for write: %s\n", headerFilename.c_str());
|
||||
return 1;
|
||||
}
|
||||
errorCount = android::stats_log_api_gen::write_stats_log_header(out, atoms);
|
||||
fclose(out);
|
||||
}
|
||||
|
||||
// Write the .java file
|
||||
if (javaFilename.size() != 0) {
|
||||
FILE* out = fopen(javaFilename.c_str(), "w");
|
||||
if (out == NULL) {
|
||||
fprintf(stderr, "Unable to open file for write: %s\n", javaFilename.c_str());
|
||||
return 1;
|
||||
}
|
||||
errorCount = android::stats_log_api_gen::write_stats_log_java(out, atoms);
|
||||
fclose(out);
|
||||
}
|
||||
|
||||
// Write the jni file
|
||||
if (jniFilename.size() != 0) {
|
||||
FILE* out = fopen(jniFilename.c_str(), "w");
|
||||
if (out == NULL) {
|
||||
fprintf(stderr, "Unable to open file for write: %s\n", jniFilename.c_str());
|
||||
return 1;
|
||||
}
|
||||
errorCount = android::stats_log_api_gen::write_stats_log_jni(out, atoms);
|
||||
fclose(out);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Main.
|
||||
*/
|
||||
int
|
||||
main(int argc, char const*const* argv)
|
||||
{
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
|
||||
return android::stats_log_api_gen::run(argc, argv);
|
||||
}
|
||||
112
tools/stats_log_api_gen/test.proto
Normal file
112
tools/stats_log_api_gen/test.proto
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
import "frameworks/base/cmds/statsd/src/stats_events.proto";
|
||||
|
||||
package android.stats_log_api_gen;
|
||||
|
||||
message IntAtom {
|
||||
optional int32 field1 = 1;
|
||||
}
|
||||
|
||||
message AnotherIntAtom {
|
||||
optional int32 field1 = 1;
|
||||
}
|
||||
|
||||
message OutOfOrderAtom {
|
||||
optional int32 field2 = 2;
|
||||
optional int32 field1 = 1;
|
||||
}
|
||||
|
||||
enum AnEnum {
|
||||
VALUE0 = 0;
|
||||
VALUE1 = 1;
|
||||
}
|
||||
|
||||
message AllTypesAtom {
|
||||
optional android.os.statsd.WorkSource attribution = 1;
|
||||
optional double double_field = 2;
|
||||
optional float float_field = 3;
|
||||
optional int64 int64_field = 4;
|
||||
optional uint64 uint64_field = 5;
|
||||
optional int32 int32_field = 6;
|
||||
optional fixed64 fixed64_field = 7;
|
||||
optional fixed32 fixed32_field = 8;
|
||||
optional bool bool_field = 9;
|
||||
optional string string_field = 10;
|
||||
optional uint32 uint32_field = 11;
|
||||
optional AnEnum enum_field = 12;
|
||||
optional sfixed32 sfixed32_field = 13;
|
||||
optional sfixed64 sfixed64_field = 14;
|
||||
optional sint32 sint32_field = 15;
|
||||
optional sint64 sint64_field = 16;
|
||||
}
|
||||
|
||||
message Event {
|
||||
oneof event {
|
||||
OutOfOrderAtom out_of_order_atom = 2;
|
||||
IntAtom int_atom = 1;
|
||||
AnotherIntAtom another_int_atom = 3;
|
||||
AllTypesAtom all_types_atom = 4;
|
||||
}
|
||||
}
|
||||
|
||||
message BadTypesAtom {
|
||||
optional IntAtom bad_int_atom = 1;
|
||||
optional bytes bad_bytes = 2;
|
||||
}
|
||||
|
||||
message BadTypesEvent {
|
||||
oneof event {
|
||||
BadTypesAtom bad_types_atom = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message BadSkippedFieldSingleAtom {
|
||||
optional int32 field2 = 2;
|
||||
}
|
||||
|
||||
message BadSkippedFieldSingle {
|
||||
oneof event {
|
||||
BadSkippedFieldSingleAtom bad = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message BadSkippedFieldMultipleAtom {
|
||||
optional int32 field1 = 1;
|
||||
optional int32 field3 = 3;
|
||||
optional int32 field5 = 5;
|
||||
}
|
||||
|
||||
message BadSkippedFieldMultiple {
|
||||
oneof event {
|
||||
BadSkippedFieldMultipleAtom bad = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message BadWorkSourcePositionAtom {
|
||||
optional int32 field1 = 1;
|
||||
optional android.os.statsd.WorkSource attribution = 2;
|
||||
}
|
||||
|
||||
message BadWorkSourcePosition {
|
||||
oneof event {
|
||||
BadWorkSourcePositionAtom bad = 1;
|
||||
}
|
||||
}
|
||||
|
||||
171
tools/stats_log_api_gen/test_collation.cpp
Normal file
171
tools/stats_log_api_gen/test_collation.cpp
Normal file
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (C) 2017, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "frameworks/base/tools/stats_log_api_gen/test.pb.h"
|
||||
#include "Collation.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace android {
|
||||
namespace stats_log_api_gen {
|
||||
|
||||
using std::set;
|
||||
using std::vector;
|
||||
|
||||
/**
|
||||
* Return whether the set contains a vector of the elements provided.
|
||||
*/
|
||||
static bool
|
||||
set_contains_vector(const set<vector<java_type_t>>& s, int count, ...)
|
||||
{
|
||||
va_list args;
|
||||
vector<java_type_t> v;
|
||||
|
||||
va_start(args, count);
|
||||
for (int i=0; i<count; i++) {
|
||||
v.push_back((java_type_t)va_arg(args, int));
|
||||
}
|
||||
va_end(args);
|
||||
|
||||
return s.find(v) != s.end();
|
||||
}
|
||||
|
||||
/**
|
||||
* Expect that the provided set contains the elements provided.
|
||||
*/
|
||||
#define EXPECT_SET_CONTAINS_SIGNATURE(s, ...) \
|
||||
do { \
|
||||
int count = sizeof((int[]){__VA_ARGS__})/sizeof(int); \
|
||||
EXPECT_TRUE(set_contains_vector(s, count, __VA_ARGS__)); \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* Test a correct collation, with all the types.
|
||||
*/
|
||||
TEST(CollationTest, CollateStats) {
|
||||
Atoms atoms;
|
||||
int errorCount = collate_atoms(Event::descriptor(), &atoms);
|
||||
|
||||
EXPECT_EQ(0, errorCount);
|
||||
EXPECT_EQ(3ul, atoms.signatures.size());
|
||||
|
||||
// IntAtom, AnotherIntAtom
|
||||
EXPECT_SET_CONTAINS_SIGNATURE(atoms.signatures, JAVA_TYPE_INT);
|
||||
|
||||
// OutOfOrderAtom
|
||||
EXPECT_SET_CONTAINS_SIGNATURE(atoms.signatures, JAVA_TYPE_INT, JAVA_TYPE_INT);
|
||||
|
||||
// AllTypesAtom
|
||||
EXPECT_SET_CONTAINS_SIGNATURE(atoms.signatures,
|
||||
JAVA_TYPE_WORK_SOURCE, // WorkSource
|
||||
JAVA_TYPE_DOUBLE, // double
|
||||
JAVA_TYPE_FLOAT, // float
|
||||
JAVA_TYPE_LONG, // int64
|
||||
JAVA_TYPE_LONG, // uint64
|
||||
JAVA_TYPE_INT, // int32
|
||||
JAVA_TYPE_LONG, // fixed64
|
||||
JAVA_TYPE_INT, // fixed32
|
||||
JAVA_TYPE_BOOLEAN, // bool
|
||||
JAVA_TYPE_STRING, // string
|
||||
JAVA_TYPE_INT, // uint32
|
||||
JAVA_TYPE_INT, // AnEnum
|
||||
JAVA_TYPE_INT, // sfixed32
|
||||
JAVA_TYPE_LONG, // sfixed64
|
||||
JAVA_TYPE_INT, // sint32
|
||||
JAVA_TYPE_LONG // sint64
|
||||
);
|
||||
|
||||
set<AtomDecl>::const_iterator atom = atoms.decls.begin();
|
||||
EXPECT_EQ(1, atom->code);
|
||||
EXPECT_EQ("int_atom", atom->name);
|
||||
EXPECT_EQ("IntAtom", atom->message);
|
||||
atom++;
|
||||
|
||||
EXPECT_EQ(2, atom->code);
|
||||
EXPECT_EQ("out_of_order_atom", atom->name);
|
||||
EXPECT_EQ("OutOfOrderAtom", atom->message);
|
||||
atom++;
|
||||
|
||||
EXPECT_EQ(3, atom->code);
|
||||
EXPECT_EQ("another_int_atom", atom->name);
|
||||
EXPECT_EQ("AnotherIntAtom", atom->message);
|
||||
atom++;
|
||||
|
||||
EXPECT_EQ(4, atom->code);
|
||||
EXPECT_EQ("all_types_atom", atom->name);
|
||||
EXPECT_EQ("AllTypesAtom", atom->message);
|
||||
atom++;
|
||||
|
||||
EXPECT_TRUE(atom == atoms.decls.end());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that event class that contains stuff other than the atoms is rejected.
|
||||
*/
|
||||
TEST(CollationTest, NonMessageTypeFails) {
|
||||
Atoms atoms;
|
||||
int errorCount = collate_atoms(IntAtom::descriptor(), &atoms);
|
||||
|
||||
EXPECT_EQ(1, errorCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that atoms that have non-primitve types are rejected.
|
||||
*/
|
||||
TEST(CollationTest, FailOnBadTypes) {
|
||||
Atoms atoms;
|
||||
int errorCount = collate_atoms(BadTypesEvent::descriptor(), &atoms);
|
||||
|
||||
EXPECT_EQ(2, errorCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that atoms that skip field numbers (in the first position) are rejected.
|
||||
*/
|
||||
TEST(CollationTest, FailOnSkippedFieldsSingle) {
|
||||
Atoms atoms;
|
||||
int errorCount = collate_atoms(BadSkippedFieldSingle::descriptor(), &atoms);
|
||||
|
||||
EXPECT_EQ(1, errorCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that atoms that skip field numbers (not in the first position, and multiple
|
||||
* times) are rejected.
|
||||
*/
|
||||
TEST(CollationTest, FailOnSkippedFieldsMultiple) {
|
||||
Atoms atoms;
|
||||
int errorCount = collate_atoms(BadSkippedFieldMultiple::descriptor(), &atoms);
|
||||
|
||||
EXPECT_EQ(2, errorCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that atoms that have a WorkSource not in the first position are rejected.
|
||||
*/
|
||||
TEST(CollationTest, FailBadWorkSourcePosition) {
|
||||
Atoms atoms;
|
||||
int errorCount = collate_atoms(BadWorkSourcePosition::descriptor(), &atoms);
|
||||
|
||||
EXPECT_EQ(1, errorCount);
|
||||
}
|
||||
|
||||
|
||||
} // namespace stats_log_api_gen
|
||||
} // namespace android
|
||||
|
||||
Reference in New Issue
Block a user