Merge "Add annotation to atoms that represent a state change in atoms.proto"

This commit is contained in:
TreeHugger Robot
2018-02-22 05:36:45 +00:00
committed by Android (Google) Code Review
39 changed files with 537 additions and 265 deletions

View File

@@ -21,6 +21,7 @@ cc_library_host_shared {
name: "libstats_proto_host",
srcs: [
"src/atoms.proto",
"src/atom_field_options.proto",
],
shared_libs: [
@@ -30,6 +31,9 @@ cc_library_host_shared {
proto: {
type: "full",
export_proto_headers: true,
include_dirs: [
"external/protobuf/src",
],
},
export_shared_lib_headers: [

View File

@@ -17,9 +17,8 @@ LOCAL_PATH:= $(call my-dir)
statsd_common_src := \
../../core/java/android/os/IStatsCompanionService.aidl \
../../core/java/android/os/IStatsManager.aidl \
src/stats_log.proto \
src/stats_log_common.proto \
src/statsd_config.proto \
src/atoms.proto \
src/FieldValue.cpp \
src/stats_log_util.cpp \
src/anomaly/AnomalyMonitor.cpp \
@@ -168,6 +167,9 @@ LOCAL_CFLAGS += \
LOCAL_SRC_FILES := \
$(statsd_common_src) \
src/atom_field_options.proto \
src/atoms.proto \
src/stats_log.proto \
tests/AnomalyMonitor_test.cpp \
tests/anomaly/AnomalyTracker_test.cpp \
tests/ConfigManager_test.cpp \
@@ -202,9 +204,13 @@ LOCAL_STATIC_LIBRARIES := \
$(statsd_common_static_libraries) \
libgmock
LOCAL_SHARED_LIBRARIES := $(statsd_common_shared_libraries)
LOCAL_PROTOC_OPTIMIZE_TYPE := full
LOCAL_PROTOC_OPTIMIZE_TYPE := lite
LOCAL_PROTOC_FLAGS := \
-Iexternal/protobuf/src
LOCAL_SHARED_LIBRARIES := $(statsd_common_shared_libraries) \
libprotobuf-cpp-full
include $(BUILD_NATIVE_TEST)
@@ -217,6 +223,7 @@ LOCAL_MODULE := statsdprotolite
LOCAL_SRC_FILES := \
src/stats_log.proto \
src/stats_log_common.proto \
src/statsd_config.proto \
src/perfetto/perfetto_config.proto \
src/atoms.proto
@@ -226,6 +233,9 @@ LOCAL_PROTOC_OPTIMIZE_TYPE := lite
LOCAL_STATIC_JAVA_LIBRARIES := \
platformprotoslite
LOCAL_PROTOC_FLAGS := \
-Iexternal/protobuf/src
include $(BUILD_STATIC_JAVA_LIBRARY)
##############################
@@ -261,8 +271,6 @@ LOCAL_SHARED_LIBRARIES := $(statsd_common_shared_libraries) \
libgtest_prod \
libstatslog
LOCAL_PROTOC_OPTIMIZE_TYPE := lite
LOCAL_MODULE_TAGS := eng tests
include $(BUILD_NATIVE_BENCHMARK)

View File

@@ -22,6 +22,8 @@
namespace android {
namespace os {
namespace statsd {
using std::string;
using std::vector;
android::hash_t hashDimension(const HashableDimensionKey& value) {

View File

@@ -0,0 +1,70 @@
/*
* Copyright (C) 2018 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";
package android.os.statsd;
option java_package = "com.android.os";
option java_multiple_files = true;
option java_outer_classname = "AtomFieldOptions";
import "google/protobuf/descriptor.proto";
enum StateField {
// Default value for fields that are not primary or exclusive state.
STATE_FIELD_UNSET = 0;
// Fields that represent the key that the state belongs to.
PRIMARY = 1;
// The field that represents the state. It's an exclusive state.
EXCLUSIVE = 2;
}
// Used to annotate an atom that reprsents a state change. A state change atom must have exactly ONE
// exclusive state field, and any number of primary key fields.
// For example,
// message UidProcessStateChanged {
// optional int32 uid = 1 [(stateFieldOption).option = PRIMARY];
// optional android.app.ProcessStateEnum state = 2 [(stateFieldOption).option = EXCLUSIVE];
// }
// Each of this UidProcessStateChanged atom represents a state change for a specific uid.
// A new state automatically overrides the previous state.
//
// If the atom has 2 or more primary fields, it means the combination of the primary fields are
// the primary key.
// For example:
// message ThreadStateChanged {
// optional int32 pid = 1 [(stateFieldOption).option = PRIMARY];
// optional int32 tid = 2 [(stateFieldOption).option = PRIMARY];
// optional int32 state = 3 [(stateFieldOption).option = EXCLUSIVE];
// }
//
// Sometimes, there is no primary key field, when the state is GLOBAL.
// For example,
//
// message ScreenStateChanged {
// optional android.view.DisplayStateEnum state = 1 [(stateFieldOption).option = EXCLUSIVE];
// }
//
// Only fields of primary types can be annotated. AttributionNode cannot be primary keys (and they
// usually are not).
message StateAtomFieldOption {
optional StateField option = 1 [default = STATE_FIELD_UNSET];
}
extend google.protobuf.FieldOptions {
// Flags to decorate an atom that presents a state change.
optional StateAtomFieldOption stateFieldOption = 50000;
}

View File

@@ -21,6 +21,7 @@ package android.os.statsd;
option java_package = "com.android.os";
option java_outer_classname = "AtomsProto";
import "frameworks/base/cmds/statsd/src/atom_field_options.proto";
import "frameworks/base/core/proto/android/app/enums.proto";
import "frameworks/base/core/proto/android/os/enums.proto";
import "frameworks/base/core/proto/android/server/enums.proto";
@@ -179,7 +180,7 @@ message AttributionNode {
*/
message ScreenStateChanged {
// New screen state, from frameworks/base/core/proto/android/view/enums.proto.
optional android.view.DisplayStateEnum state = 1;
optional android.view.DisplayStateEnum state = 1 [(stateFieldOption).option = EXCLUSIVE];
}
/**
@@ -189,10 +190,10 @@ message ScreenStateChanged {
* frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java
*/
message UidProcessStateChanged {
optional int32 uid = 1; // TODO: should be a string tagged w/ uid annotation
optional int32 uid = 1 [(stateFieldOption).option = PRIMARY];
// The state, from frameworks/base/core/proto/android/app/enums.proto.
optional android.app.ProcessStateEnum state = 2;
optional android.app.ProcessStateEnum state = 2 [(stateFieldOption).option = EXCLUSIVE];
}
/**
@@ -1514,5 +1515,4 @@ message RemainingBatteryCapacity {
*/
message FullBatteryCapacity {
optional int32 capacity_uAh = 1;
}
}

View File

@@ -16,7 +16,7 @@
#pragma once
#include "config/ConfigKey.h"
#include "frameworks/base/cmds/statsd/src/stats_log.pb.h"
#include "frameworks/base/cmds/statsd/src/stats_log_common.pb.h"
#include "statslog.h"
#include <gtest/gtest_prod.h>

View File

@@ -26,9 +26,10 @@ namespace os {
namespace statsd {
using namespace android::util;
using android::util::ProtoOutputStream;
using std::ostringstream;
using std::string;
using android::util::ProtoOutputStream;
using std::vector;
LogEvent::LogEvent(log_msg& msg) {
mContext =
@@ -130,7 +131,7 @@ bool LogEvent::write(float value) {
return false;
}
bool LogEvent::write(const std::vector<AttributionNode>& nodes) {
bool LogEvent::write(const std::vector<AttributionNodeInternal>& nodes) {
if (mContext) {
if (android_log_write_list_begin(mContext) < 0) {
return false;
@@ -148,7 +149,7 @@ bool LogEvent::write(const std::vector<AttributionNode>& nodes) {
return false;
}
bool LogEvent::write(const AttributionNode& node) {
bool LogEvent::write(const AttributionNodeInternal& node) {
if (mContext) {
if (android_log_write_list_begin(mContext) < 0) {
return false;

View File

@@ -17,7 +17,6 @@
#pragma once
#include "FieldValue.h"
#include "frameworks/base/cmds/statsd/src/stats_log.pb.h"
#include <android/util/ProtoOutputStream.h>
#include <log/log_event_list.h>
@@ -32,8 +31,26 @@ namespace android {
namespace os {
namespace statsd {
using std::string;
using std::vector;
struct AttributionNodeInternal {
void set_uid(int32_t id) {
mUid = id;
}
void set_tag(const std::string& value) {
mTag = value;
}
int32_t uid() const {
return mUid;
}
const std::string& tag() const {
return mTag;
}
int32_t mUid;
std::string mTag;
};
/**
* Wrapper for the log_msg structure.
*/
@@ -89,15 +106,15 @@ public:
bool write(int32_t value);
bool write(uint64_t value);
bool write(int64_t value);
bool write(const string& value);
bool write(const std::string& value);
bool write(float value);
bool write(const std::vector<AttributionNode>& nodes);
bool write(const AttributionNode& node);
bool write(const std::vector<AttributionNodeInternal>& nodes);
bool write(const AttributionNodeInternal& node);
/**
* Return a string representation of this event.
*/
string ToString() const;
std::string ToString() const;
/**
* Write this object to a ProtoOutputStream.

View File

@@ -24,10 +24,10 @@
#include <string>
#include <unordered_map>
#include <vector>
#include "frameworks/base/cmds/statsd/src/stats_log.pb.h"
#include "frameworks/base/cmds/statsd/src/stats_log_common.pb.h"
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
#include "stats_util.h"
#include "packages/UidMap.h"
#include "stats_util.h"
namespace android {
namespace os {

View File

@@ -18,7 +18,7 @@
#include "config/ConfigKey.h"
#include "config/ConfigListener.h"
#include "frameworks/base/cmds/statsd/src/stats_log.pb.h"
#include "frameworks/base/cmds/statsd/src/stats_log_common.pb.h"
#include "packages/PackageInfoListener.h"
#include <binder/IResultReceiver.h>

View File

@@ -15,7 +15,6 @@
*/
syntax = "proto2";
option optimize_for = LITE_RUNTIME;
package perfetto.protos;

View File

@@ -15,7 +15,6 @@
*/
syntax = "proto2";
option optimize_for = LITE_RUNTIME;
package android.os.statsd;
@@ -23,6 +22,7 @@ option java_package = "com.android.os";
option java_outer_classname = "StatsLog";
import "frameworks/base/cmds/statsd/src/atoms.proto";
import "frameworks/base/cmds/statsd/src/stats_log_common.proto";
message DimensionsValue {
optional int32 field = 1;
@@ -115,33 +115,6 @@ message GaugeMetricData {
repeated GaugeBucketInfo bucket_info = 3;
}
message UidMapping {
message PackageInfoSnapshot {
message PackageInfo {
optional string name = 1;
optional int64 version = 2;
optional int32 uid = 3;
}
optional int64 elapsed_timestamp_nanos = 1;
repeated PackageInfo package_info = 2;
}
repeated PackageInfoSnapshot snapshots = 1;
message Change {
optional bool deletion = 1;
optional int64 elapsed_timestamp_nanos = 2;
optional string app = 3;
optional int32 uid = 4;
optional int64 version = 5;
}
repeated Change changes = 2;
}
message StatsLogReport {
optional int64 metric_id = 1;
@@ -191,87 +164,4 @@ message ConfigMetricsReportList {
optional ConfigKey config_key = 1;
repeated ConfigMetricsReport reports = 2;
}
message StatsdStatsReport {
optional int32 stats_begin_time_sec = 1;
optional int32 stats_end_time_sec = 2;
message MatcherStats {
optional int64 id = 1;
optional int32 matched_times = 2;
}
message ConditionStats {
optional int64 id = 1;
optional int32 max_tuple_counts = 2;
}
message MetricStats {
optional int64 id = 1;
optional int32 max_tuple_counts = 2;
}
message AlertStats {
optional int64 id = 1;
optional int32 alerted_times = 2;
}
message ConfigStats {
optional int32 uid = 1;
optional int64 id = 2;
optional int32 creation_time_sec = 3;
optional int32 deletion_time_sec = 4;
optional int32 metric_count = 5;
optional int32 condition_count = 6;
optional int32 matcher_count = 7;
optional int32 alert_count = 8;
optional bool is_valid = 9;
repeated int32 broadcast_sent_time_sec = 10;
repeated int32 data_drop_time_sec = 11;
repeated int32 dump_report_time_sec = 12;
repeated MatcherStats matcher_stats = 13;
repeated ConditionStats condition_stats = 14;
repeated MetricStats metric_stats = 15;
repeated AlertStats alert_stats = 16;
}
repeated ConfigStats config_stats = 3;
message AtomStats {
optional int32 tag = 1;
optional int32 count = 2;
}
repeated AtomStats atom_stats = 7;
message UidMapStats {
optional int32 snapshots = 1;
optional int32 changes = 2;
optional int32 bytes_used = 3;
optional int32 dropped_snapshots = 4;
optional int32 dropped_changes = 5;
}
optional UidMapStats uidmap_stats = 8;
message AnomalyAlarmStats {
optional int32 alarms_registered = 1;
}
optional AnomalyAlarmStats anomaly_alarm_stats = 9;
message PulledAtomStats {
optional int32 atom_id = 1;
optional int64 total_pull = 2;
optional int64 total_pull_from_cache = 3;
optional int64 min_pull_interval_sec = 4;
}
repeated PulledAtomStats pulled_atom_stats = 10;
message LoggerErrorStats {
optional int32 logger_disconnection_sec = 1;
optional int32 error_code = 2;
}
repeated LoggerErrorStats logger_error_stats = 11;
}

View File

@@ -0,0 +1,132 @@
/*
* 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";
package android.os.statsd;
option java_package = "com.android.os";
option java_outer_classname = "StatsLogCommon";
message UidMapping {
message PackageInfoSnapshot {
message PackageInfo {
optional string name = 1;
optional int64 version = 2;
optional int32 uid = 3;
}
optional int64 elapsed_timestamp_nanos = 1;
repeated PackageInfo package_info = 2;
}
repeated PackageInfoSnapshot snapshots = 1;
message Change {
optional bool deletion = 1;
optional int64 elapsed_timestamp_nanos = 2;
optional string app = 3;
optional int32 uid = 4;
optional int64 version = 5;
}
repeated Change changes = 2;
}
message StatsdStatsReport {
optional int32 stats_begin_time_sec = 1;
optional int32 stats_end_time_sec = 2;
message MatcherStats {
optional int64 id = 1;
optional int32 matched_times = 2;
}
message ConditionStats {
optional int64 id = 1;
optional int32 max_tuple_counts = 2;
}
message MetricStats {
optional int64 id = 1;
optional int32 max_tuple_counts = 2;
}
message AlertStats {
optional int64 id = 1;
optional int32 alerted_times = 2;
}
message ConfigStats {
optional int32 uid = 1;
optional int64 id = 2;
optional int32 creation_time_sec = 3;
optional int32 deletion_time_sec = 4;
optional int32 metric_count = 5;
optional int32 condition_count = 6;
optional int32 matcher_count = 7;
optional int32 alert_count = 8;
optional bool is_valid = 9;
repeated int32 broadcast_sent_time_sec = 10;
repeated int32 data_drop_time_sec = 11;
repeated int32 dump_report_time_sec = 12;
repeated MatcherStats matcher_stats = 13;
repeated ConditionStats condition_stats = 14;
repeated MetricStats metric_stats = 15;
repeated AlertStats alert_stats = 16;
}
repeated ConfigStats config_stats = 3;
message AtomStats {
optional int32 tag = 1;
optional int32 count = 2;
}
repeated AtomStats atom_stats = 7;
message UidMapStats {
optional int32 snapshots = 1;
optional int32 changes = 2;
optional int32 bytes_used = 3;
optional int32 dropped_snapshots = 4;
optional int32 dropped_changes = 5;
}
optional UidMapStats uidmap_stats = 8;
message AnomalyAlarmStats {
optional int32 alarms_registered = 1;
}
optional AnomalyAlarmStats anomaly_alarm_stats = 9;
message PulledAtomStats {
optional int32 atom_id = 1;
optional int64 total_pull = 2;
optional int64 total_pull_from_cache = 3;
optional int64 min_pull_interval_sec = 4;
}
repeated PulledAtomStats pulled_atom_stats = 10;
message LoggerErrorStats {
optional int32 logger_disconnection_sec = 1;
optional int32 error_code = 2;
}
repeated LoggerErrorStats logger_error_stats = 11;
}

View File

@@ -19,7 +19,7 @@
#include <android/util/ProtoOutputStream.h>
#include "FieldValue.h"
#include "HashableDimensionKey.h"
#include "frameworks/base/cmds/statsd/src/stats_log.pb.h"
#include "frameworks/base/cmds/statsd/src/stats_log_common.pb.h"
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
#include "guardrail/StatsdStats.h"

View File

@@ -18,7 +18,7 @@
#include <sstream>
#include "HashableDimensionKey.h"
#include "frameworks/base/cmds/statsd/src/stats_log.pb.h"
#include "frameworks/base/cmds/statsd/src/stats_log_common.pb.h"
#include "logd/LogReader.h"
#include <unordered_map>

View File

@@ -15,7 +15,6 @@
*/
syntax = "proto2";
option optimize_for = LITE_RUNTIME;
package android.os.statsd;

View File

@@ -27,6 +27,8 @@ namespace android {
namespace os {
namespace statsd {
using std::vector;
void SubscriberReporter::setBroadcastSubscriber(const ConfigKey& configKey,
int64_t subscriberId,
const sp<IBinder>& intentSender) {

View File

@@ -21,7 +21,6 @@
#include "config/ConfigKey.h"
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" // subscription
#include "frameworks/base/cmds/statsd/src/stats_log.pb.h" // DimensionsValue
#include "android/os/StatsDimensionsValue.h"
#include "HashableDimensionKey.h"

View File

@@ -14,9 +14,10 @@
* limitations under the License.
*/
#include <gtest/gtest.h>
#include "src/logd/LogEvent.h"
#include "frameworks/base/cmds/statsd/src/stats_log.pb.h"
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
#include "matchers/matcher_util.h"
#include "src/logd/LogEvent.h"
#include "stats_log_util.h"
#include "stats_util.h"
#include "subscriber/SubscriberReporter.h"
@@ -64,19 +65,19 @@ TEST(AtomMatcherTest, TestFilter) {
vector<Matcher> matchers;
translateFieldMatcher(matcher1, &matchers);
AttributionNode attribution_node1;
AttributionNodeInternal attribution_node1;
attribution_node1.set_uid(1111);
attribution_node1.set_tag("location1");
AttributionNode attribution_node2;
AttributionNodeInternal attribution_node2;
attribution_node2.set_uid(2222);
attribution_node2.set_tag("location2");
AttributionNode attribution_node3;
AttributionNodeInternal attribution_node3;
attribution_node3.set_uid(3333);
attribution_node3.set_tag("location3");
std::vector<AttributionNode> attribution_nodes = {attribution_node1, attribution_node2,
attribution_node3};
std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2,
attribution_node3};
// Set up the event
LogEvent event(10, 12345);
@@ -154,19 +155,19 @@ TEST(AtomMatcherTest, TestSubDimension) {
}
TEST(AtomMatcherTest, TestMetric2ConditionLink) {
AttributionNode attribution_node1;
AttributionNodeInternal attribution_node1;
attribution_node1.set_uid(1111);
attribution_node1.set_tag("location1");
AttributionNode attribution_node2;
AttributionNodeInternal attribution_node2;
attribution_node2.set_uid(2222);
attribution_node2.set_tag("location2");
AttributionNode attribution_node3;
AttributionNodeInternal attribution_node3;
attribution_node3.set_uid(3333);
attribution_node3.set_tag("location3");
std::vector<AttributionNode> attribution_nodes = {attribution_node1, attribution_node2,
attribution_node3};
std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2,
attribution_node3};
// Set up the event
LogEvent event(10, 12345);
@@ -298,15 +299,15 @@ TEST(AtomMatcherTest, TestWriteDimensionToProto) {
}
TEST(AtomMatcherTest, TestWriteAtomToProto) {
AttributionNode attribution_node1;
AttributionNodeInternal attribution_node1;
attribution_node1.set_uid(1111);
attribution_node1.set_tag("location1");
AttributionNode attribution_node2;
AttributionNodeInternal attribution_node2;
attribution_node2.set_uid(2222);
attribution_node2.set_tag("location2");
std::vector<AttributionNode> attribution_nodes = {attribution_node1, attribution_node2};
std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2};
// Set up the event
LogEvent event(4, 12345);

View File

@@ -60,19 +60,19 @@ TEST(AtomMatcherTest, TestSimpleMatcher) {
TEST(AtomMatcherTest, TestAttributionMatcher) {
UidMap uidMap;
AttributionNode attribution_node1;
AttributionNodeInternal attribution_node1;
attribution_node1.set_uid(1111);
attribution_node1.set_tag("location1");
AttributionNode attribution_node2;
AttributionNodeInternal attribution_node2;
attribution_node2.set_uid(2222);
attribution_node2.set_tag("location2");
AttributionNode attribution_node3;
AttributionNodeInternal attribution_node3;
attribution_node3.set_uid(3333);
attribution_node3.set_tag("location3");
std::vector<AttributionNode> attribution_nodes =
{ attribution_node1, attribution_node2, attribution_node3 };
std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2,
attribution_node3};
// Set up the event
LogEvent event(TAG_ID, 0);

View File

@@ -25,14 +25,14 @@ namespace statsd {
TEST(LogEventTest, TestLogParsing) {
LogEvent event1(1, 2000);
std::vector<AttributionNode> nodes;
std::vector<AttributionNodeInternal> nodes;
AttributionNode node1;
AttributionNodeInternal node1;
node1.set_uid(1000);
node1.set_tag("tag1");
nodes.push_back(node1);
AttributionNode node2;
AttributionNodeInternal node2;
node2.set_uid(2000);
node2.set_tag("tag2");
nodes.push_back(node2);
@@ -92,17 +92,17 @@ TEST(LogEventTest, TestLogParsing) {
TEST(LogEventTest, TestLogParsing2) {
LogEvent event1(1, 2000);
std::vector<AttributionNode> nodes;
std::vector<AttributionNodeInternal> nodes;
event1.write("hello");
// repeated msg can be in the middle
AttributionNode node1;
AttributionNodeInternal node1;
node1.set_uid(1000);
node1.set_tag("tag1");
nodes.push_back(node1);
AttributionNode node2;
AttributionNodeInternal node2;
node2.set_uid(2000);
node2.set_tag("tag2");
nodes.push_back(node2);

View File

@@ -58,9 +58,9 @@ SimplePredicate getWakeLockHeldCondition(bool countNesting, bool defaultFalse,
}
void writeAttributionNodesToEvent(LogEvent* event, const std::vector<int> &uids) {
std::vector<AttributionNode> nodes;
std::vector<AttributionNodeInternal> nodes;
for (size_t i = 0; i < uids.size(); ++i) {
AttributionNode node;
AttributionNodeInternal node;
node.set_uid(uids[i]);
nodes.push_back(node);
}

View File

@@ -75,41 +75,40 @@ TEST(AttributionE2eTest, TestAttributionMatchAndSlice) {
android::String16("APP3"), 333 /* uid */, 2 /* version code*/);
// GMS core node is in the middle.
std::vector<AttributionNode> attributions1 =
{CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"),
CreateAttribution(333, "App3")};
std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"),
CreateAttribution(222, "GMSCoreModule1"),
CreateAttribution(333, "App3")};
// GMS core node is the last one.
std::vector<AttributionNode> attributions2 =
{CreateAttribution(111, "App1"), CreateAttribution(333, "App3"),
CreateAttribution(222, "GMSCoreModule1")};
std::vector<AttributionNodeInternal> attributions2 = {CreateAttribution(111, "App1"),
CreateAttribution(333, "App3"),
CreateAttribution(222, "GMSCoreModule1")};
// GMS core node is the first one.
std::vector<AttributionNode> attributions3 =
{CreateAttribution(222, "GMSCoreModule1"), CreateAttribution(333, "App3")};
std::vector<AttributionNodeInternal> attributions3 = {CreateAttribution(222, "GMSCoreModule1"),
CreateAttribution(333, "App3")};
// Single GMS core node.
std::vector<AttributionNode> attributions4 =
{CreateAttribution(222, "GMSCoreModule1")};
std::vector<AttributionNodeInternal> attributions4 = {CreateAttribution(222, "GMSCoreModule1")};
// GMS core has another uid.
std::vector<AttributionNode> attributions5 =
{CreateAttribution(111, "App1"), CreateAttribution(444, "GMSCoreModule2"),
CreateAttribution(333, "App3")};
std::vector<AttributionNodeInternal> attributions5 = {CreateAttribution(111, "App1"),
CreateAttribution(444, "GMSCoreModule2"),
CreateAttribution(333, "App3")};
// Multiple GMS core nodes.
std::vector<AttributionNode> attributions6 =
{CreateAttribution(444, "GMSCoreModule2"), CreateAttribution(222, "GMSCoreModule1")};
std::vector<AttributionNodeInternal> attributions6 = {CreateAttribution(444, "GMSCoreModule2"),
CreateAttribution(222, "GMSCoreModule1")};
// No GMS core nodes.
std::vector<AttributionNode> attributions7 =
{CreateAttribution(111, "App1"), CreateAttribution(333, "App3")};
std::vector<AttributionNode> attributions8 = {CreateAttribution(111, "App1")};
std::vector<AttributionNodeInternal> attributions7 = {CreateAttribution(111, "App1"),
CreateAttribution(333, "App3")};
std::vector<AttributionNodeInternal> attributions8 = {CreateAttribution(111, "App1")};
// GMS core node with isolated uid.
const int isolatedUid = 666;
std::vector<AttributionNode> attributions9 =
{CreateAttribution(isolatedUid, "GMSCoreModule3")};
std::vector<AttributionNodeInternal> attributions9 = {
CreateAttribution(isolatedUid, "GMSCoreModule3")};
std::vector<std::unique_ptr<LogEvent>> events;
// Events 1~4 are in the 1st bucket.

View File

@@ -78,13 +78,13 @@ TEST(DimensionInConditionE2eTest, TestCountMetricNoLink) {
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
std::vector<AttributionNode> attributions1 = {CreateAttribution(111, "App1"),
CreateAttribution(222, "GMSCoreModule1"),
CreateAttribution(222, "GMSCoreModule2")};
std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"),
CreateAttribution(222, "GMSCoreModule1"),
CreateAttribution(222, "GMSCoreModule2")};
std::vector<AttributionNode> attributions2 = {CreateAttribution(333, "App2"),
CreateAttribution(222, "GMSCoreModule1"),
CreateAttribution(555, "GMSCoreModule2")};
std::vector<AttributionNodeInternal> attributions2 = {CreateAttribution(333, "App2"),
CreateAttribution(222, "GMSCoreModule1"),
CreateAttribution(555, "GMSCoreModule2")};
std::vector<std::unique_ptr<LogEvent>> events;
events.push_back(
@@ -284,13 +284,13 @@ TEST(DimensionInConditionE2eTest, TestCountMetricWithLink) {
auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
std::vector<AttributionNode> attributions1 = {CreateAttribution(111, "App1"),
CreateAttribution(222, "GMSCoreModule1"),
CreateAttribution(222, "GMSCoreModule2")};
std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"),
CreateAttribution(222, "GMSCoreModule1"),
CreateAttribution(222, "GMSCoreModule2")};
std::vector<AttributionNode> attributions2 = {CreateAttribution(333, "App2"),
CreateAttribution(222, "GMSCoreModule1"),
CreateAttribution(555, "GMSCoreModule2")};
std::vector<AttributionNodeInternal> attributions2 = {CreateAttribution(333, "App2"),
CreateAttribution(222, "GMSCoreModule1"),
CreateAttribution(555, "GMSCoreModule2")};
std::vector<std::unique_ptr<LogEvent>> events;
@@ -464,13 +464,13 @@ TEST(DimensionInConditionE2eTest, TestDurationMetricNoLink) {
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
std::vector<AttributionNode> attributions1 = {CreateAttribution(111, "App1"),
CreateAttribution(222, "GMSCoreModule1"),
CreateAttribution(222, "GMSCoreModule2")};
std::vector<AttributionNodeInternal> attributions1 = {
CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"),
CreateAttribution(222, "GMSCoreModule2")};
std::vector<AttributionNode> attributions2 = {CreateAttribution(333, "App2"),
CreateAttribution(222, "GMSCoreModule1"),
CreateAttribution(555, "GMSCoreModule2")};
std::vector<AttributionNodeInternal> attributions2 = {
CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"),
CreateAttribution(555, "GMSCoreModule2")};
std::vector<std::unique_ptr<LogEvent>> events;
@@ -629,13 +629,13 @@ TEST(DimensionInConditionE2eTest, TestDurationMetricWithLink) {
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
std::vector<AttributionNode> attributions1 = {CreateAttribution(111, "App1"),
CreateAttribution(222, "GMSCoreModule1"),
CreateAttribution(222, "GMSCoreModule2")};
std::vector<AttributionNodeInternal> attributions1 = {
CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1"),
CreateAttribution(222, "GMSCoreModule2")};
std::vector<AttributionNode> attributions2 = {CreateAttribution(333, "App2"),
CreateAttribution(222, "GMSCoreModule1"),
CreateAttribution(555, "GMSCoreModule2")};
std::vector<AttributionNodeInternal> attributions2 = {
CreateAttribution(333, "App2"), CreateAttribution(222, "GMSCoreModule1"),
CreateAttribution(555, "GMSCoreModule2")};
std::vector<std::unique_ptr<LogEvent>> events;

View File

@@ -134,8 +134,8 @@ TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks1) {
CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
bucketStartTimeNs + 2 * bucketSizeNs - 100);
std::vector<AttributionNode> attributions =
{CreateAttribution(appUid, "App1"), CreateAttribution(appUid + 1, "GMSCoreModule1")};
std::vector<AttributionNodeInternal> attributions = {
CreateAttribution(appUid, "App1"), CreateAttribution(appUid + 1, "GMSCoreModule1")};
auto syncOnEvent1 =
CreateSyncStartEvent(attributions, "ReadEmail", bucketStartTimeNs + 50);
auto syncOffEvent1 =
@@ -249,8 +249,8 @@ TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks2) {
CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
bucketStartTimeNs + 2 * bucketSizeNs - 100);
std::vector<AttributionNode> attributions = {CreateAttribution(appUid, "App1"),
CreateAttribution(appUid + 1, "GMSCoreModule1")};
std::vector<AttributionNodeInternal> attributions = {
CreateAttribution(appUid, "App1"), CreateAttribution(appUid + 1, "GMSCoreModule1")};
auto syncOnEvent1 = CreateSyncStartEvent(attributions, "ReadEmail", bucketStartTimeNs + 50);
auto syncOffEvent1 =
CreateSyncEndEvent(attributions, "ReadEmail", bucketStartTimeNs + bucketSizeNs + 300);

View File

@@ -60,13 +60,13 @@ StatsdConfig CreateStatsdConfig(DurationMetric::AggregationType aggregationType)
return config;
}
std::vector<AttributionNode> attributions1 = {CreateAttribution(111, "App1"),
CreateAttribution(222, "GMSCoreModule1"),
CreateAttribution(222, "GMSCoreModule2")};
std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"),
CreateAttribution(222, "GMSCoreModule1"),
CreateAttribution(222, "GMSCoreModule2")};
std::vector<AttributionNode> attributions2 = {CreateAttribution(111, "App2"),
CreateAttribution(222, "GMSCoreModule1"),
CreateAttribution(222, "GMSCoreModule2")};
std::vector<AttributionNodeInternal> attributions2 = {CreateAttribution(111, "App2"),
CreateAttribution(222, "GMSCoreModule1"),
CreateAttribution(222, "GMSCoreModule2")};
/*
Events:

View File

@@ -291,8 +291,8 @@ std::unique_ptr<LogEvent> CreateScreenBrightnessChangedEvent(
}
std::unique_ptr<LogEvent> CreateWakelockStateChangedEvent(
const std::vector<AttributionNode>& attributions, const string& wakelockName,
const WakelockStateChanged::State state, uint64_t timestampNs) {
const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
const WakelockStateChanged::State state, uint64_t timestampNs) {
auto event = std::make_unique<LogEvent>(android::util::WAKELOCK_STATE_CHANGED, timestampNs);
event->write(attributions);
event->write(android::os::WakeLockLevelEnum::PARTIAL_WAKE_LOCK);
@@ -303,15 +303,15 @@ std::unique_ptr<LogEvent> CreateWakelockStateChangedEvent(
}
std::unique_ptr<LogEvent> CreateAcquireWakelockEvent(
const std::vector<AttributionNode>& attributions,
const string& wakelockName, uint64_t timestampNs) {
const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
uint64_t timestampNs) {
return CreateWakelockStateChangedEvent(
attributions, wakelockName, WakelockStateChanged::ACQUIRE, timestampNs);
}
std::unique_ptr<LogEvent> CreateReleaseWakelockEvent(
const std::vector<AttributionNode>& attributions,
const string& wakelockName, uint64_t timestampNs) {
const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
uint64_t timestampNs) {
return CreateWakelockStateChangedEvent(
attributions, wakelockName, WakelockStateChanged::RELEASE, timestampNs);
}
@@ -339,8 +339,8 @@ std::unique_ptr<LogEvent> CreateMoveToForegroundEvent(const int uid, uint64_t ti
}
std::unique_ptr<LogEvent> CreateSyncStateChangedEvent(
const std::vector<AttributionNode>& attributions,
const string& name, const SyncStateChanged::State state, uint64_t timestampNs) {
const std::vector<AttributionNodeInternal>& attributions, const string& name,
const SyncStateChanged::State state, uint64_t timestampNs) {
auto event = std::make_unique<LogEvent>(android::util::SYNC_STATE_CHANGED, timestampNs);
event->write(attributions);
event->write(name);
@@ -350,12 +350,14 @@ std::unique_ptr<LogEvent> CreateSyncStateChangedEvent(
}
std::unique_ptr<LogEvent> CreateSyncStartEvent(
const std::vector<AttributionNode>& attributions, const string& name, uint64_t timestampNs){
const std::vector<AttributionNodeInternal>& attributions, const string& name,
uint64_t timestampNs) {
return CreateSyncStateChangedEvent(attributions, name, SyncStateChanged::ON, timestampNs);
}
std::unique_ptr<LogEvent> CreateSyncEndEvent(
const std::vector<AttributionNode>& attributions, const string& name, uint64_t timestampNs) {
const std::vector<AttributionNodeInternal>& attributions, const string& name,
uint64_t timestampNs) {
return CreateSyncStateChangedEvent(attributions, name, SyncStateChanged::OFF, timestampNs);
}
@@ -396,8 +398,8 @@ sp<StatsLogProcessor> CreateStatsLogProcessor(const long timeBaseSec, const Stat
return processor;
}
AttributionNode CreateAttribution(const int& uid, const string& tag) {
AttributionNode attribution;
AttributionNodeInternal CreateAttribution(const int& uid, const string& tag) {
AttributionNodeInternal attribution;
attribution.set_uid(uid);
attribution.set_tag(tag);
return attribution;

View File

@@ -15,10 +15,11 @@
#pragma once
#include <gtest/gtest.h>
#include "frameworks/base/cmds/statsd/src/stats_log.pb.h"
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
#include "statslog.h"
#include "src/logd/LogEvent.h"
#include "src/StatsLogProcessor.h"
#include "src/logd/LogEvent.h"
#include "statslog.h"
namespace android {
namespace os {
@@ -119,11 +120,13 @@ std::unique_ptr<LogEvent> CreateMoveToForegroundEvent(const int uid, uint64_t ti
// Create log event when the app sync starts.
std::unique_ptr<LogEvent> CreateSyncStartEvent(
const std::vector<AttributionNode>& attributions, const string& name, uint64_t timestampNs);
const std::vector<AttributionNodeInternal>& attributions, const string& name,
uint64_t timestampNs);
// Create log event when the app sync ends.
std::unique_ptr<LogEvent> CreateSyncEndEvent(
const std::vector<AttributionNode>& attributions, const string& name, uint64_t timestampNs);
const std::vector<AttributionNodeInternal>& attributions, const string& name,
uint64_t timestampNs);
// Create log event when the app sync ends.
std::unique_ptr<LogEvent> CreateAppCrashEvent(
@@ -131,20 +134,20 @@ std::unique_ptr<LogEvent> CreateAppCrashEvent(
// Create log event for acquiring wakelock.
std::unique_ptr<LogEvent> CreateAcquireWakelockEvent(
const std::vector<AttributionNode>& attributions,
const string& wakelockName, uint64_t timestampNs);
const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
uint64_t timestampNs);
// Create log event for releasing wakelock.
std::unique_ptr<LogEvent> CreateReleaseWakelockEvent(
const std::vector<AttributionNode>& attributions,
const string& wakelockName, uint64_t timestampNs);
const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
uint64_t timestampNs);
// Create log event for releasing wakelock.
std::unique_ptr<LogEvent> CreateIsolatedUidChangedEvent(
int isolatedUid, int hostUid, bool is_create, uint64_t timestampNs);
// Helper function to create an AttributionNode proto.
AttributionNode CreateAttribution(const int& uid, const string& tag);
// Helper function to create an AttributionNodeInternal proto.
AttributionNodeInternal CreateAttribution(const int& uid, const string& tag);
// Create a statsd log event processor upon the start time in seconds, config and key.
sp<StatsLogProcessor> CreateStatsLogProcessor(const long timeBaseSec, const StatsdConfig& config,

View File

@@ -16,5 +16,5 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Include the sub-makefiles
#Include the sub-makefiles
include $(call all-makefiles-under,$(LOCAL_PATH))

View File

@@ -24,7 +24,6 @@ LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_STATIC_JAVA_LIBRARIES := platformprotoslite \
statsdprotolite
LOCAL_PROTOC_OPTIMIZE_TYPE := lite
LOCAL_PRIVILEGED_MODULE := true
LOCAL_DEX_PREOPT := false
LOCAL_CERTIFICATE := platform

View File

@@ -19,15 +19,11 @@ include $(CLEAR_VARS)
LOCAL_PACKAGE_NAME := StatsdLoadtest
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_SRC_FILES += ../../src/stats_log.proto \
../../src/atoms.proto \
../../src/perfetto/perfetto_config.proto \
../../src/statsd_config.proto
LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/../../src/
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_STATIC_JAVA_LIBRARIES := platformprotoslite
LOCAL_PROTOC_OPTIMIZE_TYPE := lite
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_STATIC_JAVA_LIBRARIES := platformprotoslite \
statsdprotolite
LOCAL_CERTIFICATE := platform
LOCAL_PRIVILEGED_MODULE := true
LOCAL_DEX_PREOPT := false

View File

@@ -50,7 +50,7 @@ import android.widget.Toast;
import com.android.os.StatsLog.ConfigMetricsReport;
import com.android.os.StatsLog.ConfigMetricsReportList;
import com.android.os.StatsLog.StatsdStatsReport;
import com.android.os.StatsLogCommon.StatsdStatsReport;
import com.android.internal.os.StatsdConfigProto.TimeUnit;
import java.util.ArrayList;

View File

@@ -16,11 +16,8 @@
package com.android.statsd.loadtest;
import android.content.Context;
import android.util.Log;
import com.android.os.StatsLog.StatsdStatsReport;
import com.android.os.StatsLogCommon.StatsdStatsReport;
import com.android.internal.os.StatsdConfigProto.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class StatsdStatsRecorder extends PerfDataRecorder {
private static final String TAG = "loadtest.StatsdStatsRecorder";

View File

@@ -62,10 +62,14 @@ cc_test_host {
shared_libs: [
"libstats_proto_host",
"libprotobuf-cpp-full",
],
proto: {
type: "full",
include_dirs: [
"external/protobuf/src",
],
},
}

View File

@@ -41,12 +41,12 @@ AtomDecl::AtomDecl()
}
AtomDecl::AtomDecl(const AtomDecl& that)
:code(that.code),
name(that.name),
message(that.message),
fields(that.fields)
{
}
: code(that.code),
name(that.name),
message(that.message),
fields(that.fields),
primaryFields(that.primaryFields),
exclusiveField(that.exclusiveField) {}
AtomDecl::AtomDecl(int c, const string& n, const string& m)
:code(c),
@@ -237,6 +237,31 @@ int collate_atom(const Descriptor *atom, AtomDecl *atomDecl,
signature->push_back(javaType);
}
atomDecl->fields.push_back(atField);
if (field->options().GetExtension(os::statsd::stateFieldOption).option() ==
os::statsd::StateField::PRIMARY) {
if (javaType == JAVA_TYPE_UNKNOWN ||
javaType == JAVA_TYPE_ATTRIBUTION_CHAIN ||
javaType == JAVA_TYPE_OBJECT || javaType == JAVA_TYPE_BYTE_ARRAY) {
errorCount++;
}
atomDecl->primaryFields.push_back(it->first);
}
if (field->options().GetExtension(os::statsd::stateFieldOption).option() ==
os::statsd::StateField::EXCLUSIVE) {
if (javaType == JAVA_TYPE_UNKNOWN ||
javaType == JAVA_TYPE_ATTRIBUTION_CHAIN ||
javaType == JAVA_TYPE_OBJECT || javaType == JAVA_TYPE_BYTE_ARRAY) {
errorCount++;
}
if (atomDecl->exclusiveField == 0) {
atomDecl->exclusiveField = it->first;
} else {
errorCount++;
}
}
}
return errorCount;
@@ -318,6 +343,9 @@ int collate_atoms(const Descriptor *descriptor, Atoms *atoms) {
AtomDecl atomDecl(atomField->number(), atomField->name(), atom->name());
vector<java_type_t> signature;
errorCount += collate_atom(atom, &atomDecl, &signature);
if (atomDecl.primaryFields.size() != 0 && atomDecl.exclusiveField == 0) {
errorCount++;
}
atoms->signatures.insert(signature);
atoms->decls.insert(atomDecl);

View File

@@ -81,6 +81,9 @@ struct AtomDecl {
string message;
vector<AtomField> fields;
vector<int> primaryFields;
int exclusiveField = 0;
AtomDecl();
AtomDecl(const AtomDecl& that);
AtomDecl(int code, const string& name, const string& message);

View File

@@ -320,6 +320,7 @@ write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl &attributio
fprintf(out, "\n");
fprintf(out, "#include <stdint.h>\n");
fprintf(out, "#include <vector>\n");
fprintf(out, "#include <map>\n");
fprintf(out, "#include <set>\n");
fprintf(out, "\n");
@@ -412,6 +413,43 @@ write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl &attributio
fprintf(out, "const static int kMaxPushedAtomId = %d;\n\n", maxPushedAtomId);
fprintf(out, "struct StateAtomFieldOptions {\n");
fprintf(out, " std::vector<int> primaryFields;\n");
fprintf(out, " int exclusiveField;\n");
fprintf(out, "\n");
fprintf(out,
" static std::map<int, StateAtomFieldOptions> "
"getStateAtomFieldOptions() {\n");
fprintf(out, " std::map<int, StateAtomFieldOptions> options;\n");
fprintf(out, " StateAtomFieldOptions opt;\n");
for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
atom != atoms.decls.end(); atom++) {
if (atom->primaryFields.size() == 0 && atom->exclusiveField == 0) {
continue;
}
fprintf(out,
"\n // Adding primary and exclusive fields for atom "
"(%d)%s\n",
atom->code, atom->name.c_str());
fprintf(out, " opt.primaryFields.clear();\n");
for (const auto& field : atom->primaryFields) {
fprintf(out, " opt.primaryFields.push_back(%d);\n", field);
}
fprintf(out, " opt.exclusiveField = %d;\n", atom->exclusiveField);
fprintf(out, " options[static_cast<int>(%s)] = opt;\n",
make_constant_name(atom->name).c_str());
}
fprintf(out, " return options;\n");
fprintf(out, " }\n");
fprintf(out, "};\n");
fprintf(out,
"const static std::map<int, StateAtomFieldOptions> "
"kStateAtomsFieldOptions = "
"StateAtomFieldOptions::getStateAtomFieldOptions();\n");
// Print write methods
fprintf(out, "//\n");
fprintf(out, "// Write methods\n");

View File

@@ -17,6 +17,7 @@
syntax = "proto2";
import "frameworks/base/cmds/statsd/src/atoms.proto";
import "frameworks/base/cmds/statsd/src/atom_field_options.proto";
package android.stats_log_api_gen;
@@ -108,3 +109,68 @@ message BadAttributionNodePosition {
oneof event { BadAttributionNodePositionAtom bad = 1; }
}
message BadStateAtoms {
oneof event {
BadStateAtom1 bad1 = 1;
BadStateAtom2 bad2 = 2;
BadStateAtom3 bad3 = 3;
}
}
message GoodStateAtoms {
oneof event {
GoodStateAtom1 good1 = 1;
GoodStateAtom2 good2 = 2;
}
}
// The atom has only primary field but no exclusive state field.
message BadStateAtom1 {
optional int32 uid = 1
[(android.os.statsd.stateFieldOption).option = PRIMARY];
}
// Only primative types can be annotated.
message BadStateAtom2 {
repeated android.os.statsd.AttributionNode attribution = 1
[(android.os.statsd.stateFieldOption).option = PRIMARY];
optional int32 state = 2
[(android.os.statsd.stateFieldOption).option = EXCLUSIVE];
}
// Having 2 exclusive state field in the atom means the atom is badly designed.
// E.g., putting bluetooth state and wifi state in the same atom.
message BadStateAtom3 {
optional int32 uid = 1
[(android.os.statsd.stateFieldOption).option = PRIMARY];
optional int32 state = 2
[(android.os.statsd.stateFieldOption).option = EXCLUSIVE];
optional int32 state2 = 3
[(android.os.statsd.stateFieldOption).option = EXCLUSIVE];
}
message GoodStateAtom1 {
optional int32 uid = 1
[(android.os.statsd.stateFieldOption).option = PRIMARY];
optional int32 state = 2
[(android.os.statsd.stateFieldOption).option = EXCLUSIVE];
}
// Atoms can have exclusive state field, but no primary field. That means
// the state is globally exclusive (e.g., DisplayState).
message GoodStateAtom2 {
optional int32 uid = 1;
optional int32 state = 2
[(android.os.statsd.stateFieldOption).option = EXCLUSIVE];
}
// We can have more than one primary fields. That means their combination is a
// primary key.
message GoodStateAtom3 {
optional int32 uid = 1
[(android.os.statsd.stateFieldOption).option = PRIMARY];
optional int32 tid = 2
[(android.os.statsd.stateFieldOption).option = PRIMARY];
optional int32 state = 3
[(android.os.statsd.stateFieldOption).option = EXCLUSIVE];
}

View File

@@ -199,5 +199,18 @@ TEST(CollationTest, FailBadAttributionNodePosition) {
EXPECT_EQ(1, errorCount);
}
TEST(CollationTest, FailOnBadStateAtomOptions) {
Atoms atoms;
int errorCount = collate_atoms(BadStateAtoms::descriptor(), &atoms);
EXPECT_EQ(3, errorCount);
}
TEST(CollationTest, PassOnGoodStateAtomOptions) {
Atoms atoms;
int errorCount = collate_atoms(GoodStateAtoms::descriptor(), &atoms);
EXPECT_EQ(0, errorCount);
}
} // namespace stats_log_api_gen
} // namespace android