Loading apex/statsd/aidl/android/os/IStatsd.aidl +0 −6 Original line number Diff line number Diff line Loading @@ -221,12 +221,6 @@ interface IStatsd { */ const int FLAG_REQUIRE_LOW_LATENCY_MONITOR = 0x04; /** * Logs an event for binary push for module updates. */ oneway void sendBinaryPushStateChangedAtom(in String trainName, in long trainVersionCode, in int options, in int state, in long[] experimentId); /** * Logs an event for watchdog rollbacks. */ Loading cmds/statsd/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,7 @@ cc_defaults { "src/config/ConfigKey.cpp", "src/config/ConfigListener.cpp", "src/config/ConfigManager.cpp", "src/experiment_ids.proto", "src/external/GpuStatsPuller.cpp", "src/external/Perfetto.cpp", "src/external/PullResultReceiver.cpp", Loading cmds/statsd/src/StatsLogProcessor.cpp +123 −0 Original line number Diff line number Diff line Loading @@ -20,13 +20,17 @@ #include "StatsLogProcessor.h" #include <android-base/file.h> #include <cutils/multiuser.h> #include <frameworks/base/cmds/statsd/src/active_config_list.pb.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" Loading Loading @@ -68,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" Loading Loading @@ -181,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()); Loading @@ -201,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()); Loading cmds/statsd/src/StatsLogProcessor.h +8 −0 Original line number Diff line number Diff line Loading @@ -196,6 +196,14 @@ private: // Handler over the isolated uid change event. void onIsolatedUidChangedEventLocked(const LogEvent& event); // Handler over the binary push state changed event. void onBinaryPushStateChangedEventLocked(LogEvent* event); // Updates train info on disk based on binary push state changed info and // write disk info into parameters. void getAndUpdateTrainInfoOnDisk(int32_t state, int64_t* trainVersionCode, string* trainName, std::vector<int64_t>* experimentIds); // Reset all configs. void resetConfigsLocked(const int64_t timestampNs); // Reset the specified configs. Loading cmds/statsd/src/StatsService.cpp +6 −121 Original line number Diff line number Diff line Loading @@ -70,24 +70,11 @@ static binder::Status exception(uint32_t code, const std::string& msg) { return binder::Status::fromExceptionCode(code, String8(msg.c_str())); } static bool checkPermission(const char* permission) { sp<IStatsCompanionService> scs = getStatsCompanionService(); if (scs == nullptr) { return false; } bool success; pid_t pid = IPCThreadState::self()->getCallingPid(); uid_t uid = IPCThreadState::self()->getCallingUid(); binder::Status status = scs->checkPermission(String16(permission), pid, uid, &success); if (!status.isOk()) { return false; return checkPermissionForIds(permission, pid, uid); } return success; } binder::Status checkUid(uid_t expectedUid) { uid_t uid = IPCThreadState::self()->getCallingUid(); Loading Loading @@ -870,18 +857,8 @@ status_t StatsService::cmd_log_binary_push(int out, const Vector<String8>& args) dprintf(out, "Incorrect number of argument supplied\n"); return UNKNOWN_ERROR; } android::String16 trainName = android::String16(args[1].c_str()); string trainName = string(args[1].c_str()); int64_t trainVersion = strtoll(args[2].c_str(), nullptr, 10); int options = 0; if (args[3] == "1") { options = options | IStatsd::FLAG_REQUIRE_STAGING; } if (args[4] == "1") { options = options | IStatsd::FLAG_ROLLBACK_ENABLED; } if (args[5] == "1") { options = options | IStatsd::FLAG_REQUIRE_LOW_LATENCY_MONITOR; } int32_t state = atoi(args[6].c_str()); vector<int64_t> experimentIds; if (argCount == 8) { Loading @@ -892,7 +869,10 @@ status_t StatsService::cmd_log_binary_push(int out, const Vector<String8>& args) } } dprintf(out, "Logging BinaryPushStateChanged\n"); sendBinaryPushStateChangedAtom(trainName, trainVersion, options, state, experimentIds); vector<uint8_t> experimentIdBytes; writeExperimentIdsToProto(experimentIds, &experimentIdBytes); LogEvent event(trainName, trainVersion, args[3], args[4], args[5], state, experimentIdBytes, 0); mProcessor->OnLogEvent(&event); return NO_ERROR; } Loading Loading @@ -1313,101 +1293,6 @@ Status StatsService::unregisterNativePullAtomCallback(int32_t atomTag) { return Status::ok(); } Status StatsService::sendBinaryPushStateChangedAtom(const android::String16& trainNameIn, const int64_t trainVersionCodeIn, const int options, const int32_t state, const std::vector<int64_t>& experimentIdsIn) { // Note: We skip the usage stats op check here since we do not have a package name. // This is ok since we are overloading the usage_stats permission. // This method only sends data, it does not receive it. pid_t pid = IPCThreadState::self()->getCallingPid(); uid_t uid = IPCThreadState::self()->getCallingUid(); // Root, system, and shell always have access if (uid != AID_ROOT && uid != AID_SYSTEM && uid != AID_SHELL) { // Caller must be granted these permissions if (!checkPermission(kPermissionDump)) { return exception(binder::Status::EX_SECURITY, StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, kPermissionDump)); } if (!checkPermission(kPermissionUsage)) { return exception(binder::Status::EX_SECURITY, StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, kPermissionUsage)); } } bool readTrainInfoSuccess = false; InstallTrainInfo trainInfoOnDisk; readTrainInfoSuccess = StorageManager::readTrainInfo(trainInfoOnDisk); bool resetExperimentIds = false; int64_t trainVersionCode = trainVersionCodeIn; std::string trainNameUtf8 = std::string(String8(trainNameIn).string()); if (readTrainInfoSuccess) { // Keep the old train version if we received an empty version. if (trainVersionCodeIn == -1) { trainVersionCode = trainInfoOnDisk.trainVersionCode; } else if (trainVersionCodeIn != 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 (trainNameUtf8.size() == 0) { trainNameUtf8 = trainInfoOnDisk.trainName; } else if (trainNameUtf8 != trainInfoOnDisk.trainName) { // Reset experiment ids if we received a new valid train name. resetExperimentIds = true; } // Reset if we received a different experiment id. if (!experimentIdsIn.empty() && (trainInfoOnDisk.experimentIds.empty() || experimentIdsIn[0] != trainInfoOnDisk.experimentIds[0])) { resetExperimentIds = true; } } // Find the right experiment IDs std::vector<int64_t> experimentIds; if (resetExperimentIds || !readTrainInfoSuccess) { experimentIds = experimentIdsIn; } else { experimentIds = trainInfoOnDisk.experimentIds; } if (!experimentIds.empty()) { int64_t firstId = experimentIds[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; } } // Flatten the experiment IDs to proto vector<uint8_t> experimentIdsProtoBuffer; writeExperimentIdsToProto(experimentIds, &experimentIdsProtoBuffer); StorageManager::writeTrainInfo(trainVersionCode, trainNameUtf8, state, experimentIds); userid_t userId = multiuser_get_user_id(uid); bool requiresStaging = options & IStatsd::FLAG_REQUIRE_STAGING; bool rollbackEnabled = options & IStatsd::FLAG_ROLLBACK_ENABLED; bool requiresLowLatencyMonitor = options & IStatsd::FLAG_REQUIRE_LOW_LATENCY_MONITOR; LogEvent event(trainNameUtf8, trainVersionCode, requiresStaging, rollbackEnabled, requiresLowLatencyMonitor, state, experimentIdsProtoBuffer, userId); mProcessor->OnLogEvent(&event); return Status::ok(); } Status StatsService::sendWatchdogRollbackOccurredAtom(const int32_t rollbackTypeIn, const android::String16& packageNameIn, const int64_t packageVersionCodeIn, Loading Loading
apex/statsd/aidl/android/os/IStatsd.aidl +0 −6 Original line number Diff line number Diff line Loading @@ -221,12 +221,6 @@ interface IStatsd { */ const int FLAG_REQUIRE_LOW_LATENCY_MONITOR = 0x04; /** * Logs an event for binary push for module updates. */ oneway void sendBinaryPushStateChangedAtom(in String trainName, in long trainVersionCode, in int options, in int state, in long[] experimentId); /** * Logs an event for watchdog rollbacks. */ Loading
cmds/statsd/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,7 @@ cc_defaults { "src/config/ConfigKey.cpp", "src/config/ConfigListener.cpp", "src/config/ConfigManager.cpp", "src/experiment_ids.proto", "src/external/GpuStatsPuller.cpp", "src/external/Perfetto.cpp", "src/external/PullResultReceiver.cpp", Loading
cmds/statsd/src/StatsLogProcessor.cpp +123 −0 Original line number Diff line number Diff line Loading @@ -20,13 +20,17 @@ #include "StatsLogProcessor.h" #include <android-base/file.h> #include <cutils/multiuser.h> #include <frameworks/base/cmds/statsd/src/active_config_list.pb.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" Loading Loading @@ -68,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" Loading Loading @@ -181,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()); Loading @@ -201,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()); Loading
cmds/statsd/src/StatsLogProcessor.h +8 −0 Original line number Diff line number Diff line Loading @@ -196,6 +196,14 @@ private: // Handler over the isolated uid change event. void onIsolatedUidChangedEventLocked(const LogEvent& event); // Handler over the binary push state changed event. void onBinaryPushStateChangedEventLocked(LogEvent* event); // Updates train info on disk based on binary push state changed info and // write disk info into parameters. void getAndUpdateTrainInfoOnDisk(int32_t state, int64_t* trainVersionCode, string* trainName, std::vector<int64_t>* experimentIds); // Reset all configs. void resetConfigsLocked(const int64_t timestampNs); // Reset the specified configs. Loading
cmds/statsd/src/StatsService.cpp +6 −121 Original line number Diff line number Diff line Loading @@ -70,24 +70,11 @@ static binder::Status exception(uint32_t code, const std::string& msg) { return binder::Status::fromExceptionCode(code, String8(msg.c_str())); } static bool checkPermission(const char* permission) { sp<IStatsCompanionService> scs = getStatsCompanionService(); if (scs == nullptr) { return false; } bool success; pid_t pid = IPCThreadState::self()->getCallingPid(); uid_t uid = IPCThreadState::self()->getCallingUid(); binder::Status status = scs->checkPermission(String16(permission), pid, uid, &success); if (!status.isOk()) { return false; return checkPermissionForIds(permission, pid, uid); } return success; } binder::Status checkUid(uid_t expectedUid) { uid_t uid = IPCThreadState::self()->getCallingUid(); Loading Loading @@ -870,18 +857,8 @@ status_t StatsService::cmd_log_binary_push(int out, const Vector<String8>& args) dprintf(out, "Incorrect number of argument supplied\n"); return UNKNOWN_ERROR; } android::String16 trainName = android::String16(args[1].c_str()); string trainName = string(args[1].c_str()); int64_t trainVersion = strtoll(args[2].c_str(), nullptr, 10); int options = 0; if (args[3] == "1") { options = options | IStatsd::FLAG_REQUIRE_STAGING; } if (args[4] == "1") { options = options | IStatsd::FLAG_ROLLBACK_ENABLED; } if (args[5] == "1") { options = options | IStatsd::FLAG_REQUIRE_LOW_LATENCY_MONITOR; } int32_t state = atoi(args[6].c_str()); vector<int64_t> experimentIds; if (argCount == 8) { Loading @@ -892,7 +869,10 @@ status_t StatsService::cmd_log_binary_push(int out, const Vector<String8>& args) } } dprintf(out, "Logging BinaryPushStateChanged\n"); sendBinaryPushStateChangedAtom(trainName, trainVersion, options, state, experimentIds); vector<uint8_t> experimentIdBytes; writeExperimentIdsToProto(experimentIds, &experimentIdBytes); LogEvent event(trainName, trainVersion, args[3], args[4], args[5], state, experimentIdBytes, 0); mProcessor->OnLogEvent(&event); return NO_ERROR; } Loading Loading @@ -1313,101 +1293,6 @@ Status StatsService::unregisterNativePullAtomCallback(int32_t atomTag) { return Status::ok(); } Status StatsService::sendBinaryPushStateChangedAtom(const android::String16& trainNameIn, const int64_t trainVersionCodeIn, const int options, const int32_t state, const std::vector<int64_t>& experimentIdsIn) { // Note: We skip the usage stats op check here since we do not have a package name. // This is ok since we are overloading the usage_stats permission. // This method only sends data, it does not receive it. pid_t pid = IPCThreadState::self()->getCallingPid(); uid_t uid = IPCThreadState::self()->getCallingUid(); // Root, system, and shell always have access if (uid != AID_ROOT && uid != AID_SYSTEM && uid != AID_SHELL) { // Caller must be granted these permissions if (!checkPermission(kPermissionDump)) { return exception(binder::Status::EX_SECURITY, StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, kPermissionDump)); } if (!checkPermission(kPermissionUsage)) { return exception(binder::Status::EX_SECURITY, StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, kPermissionUsage)); } } bool readTrainInfoSuccess = false; InstallTrainInfo trainInfoOnDisk; readTrainInfoSuccess = StorageManager::readTrainInfo(trainInfoOnDisk); bool resetExperimentIds = false; int64_t trainVersionCode = trainVersionCodeIn; std::string trainNameUtf8 = std::string(String8(trainNameIn).string()); if (readTrainInfoSuccess) { // Keep the old train version if we received an empty version. if (trainVersionCodeIn == -1) { trainVersionCode = trainInfoOnDisk.trainVersionCode; } else if (trainVersionCodeIn != 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 (trainNameUtf8.size() == 0) { trainNameUtf8 = trainInfoOnDisk.trainName; } else if (trainNameUtf8 != trainInfoOnDisk.trainName) { // Reset experiment ids if we received a new valid train name. resetExperimentIds = true; } // Reset if we received a different experiment id. if (!experimentIdsIn.empty() && (trainInfoOnDisk.experimentIds.empty() || experimentIdsIn[0] != trainInfoOnDisk.experimentIds[0])) { resetExperimentIds = true; } } // Find the right experiment IDs std::vector<int64_t> experimentIds; if (resetExperimentIds || !readTrainInfoSuccess) { experimentIds = experimentIdsIn; } else { experimentIds = trainInfoOnDisk.experimentIds; } if (!experimentIds.empty()) { int64_t firstId = experimentIds[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; } } // Flatten the experiment IDs to proto vector<uint8_t> experimentIdsProtoBuffer; writeExperimentIdsToProto(experimentIds, &experimentIdsProtoBuffer); StorageManager::writeTrainInfo(trainVersionCode, trainNameUtf8, state, experimentIds); userid_t userId = multiuser_get_user_id(uid); bool requiresStaging = options & IStatsd::FLAG_REQUIRE_STAGING; bool rollbackEnabled = options & IStatsd::FLAG_ROLLBACK_ENABLED; bool requiresLowLatencyMonitor = options & IStatsd::FLAG_REQUIRE_LOW_LATENCY_MONITOR; LogEvent event(trainNameUtf8, trainVersionCode, requiresStaging, rollbackEnabled, requiresLowLatencyMonitor, state, experimentIdsProtoBuffer, userId); mProcessor->OnLogEvent(&event); return Status::ok(); } Status StatsService::sendWatchdogRollbackOccurredAtom(const int32_t rollbackTypeIn, const android::String16& packageNameIn, const int64_t packageVersionCodeIn, Loading