// 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 #include #include #include #include #include #include #include "src/statsd_config.pb.h" #include "metrics/metrics_test_helper.h" #include "src/condition/ConditionTracker.h" #include "src/matchers/AtomMatchingTracker.h" #include "src/metrics/CountMetricProducer.h" #include "src/metrics/GaugeMetricProducer.h" #include "src/metrics/MetricProducer.h" #include "src/metrics/ValueMetricProducer.h" #include "src/metrics/parsing_utils/metrics_manager_util.h" #include "src/state/StateManager.h" #include "statsd_test_util.h" using namespace testing; using android::sp; using android::os::statsd::Predicate; using std::map; using std::set; using std::unordered_map; using std::vector; #ifdef __ANDROID__ namespace android { namespace os { namespace statsd { namespace { const ConfigKey kConfigKey(0, 12345); const long timeBaseSec = 1000; StatsdConfig buildGoodConfig() { StatsdConfig config; config.set_id(12345); AtomMatcher* eventMatcher = config.add_atom_matcher(); eventMatcher->set_id(StringToId("SCREEN_IS_ON")); SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher(); simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/); simpleAtomMatcher->add_field_value_matcher()->set_field( 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/); simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int( 2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/); eventMatcher = config.add_atom_matcher(); eventMatcher->set_id(StringToId("SCREEN_IS_OFF")); simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher(); simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/); simpleAtomMatcher->add_field_value_matcher()->set_field( 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/); simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int( 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_OFF*/); eventMatcher = config.add_atom_matcher(); eventMatcher->set_id(StringToId("SCREEN_ON_OR_OFF")); AtomMatcher_Combination* combination = eventMatcher->mutable_combination(); combination->set_operation(LogicalOperation::OR); combination->add_matcher(StringToId("SCREEN_IS_ON")); combination->add_matcher(StringToId("SCREEN_IS_OFF")); CountMetric* metric = config.add_count_metric(); metric->set_id(3); metric->set_what(StringToId("SCREEN_IS_ON")); metric->set_bucket(ONE_MINUTE); metric->mutable_dimensions_in_what()->set_field(2 /*SCREEN_STATE_CHANGE*/); metric->mutable_dimensions_in_what()->add_child()->set_field(1); return config; } set unionSet(const vector> sets) { set toRet; for (const set& s : sets) { toRet.insert(s.begin(), s.end()); } return toRet; } } // anonymous namespace TEST(MetricsManagerTest, TestLogSources) { string app1 = "app1"; set app1Uids = {1111, 11111}; string app2 = "app2"; set app2Uids = {2222}; string app3 = "app3"; set app3Uids = {3333, 1111}; map> pkgToUids; pkgToUids[app1] = app1Uids; pkgToUids[app2] = app2Uids; pkgToUids[app3] = app3Uids; int32_t atom1 = 10, atom2 = 20, atom3 = 30; sp uidMap = new StrictMock(); EXPECT_CALL(*uidMap, getAppUid(_)) .Times(4) .WillRepeatedly(Invoke([&pkgToUids](const string& pkg) { const auto& it = pkgToUids.find(pkg); if (it != pkgToUids.end()) { return it->second; } return set(); })); sp pullerManager = new StrictMock(); EXPECT_CALL(*pullerManager, RegisterPullUidProvider(kConfigKey, _)).Times(1); EXPECT_CALL(*pullerManager, UnregisterPullUidProvider(kConfigKey, _)).Times(1); sp anomalyAlarmMonitor; sp periodicAlarmMonitor; StatsdConfig config; config.add_allowed_log_source("AID_SYSTEM"); config.add_allowed_log_source(app1); config.add_default_pull_packages("AID_SYSTEM"); config.add_default_pull_packages("AID_ROOT"); const set defaultPullUids = {AID_SYSTEM, AID_ROOT}; PullAtomPackages* pullAtomPackages = config.add_pull_atom_packages(); pullAtomPackages->set_atom_id(atom1); pullAtomPackages->add_packages(app1); pullAtomPackages->add_packages(app3); pullAtomPackages = config.add_pull_atom_packages(); pullAtomPackages->set_atom_id(atom2); pullAtomPackages->add_packages(app2); pullAtomPackages->add_packages("AID_STATSD"); MetricsManager metricsManager(kConfigKey, config, timeBaseSec, timeBaseSec, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor); EXPECT_TRUE(metricsManager.isConfigValid()); EXPECT_THAT(metricsManager.mAllowedUid, ElementsAre(AID_SYSTEM)); EXPECT_THAT(metricsManager.mAllowedPkg, ElementsAre(app1)); EXPECT_THAT(metricsManager.mAllowedLogSources, ContainerEq(unionSet(vector>({app1Uids, {AID_SYSTEM}})))); EXPECT_THAT(metricsManager.mDefaultPullUids, ContainerEq(defaultPullUids)); vector atom1Uids = metricsManager.getPullAtomUids(atom1); EXPECT_THAT(atom1Uids, UnorderedElementsAreArray(unionSet({defaultPullUids, app1Uids, app3Uids}))); vector atom2Uids = metricsManager.getPullAtomUids(atom2); EXPECT_THAT(atom2Uids, UnorderedElementsAreArray(unionSet({defaultPullUids, app2Uids, {AID_STATSD}}))); vector atom3Uids = metricsManager.getPullAtomUids(atom3); EXPECT_THAT(atom3Uids, UnorderedElementsAreArray(defaultPullUids)); } TEST(MetricsManagerTest, TestLogSourcesOnConfigUpdate) { string app1 = "app1"; set app1Uids = {1111, 11111}; string app2 = "app2"; set app2Uids = {2222}; string app3 = "app3"; set app3Uids = {3333, 1111}; map> pkgToUids; pkgToUids[app1] = app1Uids; pkgToUids[app2] = app2Uids; pkgToUids[app3] = app3Uids; int32_t atom1 = 10, atom2 = 20, atom3 = 30; sp uidMap = new StrictMock(); EXPECT_CALL(*uidMap, getAppUid(_)) .Times(8) .WillRepeatedly(Invoke([&pkgToUids](const string& pkg) { const auto& it = pkgToUids.find(pkg); if (it != pkgToUids.end()) { return it->second; } return set(); })); sp pullerManager = new StrictMock(); EXPECT_CALL(*pullerManager, RegisterPullUidProvider(kConfigKey, _)).Times(1); EXPECT_CALL(*pullerManager, UnregisterPullUidProvider(kConfigKey, _)).Times(1); sp anomalyAlarmMonitor; sp periodicAlarmMonitor; StatsdConfig config; config.add_allowed_log_source("AID_SYSTEM"); config.add_allowed_log_source(app1); config.add_default_pull_packages("AID_SYSTEM"); config.add_default_pull_packages("AID_ROOT"); PullAtomPackages* pullAtomPackages = config.add_pull_atom_packages(); pullAtomPackages->set_atom_id(atom1); pullAtomPackages->add_packages(app1); pullAtomPackages->add_packages(app3); pullAtomPackages = config.add_pull_atom_packages(); pullAtomPackages->set_atom_id(atom2); pullAtomPackages->add_packages(app2); pullAtomPackages->add_packages("AID_STATSD"); MetricsManager metricsManager(kConfigKey, config, timeBaseSec, timeBaseSec, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor); EXPECT_TRUE(metricsManager.isConfigValid()); // Update with new allowed log sources. StatsdConfig newConfig; newConfig.add_allowed_log_source("AID_ROOT"); newConfig.add_allowed_log_source(app2); newConfig.add_default_pull_packages("AID_SYSTEM"); newConfig.add_default_pull_packages("AID_STATSD"); pullAtomPackages = newConfig.add_pull_atom_packages(); pullAtomPackages->set_atom_id(atom2); pullAtomPackages->add_packages(app1); pullAtomPackages->add_packages(app3); pullAtomPackages = newConfig.add_pull_atom_packages(); pullAtomPackages->set_atom_id(atom3); pullAtomPackages->add_packages(app2); pullAtomPackages->add_packages("AID_ADB"); metricsManager.updateConfig(newConfig, timeBaseSec, timeBaseSec, anomalyAlarmMonitor, periodicAlarmMonitor); EXPECT_TRUE(metricsManager.isConfigValid()); EXPECT_THAT(metricsManager.mAllowedUid, ElementsAre(AID_ROOT)); EXPECT_THAT(metricsManager.mAllowedPkg, ElementsAre(app2)); EXPECT_THAT(metricsManager.mAllowedLogSources, ContainerEq(unionSet(vector>({app2Uids, {AID_ROOT}})))); const set defaultPullUids = {AID_SYSTEM, AID_STATSD}; EXPECT_THAT(metricsManager.mDefaultPullUids, ContainerEq(defaultPullUids)); vector atom1Uids = metricsManager.getPullAtomUids(atom1); EXPECT_THAT(atom1Uids, UnorderedElementsAreArray(defaultPullUids)); vector atom2Uids = metricsManager.getPullAtomUids(atom2); EXPECT_THAT(atom2Uids, UnorderedElementsAreArray(unionSet({defaultPullUids, app1Uids, app3Uids}))); vector atom3Uids = metricsManager.getPullAtomUids(atom3); EXPECT_THAT(atom3Uids, UnorderedElementsAreArray(unionSet({defaultPullUids, app2Uids, {AID_ADB}}))); } TEST(MetricsManagerTest, TestCheckLogCredentialsWhitelistedAtom) { sp uidMap; sp pullerManager = new StatsPullerManager(); sp anomalyAlarmMonitor; sp periodicAlarmMonitor; StatsdConfig config; config.add_whitelisted_atom_ids(3); config.add_whitelisted_atom_ids(4); MetricsManager metricsManager(kConfigKey, config, timeBaseSec, timeBaseSec, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor); LogEvent event(0 /* uid */, 0 /* pid */); CreateNoValuesLogEvent(&event, 10 /* atom id */, 0 /* timestamp */); EXPECT_FALSE(metricsManager.checkLogCredentials(event)); CreateNoValuesLogEvent(&event, 3 /* atom id */, 0 /* timestamp */); EXPECT_TRUE(metricsManager.checkLogCredentials(event)); CreateNoValuesLogEvent(&event, 4 /* atom id */, 0 /* timestamp */); EXPECT_TRUE(metricsManager.checkLogCredentials(event)); } TEST(MetricsManagerTest, TestWhitelistedAtomStateTracker) { sp uidMap; sp pullerManager = new StatsPullerManager(); sp anomalyAlarmMonitor; sp periodicAlarmMonitor; StatsdConfig config = buildGoodConfig(); config.add_allowed_log_source("AID_SYSTEM"); config.add_whitelisted_atom_ids(3); config.add_whitelisted_atom_ids(4); State state; state.set_id(1); state.set_atom_id(3); *config.add_state() = state; config.mutable_count_metric(0)->add_slice_by_state(state.id()); StateManager::getInstance().clear(); MetricsManager metricsManager(kConfigKey, config, timeBaseSec, timeBaseSec, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor); EXPECT_EQ(0, StateManager::getInstance().getStateTrackersCount()); EXPECT_FALSE(metricsManager.isConfigValid()); } } // namespace statsd } // namespace os } // namespace android #else GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif