Add whitelist atom field option
Whitelisted atoms can be triggered from any source Test: stats-log-api-gen-test Bug: 119217680 Change-Id: Ia5faed04d696b59ba4ffaab13f5046f943d8a8b7
This commit is contained in:
@@ -82,4 +82,6 @@ extend google.protobuf.FieldOptions {
|
||||
optional bool is_uid = 50001 [default = false];
|
||||
|
||||
optional LogMode log_mode = 50002 [default = MODE_AUTOMATIC];
|
||||
|
||||
optional bool allow_from_any_uid = 50003 [default = false];
|
||||
}
|
||||
@@ -110,7 +110,7 @@ message Atom {
|
||||
PacketWakeupOccurred packet_wakeup_occurred = 44;
|
||||
WallClockTimeShifted wall_clock_time_shifted = 45;
|
||||
AnomalyDetected anomaly_detected = 46;
|
||||
AppBreadcrumbReported app_breadcrumb_reported = 47;
|
||||
AppBreadcrumbReported app_breadcrumb_reported = 47 [(allow_from_any_uid) = true];
|
||||
AppStartOccurred app_start_occurred = 48;
|
||||
AppStartCanceled app_start_canceled = 49;
|
||||
AppStartFullyDrawn app_start_fully_drawn = 50;
|
||||
@@ -121,7 +121,7 @@ message Atom {
|
||||
AppStartMemoryStateCaptured app_start_memory_state_captured = 55;
|
||||
ShutdownSequenceReported shutdown_sequence_reported = 56;
|
||||
BootSequenceReported boot_sequence_reported = 57;
|
||||
DaveyOccurred davey_occurred = 58;
|
||||
DaveyOccurred davey_occurred = 58 [(allow_from_any_uid) = true];
|
||||
OverlayStateChanged overlay_state_changed = 59;
|
||||
ForegroundServiceStateChanged foreground_service_state_changed = 60;
|
||||
CallStateChanged call_state_changed = 61;
|
||||
|
||||
@@ -234,12 +234,22 @@ void MetricsManager::onDumpReport(const int64_t dumpTimeStampNs,
|
||||
VLOG("=========================Metric Reports End==========================");
|
||||
}
|
||||
|
||||
// Consume the stats log if it's interesting to this metric.
|
||||
void MetricsManager::onLogEvent(const LogEvent& event) {
|
||||
if (!mConfigValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool MetricsManager::checkLogCredentials(const LogEvent& event) {
|
||||
if (android::util::AtomsInfo::kWhitelistedAtoms.find(event.GetTagId()) !=
|
||||
android::util::AtomsInfo::kWhitelistedAtoms.end())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
std::lock_guard<std::mutex> lock(mAllowedLogSourcesMutex);
|
||||
if (mAllowedLogSources.find(event.GetUid()) == mAllowedLogSources.end()) {
|
||||
VLOG("log source %d not on the whitelist", event.GetUid());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MetricsManager::eventSanityCheck(const LogEvent& event) {
|
||||
if (event.GetTagId() == android::util::APP_BREADCRUMB_REPORTED) {
|
||||
// Check that app breadcrumb reported fields are valid.
|
||||
status_t err = NO_ERROR;
|
||||
@@ -249,23 +259,23 @@ void MetricsManager::onLogEvent(const LogEvent& event) {
|
||||
long appHookUid = event.GetLong(event.size()-2, &err);
|
||||
if (err != NO_ERROR ) {
|
||||
VLOG("APP_BREADCRUMB_REPORTED had error when parsing the uid");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
int32_t loggerUid = event.GetUid();
|
||||
if (loggerUid != appHookUid && loggerUid != AID_STATSD) {
|
||||
VLOG("APP_BREADCRUMB_REPORTED has invalid uid: claimed %ld but caller is %d",
|
||||
appHookUid, loggerUid);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// The state must be from 0,3. This part of code must be manually updated.
|
||||
long appHookState = event.GetLong(event.size(), &err);
|
||||
if (err != NO_ERROR ) {
|
||||
VLOG("APP_BREADCRUMB_REPORTED had error when parsing the state field");
|
||||
return;
|
||||
return false;
|
||||
} else if (appHookState < 0 || appHookState > 3) {
|
||||
VLOG("APP_BREADCRUMB_REPORTED does not have valid state %ld", appHookState);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
} else if (event.GetTagId() == android::util::DAVEY_OCCURRED) {
|
||||
// Daveys can be logged from any app since they are logged in libs/hwui/JankTracker.cpp.
|
||||
@@ -276,31 +286,42 @@ void MetricsManager::onLogEvent(const LogEvent& event) {
|
||||
long jankUid = event.GetLong(1, &err);
|
||||
if (err != NO_ERROR ) {
|
||||
VLOG("Davey occurred had error when parsing the uid");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
int32_t loggerUid = event.GetUid();
|
||||
if (loggerUid != jankUid && loggerUid != AID_STATSD) {
|
||||
VLOG("DAVEY_OCCURRED has invalid uid: claimed %ld but caller is %d", jankUid,
|
||||
loggerUid);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
long duration = event.GetLong(event.size(), &err);
|
||||
if (err != NO_ERROR ) {
|
||||
VLOG("Davey occurred had error when parsing the duration");
|
||||
return;
|
||||
return false;
|
||||
} else if (duration > 100000) {
|
||||
VLOG("Davey duration is unreasonably long: %ld", duration);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
std::lock_guard<std::mutex> lock(mAllowedLogSourcesMutex);
|
||||
if (mAllowedLogSources.find(event.GetUid()) == mAllowedLogSources.end()) {
|
||||
VLOG("log source %d not on the whitelist", event.GetUid());
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Consume the stats log if it's interesting to this metric.
|
||||
void MetricsManager::onLogEvent(const LogEvent& event) {
|
||||
if (!mConfigValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!checkLogCredentials(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!eventSanityCheck(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int tagId = event.GetTagId();
|
||||
int64_t eventTimeNs = event.GetElapsedTimestampNs();
|
||||
|
||||
|
||||
@@ -48,6 +48,10 @@ public:
|
||||
// Return whether the configuration is valid.
|
||||
bool isConfigValid() const;
|
||||
|
||||
bool checkLogCredentials(const LogEvent& event);
|
||||
|
||||
bool eventSanityCheck(const LogEvent& event);
|
||||
|
||||
void onLogEvent(const LogEvent& event);
|
||||
|
||||
void onAnomalyAlarmFired(
|
||||
|
||||
@@ -48,6 +48,7 @@ AtomDecl::AtomDecl(const AtomDecl& that)
|
||||
primaryFields(that.primaryFields),
|
||||
exclusiveField(that.exclusiveField),
|
||||
uidField(that.uidField),
|
||||
whitelisted(that.whitelisted),
|
||||
binaryFields(that.binaryFields) {}
|
||||
|
||||
AtomDecl::AtomDecl(int c, const string& n, const string& m)
|
||||
@@ -162,6 +163,7 @@ int collate_atom(const Descriptor *atom, AtomDecl *atomDecl,
|
||||
vector<java_type_t> *signature) {
|
||||
|
||||
int errorCount = 0;
|
||||
|
||||
// Build a sorted list of the fields. Descriptor has them in source file
|
||||
// order.
|
||||
map<int, const FieldDescriptor *> fields;
|
||||
@@ -387,6 +389,11 @@ int collate_atoms(const Descriptor *descriptor, Atoms *atoms) {
|
||||
|
||||
const Descriptor *atom = atomField->message_type();
|
||||
AtomDecl atomDecl(atomField->number(), atomField->name(), atom->name());
|
||||
|
||||
if (atomField->options().GetExtension(os::statsd::allow_from_any_uid) == true) {
|
||||
atomDecl.whitelisted = true;
|
||||
}
|
||||
|
||||
vector<java_type_t> signature;
|
||||
errorCount += collate_atom(atom, &atomDecl, &signature);
|
||||
if (atomDecl.primaryFields.size() != 0 && atomDecl.exclusiveField == 0) {
|
||||
|
||||
@@ -89,6 +89,8 @@ struct AtomDecl {
|
||||
|
||||
int uidField = 0;
|
||||
|
||||
bool whitelisted = false;
|
||||
|
||||
vector<int> binaryFields;
|
||||
|
||||
AtomDecl();
|
||||
|
||||
@@ -158,6 +158,20 @@ static int write_stats_log_cpp(FILE *out, const Atoms &atoms,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(out, "};\n");
|
||||
fprintf(out, "\n");
|
||||
|
||||
fprintf(out,
|
||||
"const std::set<int> AtomsInfo::kWhitelistedAtoms = {\n");
|
||||
for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
|
||||
atom != atoms.decls.end(); atom++) {
|
||||
if (atom->whitelisted) {
|
||||
string constant = make_constant_name(atom->name);
|
||||
fprintf(out, " %s,\n", constant.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(out, "};\n");
|
||||
fprintf(out, "\n");
|
||||
|
||||
@@ -728,6 +742,8 @@ write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl &attributio
|
||||
fprintf(out,
|
||||
" const static std::map<int, std::vector<int>> "
|
||||
"kBytesFieldAtoms;");
|
||||
fprintf(out,
|
||||
" const static std::set<int> kWhitelistedAtoms;\n");
|
||||
fprintf(out, "};\n");
|
||||
|
||||
fprintf(out, "const static int kMaxPushedAtomId = %d;\n\n",
|
||||
|
||||
@@ -195,4 +195,22 @@ message GoodStateAtom3 {
|
||||
[(android.os.statsd.state_field_option).option = PRIMARY];
|
||||
optional int32 state = 3
|
||||
[(android.os.statsd.state_field_option).option = EXCLUSIVE];
|
||||
}
|
||||
|
||||
message WhitelistedAtom {
|
||||
optional int32 field = 1;
|
||||
}
|
||||
|
||||
message NonWhitelistedAtom {
|
||||
optional int32 field = 1;
|
||||
}
|
||||
|
||||
message ListedAtoms {
|
||||
oneof event {
|
||||
// Atoms can be whitelisted i.e. they can be triggered by any source
|
||||
WhitelistedAtom whitelisted_atom = 1 [(android.os.statsd.allow_from_any_uid) = true];
|
||||
// Atoms are not whitelisted by default, so they can only be triggered
|
||||
// by whitelisted sources
|
||||
NonWhitelistedAtom non_whitelisted_atom = 2;
|
||||
}
|
||||
}
|
||||
@@ -226,5 +226,25 @@ TEST(CollationTest, FailOnBadBinaryFieldAtom) {
|
||||
EXPECT_TRUE(errorCount > 0);
|
||||
}
|
||||
|
||||
TEST(CollationTest, PassOnWhitelistedAtom) {
|
||||
Atoms atoms;
|
||||
int errorCount =
|
||||
collate_atoms(ListedAtoms::descriptor(), &atoms);
|
||||
EXPECT_EQ(errorCount, 0);
|
||||
EXPECT_EQ(atoms.decls.size(), 2ul);
|
||||
}
|
||||
|
||||
TEST(CollationTest, RecogniseWhitelistedAtom) {
|
||||
Atoms atoms;
|
||||
collate_atoms(ListedAtoms::descriptor(), &atoms);
|
||||
for (const auto& atomDecl : atoms.decls) {
|
||||
if (atomDecl.code == 1) {
|
||||
EXPECT_TRUE(atomDecl.whitelisted);
|
||||
} else {
|
||||
EXPECT_FALSE(atomDecl.whitelisted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace stats_log_api_gen
|
||||
} // namespace android
|
||||
Reference in New Issue
Block a user