You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

326 lines
12 KiB

// 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 <gmock/gmock.h>
#include <gtest/gtest.h>
#include <private/android_filesystem_config.h>
#include <stdio.h>
#include <set>
#include <unordered_map>
#include <vector>
#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<int32_t> unionSet(const vector<set<int32_t>> sets) {
set<int32_t> toRet;
for (const set<int32_t>& s : sets) {
toRet.insert(s.begin(), s.end());
}
return toRet;
}
} // anonymous namespace
TEST(MetricsManagerTest, TestLogSources) {
string app1 = "app1";
set<int32_t> app1Uids = {1111, 11111};
string app2 = "app2";
set<int32_t> app2Uids = {2222};
string app3 = "app3";
set<int32_t> app3Uids = {3333, 1111};
map<string, set<int32_t>> pkgToUids;
pkgToUids[app1] = app1Uids;
pkgToUids[app2] = app2Uids;
pkgToUids[app3] = app3Uids;
int32_t atom1 = 10, atom2 = 20, atom3 = 30;
sp<MockUidMap> uidMap = new StrictMock<MockUidMap>();
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<int32_t>();
}));
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterPullUidProvider(kConfigKey, _)).Times(1);
EXPECT_CALL(*pullerManager, UnregisterPullUidProvider(kConfigKey, _)).Times(1);
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> 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<int32_t> 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<set<int32_t>>({app1Uids, {AID_SYSTEM}}))));
EXPECT_THAT(metricsManager.mDefaultPullUids, ContainerEq(defaultPullUids));
vector<int32_t> atom1Uids = metricsManager.getPullAtomUids(atom1);
EXPECT_THAT(atom1Uids,
UnorderedElementsAreArray(unionSet({defaultPullUids, app1Uids, app3Uids})));
vector<int32_t> atom2Uids = metricsManager.getPullAtomUids(atom2);
EXPECT_THAT(atom2Uids,
UnorderedElementsAreArray(unionSet({defaultPullUids, app2Uids, {AID_STATSD}})));
vector<int32_t> atom3Uids = metricsManager.getPullAtomUids(atom3);
EXPECT_THAT(atom3Uids, UnorderedElementsAreArray(defaultPullUids));
}
TEST(MetricsManagerTest, TestLogSourcesOnConfigUpdate) {
string app1 = "app1";
set<int32_t> app1Uids = {1111, 11111};
string app2 = "app2";
set<int32_t> app2Uids = {2222};
string app3 = "app3";
set<int32_t> app3Uids = {3333, 1111};
map<string, set<int32_t>> pkgToUids;
pkgToUids[app1] = app1Uids;
pkgToUids[app2] = app2Uids;
pkgToUids[app3] = app3Uids;
int32_t atom1 = 10, atom2 = 20, atom3 = 30;
sp<MockUidMap> uidMap = new StrictMock<MockUidMap>();
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<int32_t>();
}));
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterPullUidProvider(kConfigKey, _)).Times(1);
EXPECT_CALL(*pullerManager, UnregisterPullUidProvider(kConfigKey, _)).Times(1);
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> 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<set<int32_t>>({app2Uids, {AID_ROOT}}))));
const set<int32_t> defaultPullUids = {AID_SYSTEM, AID_STATSD};
EXPECT_THAT(metricsManager.mDefaultPullUids, ContainerEq(defaultPullUids));
vector<int32_t> atom1Uids = metricsManager.getPullAtomUids(atom1);
EXPECT_THAT(atom1Uids, UnorderedElementsAreArray(defaultPullUids));
vector<int32_t> atom2Uids = metricsManager.getPullAtomUids(atom2);
EXPECT_THAT(atom2Uids,
UnorderedElementsAreArray(unionSet({defaultPullUids, app1Uids, app3Uids})));
vector<int32_t> atom3Uids = metricsManager.getPullAtomUids(atom3);
EXPECT_THAT(atom3Uids,
UnorderedElementsAreArray(unionSet({defaultPullUids, app2Uids, {AID_ADB}})));
}
TEST(MetricsManagerTest, TestCheckLogCredentialsWhitelistedAtom) {
sp<UidMap> uidMap;
sp<StatsPullerManager> pullerManager = new StatsPullerManager();
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> 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> uidMap;
sp<StatsPullerManager> pullerManager = new StatsPullerManager();
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> 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