diff options
Diffstat (limited to 'cmds/statsd/src/StatsLogProcessor.cpp')
-rw-r--r-- | cmds/statsd/src/StatsLogProcessor.cpp | 129 |
1 files changed, 123 insertions, 6 deletions
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp index 34818145a922..bde15a5cdaae 100644 --- a/cmds/statsd/src/StatsLogProcessor.cpp +++ b/cmds/statsd/src/StatsLogProcessor.cpp @@ -20,17 +20,17 @@ #include "StatsLogProcessor.h" #include <android-base/file.h> -#include <dirent.h> +#include <cutils/multiuser.h> #include <frameworks/base/cmds/statsd/src/active_config_list.pb.h> -#include <log/log_event_list.h> -#include <utils/Errors.h> -#include <utils/SystemClock.h> +#include <frameworks/base/cmds/statsd/src/experiment_ids.pb.h> #include "android-base/stringprintf.h" #include "atoms_info.h" #include "external/StatsPullerManager.h" #include "guardrail/StatsdStats.h" +#include "logd/LogEvent.h" #include "metrics/CountMetricProducer.h" +#include "StatsService.h" #include "state/StateManager.h" #include "stats_log_util.h" #include "stats_util.h" @@ -47,8 +47,6 @@ using android::util::FIELD_TYPE_INT64; using android::util::FIELD_TYPE_MESSAGE; using android::util::FIELD_TYPE_STRING; using android::util::ProtoOutputStream; -using std::make_unique; -using std::unique_ptr; using std::vector; namespace android { @@ -74,6 +72,10 @@ const int FIELD_ID_STRINGS = 9; // for ActiveConfigList const int FIELD_ID_ACTIVE_CONFIG_LIST_CONFIG = 1; +// for permissions checks +constexpr const char* kPermissionDump = "android.permission.DUMP"; +constexpr const char* kPermissionUsage = "android.permission.PACKAGE_USAGE_STATS"; + #define NS_PER_HOUR 3600 * NS_PER_SEC #define STATS_ACTIVE_METRIC_DIR "/data/misc/stats-active-metric" @@ -187,6 +189,115 @@ void StatsLogProcessor::onIsolatedUidChangedEventLocked(const LogEvent& event) { } } +void StatsLogProcessor::onBinaryPushStateChangedEventLocked(LogEvent* event) { + pid_t pid = event->GetPid(); + uid_t uid = event->GetUid(); + if (!checkPermissionForIds(kPermissionDump, pid, uid) || + !checkPermissionForIds(kPermissionUsage, pid, uid)) { + return; + } + status_t err = NO_ERROR, err2 = NO_ERROR, err3 = NO_ERROR, err4 = NO_ERROR; + string trainName = string(event->GetString(1 /*train name field id*/, &err)); + int64_t trainVersionCode = event->GetLong(2 /*train version field id*/, &err2); + int32_t state = int32_t(event->GetLong(6 /*state field id*/, &err3)); +#ifdef NEW_ENCODING_SCHEME + std::vector<uint8_t> trainExperimentIdBytes = + event->GetStorage(7 /*experiment ids field id*/, &err4); +#else + string trainExperimentIdString = event->GetString(7 /*experiment ids field id*/, &err4); +#endif + if (err != NO_ERROR || err2 != NO_ERROR || err3 != NO_ERROR || err4 != NO_ERROR) { + ALOGE("Failed to parse fields in binary push state changed log event"); + return; + } + ExperimentIds trainExperimentIds; +#ifdef NEW_ENCODING_SCHEME + if (!trainExperimentIds.ParseFromArray(trainExperimentIdBytes.data(), + trainExperimentIdBytes.size())) { +#else + if (!trainExperimentIds.ParseFromString(trainExperimentIdString)) { +#endif + ALOGE("Failed to parse experimentids in binary push state changed."); + return; + } + vector<int64_t> experimentIdVector = {trainExperimentIds.experiment_id().begin(), + trainExperimentIds.experiment_id().end()}; + // Update the train info on disk and get any data the logevent is missing. + getAndUpdateTrainInfoOnDisk( + state, &trainVersionCode, &trainName, &experimentIdVector); + + std::vector<uint8_t> trainExperimentIdProto; + writeExperimentIdsToProto(experimentIdVector, &trainExperimentIdProto); + int32_t userId = multiuser_get_user_id(uid); + + event->updateValue(1 /*train name field id*/, trainName, STRING); + event->updateValue(2 /*train version field id*/, trainVersionCode, LONG); +#ifdef NEW_ENCODING_SCHEME + event->updateValue(7 /*experiment ids field id*/, trainExperimentIdProto, STORAGE); +#else + event->updateValue(7 /*experiment ids field id*/, trainExperimentIdProto, STRING); +#endif + event->updateValue(8 /*user id field id*/, userId, INT); +} + +void StatsLogProcessor::getAndUpdateTrainInfoOnDisk(int32_t state, + int64_t* trainVersionCode, + string* trainName, + std::vector<int64_t>* experimentIds) { + bool readTrainInfoSuccess = false; + InstallTrainInfo trainInfoOnDisk; + readTrainInfoSuccess = StorageManager::readTrainInfo(trainInfoOnDisk); + + bool resetExperimentIds = false; + if (readTrainInfoSuccess) { + // Keep the old train version if we received an empty version. + if (*trainVersionCode == -1) { + *trainVersionCode = trainInfoOnDisk.trainVersionCode; + } else if (*trainVersionCode != trainInfoOnDisk.trainVersionCode) { + // Reset experiment ids if we receive a new non-empty train version. + resetExperimentIds = true; + } + + // Keep the old train name if we received an empty train name. + if (trainName->size() == 0) { + *trainName = trainInfoOnDisk.trainName; + } else if (*trainName != trainInfoOnDisk.trainName) { + // Reset experiment ids if we received a new valid train name. + resetExperimentIds = true; + } + + // Reset if we received a different experiment id. + if (!experimentIds->empty() && + (trainInfoOnDisk.experimentIds.empty() || + experimentIds->at(0) != trainInfoOnDisk.experimentIds[0])) { + resetExperimentIds = true; + } + } + + // Find the right experiment IDs + if (!resetExperimentIds && readTrainInfoSuccess) { + *experimentIds = trainInfoOnDisk.experimentIds; + } + + if (!experimentIds->empty()) { + int64_t firstId = experimentIds->at(0); + switch (state) { + case android::util::BINARY_PUSH_STATE_CHANGED__STATE__INSTALL_SUCCESS: + experimentIds->push_back(firstId + 1); + break; + case android::util::BINARY_PUSH_STATE_CHANGED__STATE__INSTALLER_ROLLBACK_INITIATED: + experimentIds->push_back(firstId + 2); + break; + case android::util::BINARY_PUSH_STATE_CHANGED__STATE__INSTALLER_ROLLBACK_SUCCESS: + experimentIds->push_back(firstId + 3); + break; + } + } + + StorageManager::writeTrainInfo(*trainVersionCode, *trainName, state, *experimentIds); +} + + void StatsLogProcessor::resetConfigs() { std::lock_guard<std::mutex> lock(mMetricsMutex); resetConfigsLocked(getElapsedRealtimeNs()); @@ -207,6 +318,12 @@ void StatsLogProcessor::OnLogEvent(LogEvent* event) { void StatsLogProcessor::OnLogEvent(LogEvent* event, int64_t elapsedRealtimeNs) { std::lock_guard<std::mutex> lock(mMetricsMutex); + // Hard-coded logic to update train info on disk and fill in any information + // this log event may be missing. + if (event->GetTagId() == android::util::BINARY_PUSH_STATE_CHANGED) { + onBinaryPushStateChangedEventLocked(event); + } + #ifdef VERY_VERBOSE_PRINTING if (mPrintAllLogs) { ALOGI("%s", event->ToString().c_str()); |