diff options
Diffstat (limited to 'cmds')
59 files changed, 854 insertions, 563 deletions
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index d1af71d8886e..54785ca13185 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -66,9 +66,12 @@ namespace android { static const char OEM_BOOTANIMATION_FILE[] = "/oem/media/bootanimation.zip"; +static const char PRODUCT_BOOTANIMATION_FILE[] = "/product/media/bootanimation.zip"; static const char SYSTEM_BOOTANIMATION_FILE[] = "/system/media/bootanimation.zip"; +static const char PRODUCT_ENCRYPTED_BOOTANIMATION_FILE[] = "/product/media/bootanimation-encrypted.zip"; static const char SYSTEM_ENCRYPTED_BOOTANIMATION_FILE[] = "/system/media/bootanimation-encrypted.zip"; static const char OEM_SHUTDOWNANIMATION_FILE[] = "/oem/media/shutdownanimation.zip"; +static const char PRODUCT_SHUTDOWNANIMATION_FILE[] = "/product/media/shutdownanimation.zip"; static const char SYSTEM_SHUTDOWNANIMATION_FILE[] = "/system/media/shutdownanimation.zip"; static const char SYSTEM_DATA_DIR_PATH[] = "/data/system"; @@ -308,14 +311,20 @@ status_t BootAnimation::readyToRun() { bool encryptedAnimation = atoi(decrypt) != 0 || !strcmp("trigger_restart_min_framework", decrypt); - if (!mShuttingDown && encryptedAnimation && - (access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0)) { - mZipFileName = SYSTEM_ENCRYPTED_BOOTANIMATION_FILE; - return NO_ERROR; + if (!mShuttingDown && encryptedAnimation) { + static const char* encryptedBootFiles[] = + {PRODUCT_ENCRYPTED_BOOTANIMATION_FILE, SYSTEM_ENCRYPTED_BOOTANIMATION_FILE}; + for (const char* f : encryptedBootFiles) { + if (access(f, R_OK) == 0) { + mZipFileName = f; + return NO_ERROR; + } + } } - static const char* bootFiles[] = {OEM_BOOTANIMATION_FILE, SYSTEM_BOOTANIMATION_FILE}; + static const char* bootFiles[] = + {PRODUCT_BOOTANIMATION_FILE, OEM_BOOTANIMATION_FILE, SYSTEM_BOOTANIMATION_FILE}; static const char* shutdownFiles[] = - {OEM_SHUTDOWNANIMATION_FILE, SYSTEM_SHUTDOWNANIMATION_FILE}; + {PRODUCT_SHUTDOWNANIMATION_FILE, OEM_SHUTDOWNANIMATION_FILE, SYSTEM_SHUTDOWNANIMATION_FILE}; for (const char* f : (!mShuttingDown ? bootFiles : shutdownFiles)) { if (access(f, R_OK) == 0) { diff --git a/cmds/dpm/src/com/android/commands/dpm/Dpm.java b/cmds/dpm/src/com/android/commands/dpm/Dpm.java index 3ac70d668198..47581e10e937 100644 --- a/cmds/dpm/src/com/android/commands/dpm/Dpm.java +++ b/cmds/dpm/src/com/android/commands/dpm/Dpm.java @@ -45,6 +45,7 @@ public final class Dpm extends BaseCommand { private static final String COMMAND_SET_DEVICE_OWNER = "set-device-owner"; private static final String COMMAND_SET_PROFILE_OWNER = "set-profile-owner"; private static final String COMMAND_REMOVE_ACTIVE_ADMIN = "remove-active-admin"; + private static final String COMMAND_CLEAR_FREEZE_PERIOD_RECORD = "clear-freeze-period-record"; private IDevicePolicyManager mDevicePolicyManager; private int mUserId = UserHandle.USER_SYSTEM; @@ -75,7 +76,11 @@ public final class Dpm extends BaseCommand { "\n" + "dpm remove-active-admin: Disables an active admin, the admin must have declared" + " android:testOnly in the application in its manifest. This will also remove" + - " device and profile owners\n"); + " device and profile owners\n" + + "\n" + + "dpm " + COMMAND_CLEAR_FREEZE_PERIOD_RECORD + ": clears framework-maintained " + + "record of past freeze periods that the device went through. For use during " + + "feature development to prevent triggering restriction on setting freeze periods"); } @Override @@ -101,6 +106,9 @@ public final class Dpm extends BaseCommand { case COMMAND_REMOVE_ACTIVE_ADMIN: runRemoveActiveAdmin(); break; + case COMMAND_CLEAR_FREEZE_PERIOD_RECORD: + runClearFreezePeriodRecord(); + break; default: throw new IllegalArgumentException ("unknown command '" + command + "'"); } @@ -190,6 +198,11 @@ public final class Dpm extends BaseCommand { + mComponent.toShortString() + " for user " + mUserId); } + private void runClearFreezePeriodRecord() throws RemoteException { + mDevicePolicyManager.clearSystemUpdatePolicyFreezePeriodRecord(); + System.out.println("Success"); + } + private ComponentName parseComponentName(String component) { ComponentName cn = ComponentName.unflattenFromString(component); if (cn == null) { diff --git a/cmds/incident/main.cpp b/cmds/incident/main.cpp index 519852dbe88b..cdec6a01d086 100644 --- a/cmds/incident/main.cpp +++ b/cmds/incident/main.cpp @@ -148,9 +148,19 @@ find_section(const char* name) static int get_dest(const char* arg) { - if (strcmp(arg, "LOCAL") == 0) return 0; - if (strcmp(arg, "EXPLICIT") == 0) return 1; - if (strcmp(arg, "AUTOMATIC") == 0) return 2; + if (strcmp(arg, "L") == 0 + || strcmp(arg, "LOCAL") == 0) { + return DEST_LOCAL; + } + if (strcmp(arg, "E") == 0 + || strcmp(arg, "EXPLICIT") == 0) { + return DEST_EXPLICIT; + } + if (strcmp(arg, "A") == 0 + || strcmp(arg, "AUTO") == 0 + || strcmp(arg, "AUTOMATIC") == 0) { + return DEST_AUTOMATIC; + } return -1; // return the default value } diff --git a/cmds/incidentd/src/Privacy.cpp b/cmds/incidentd/src/Privacy.cpp index 5db2239810e2..3f0e331c8b55 100644 --- a/cmds/incidentd/src/Privacy.cpp +++ b/cmds/incidentd/src/Privacy.cpp @@ -65,10 +65,19 @@ PrivacySpec::CheckPremission(const Privacy* privacy, const uint8_t defaultDest) bool PrivacySpec::RequireAll() const { return dest == android::os::DEST_LOCAL; } -PrivacySpec new_spec_from_args(int dest) +PrivacySpec PrivacySpec::new_spec(int dest) { - if (dest < 0) return PrivacySpec(); - return PrivacySpec(dest); + switch (dest) { + case android::os::DEST_AUTOMATIC: + case android::os::DEST_EXPLICIT: + case android::os::DEST_LOCAL: + return PrivacySpec(dest); + default: + return PrivacySpec(); + } } -PrivacySpec get_default_dropbox_spec() { return PrivacySpec(android::os::DEST_AUTOMATIC); }
\ No newline at end of file +PrivacySpec PrivacySpec::get_default_dropbox_spec() +{ + return PrivacySpec(android::os::DEST_AUTOMATIC); +} diff --git a/cmds/incidentd/src/Privacy.h b/cmds/incidentd/src/Privacy.h index 9e15ff43be06..4f3db678f765 100644 --- a/cmds/incidentd/src/Privacy.h +++ b/cmds/incidentd/src/Privacy.h @@ -65,8 +65,6 @@ public: const uint8_t dest; PrivacySpec() : dest(DEST_DEFAULT_VALUE) {} - PrivacySpec(uint8_t dest) : dest(dest) {} - bool operator<(const PrivacySpec& other) const; // check permission of a policy, if returns true, don't strip the data. @@ -74,9 +72,12 @@ public: // if returns true, no data need to be stripped. bool RequireAll() const; -}; -PrivacySpec new_spec_from_args(int dest); -PrivacySpec get_default_dropbox_spec(); + // Constructs spec using static methods below. + static PrivacySpec new_spec(int dest); + static PrivacySpec get_default_dropbox_spec(); +private: + PrivacySpec(uint8_t dest) : dest(dest) {} +}; #endif // PRIVACY_H diff --git a/cmds/incidentd/src/Reporter.cpp b/cmds/incidentd/src/Reporter.cpp index bd559d6980f1..b9f479bd683f 100644 --- a/cmds/incidentd/src/Reporter.cpp +++ b/cmds/incidentd/src/Reporter.cpp @@ -64,7 +64,8 @@ ReportRequest::ok() ReportRequestSet::ReportRequestSet() :mRequests(), mSections(), - mMainFd(-1) + mMainFd(-1), + mMainDest(-1) { } @@ -86,6 +87,12 @@ ReportRequestSet::setMainFd(int fd) mMainFd = fd; } +void +ReportRequestSet::setMainDest(int dest) +{ + mMainDest = dest; +} + bool ReportRequestSet::containsSection(int id) { return mSections.containsSection(id); @@ -125,12 +132,14 @@ Reporter::runReport() status_t err = NO_ERROR; bool needMainFd = false; int mainFd = -1; + int mainDest = -1; HeaderSection headers; // See if we need the main file for (ReportRequestSet::iterator it=batch.begin(); it!=batch.end(); it++) { if ((*it)->fd < 0 && mainFd < 0) { needMainFd = true; + mainDest = (*it)->args.dest(); break; } } @@ -154,6 +163,7 @@ Reporter::runReport() // Add to the set batch.setMainFd(mainFd); + batch.setMainDest(mainDest); } // Tell everyone that we're starting. diff --git a/cmds/incidentd/src/Reporter.h b/cmds/incidentd/src/Reporter.h index 2615c6202d3d..f30ecf0dd648 100644 --- a/cmds/incidentd/src/Reporter.h +++ b/cmds/incidentd/src/Reporter.h @@ -53,6 +53,7 @@ public: void add(const sp<ReportRequest>& request); void setMainFd(int fd); + void setMainDest(int dest); typedef vector<sp<ReportRequest>>::iterator iterator; @@ -61,10 +62,12 @@ public: int mainFd() { return mMainFd; } bool containsSection(int id); + int mainDest() { return mMainDest; } private: vector<sp<ReportRequest>> mRequests; IncidentReportArgs mSections; int mMainFd; + int mMainDest; }; // ================================================================================ diff --git a/cmds/incidentd/src/Section.cpp b/cmds/incidentd/src/Section.cpp index 0827785811b6..faeab87f8178 100644 --- a/cmds/incidentd/src/Section.cpp +++ b/cmds/incidentd/src/Section.cpp @@ -152,36 +152,40 @@ write_report_requests(const int id, const FdBuffer& buffer, ReportRequestSet* re // The streaming ones, group requests by spec in order to save unnecessary strip operations map<PrivacySpec, vector<sp<ReportRequest>>> requestsBySpec; - for (ReportRequestSet::iterator it = requests->begin(); it != requests->end(); it++) { + for (auto it = requests->begin(); it != requests->end(); it++) { sp<ReportRequest> request = *it; if (!request->ok() || !request->args.containsSection(id)) { continue; // skip invalid request } - PrivacySpec spec = new_spec_from_args(request->args.dest()); + PrivacySpec spec = PrivacySpec::new_spec(request->args.dest()); requestsBySpec[spec].push_back(request); } - for (map<PrivacySpec, vector<sp<ReportRequest>>>::iterator mit = requestsBySpec.begin(); mit != requestsBySpec.end(); mit++) { + for (auto mit = requestsBySpec.begin(); mit != requestsBySpec.end(); mit++) { PrivacySpec spec = mit->first; err = privacyBuffer.strip(spec); if (err != NO_ERROR) return err; // it means the privacyBuffer data is corrupted. if (privacyBuffer.size() == 0) continue; - for (vector<sp<ReportRequest>>::iterator it = mit->second.begin(); it != mit->second.end(); it++) { + for (auto it = mit->second.begin(); it != mit->second.end(); it++) { sp<ReportRequest> request = *it; err = write_section_header(request->fd, id, privacyBuffer.size()); if (err != NO_ERROR) { request->err = err; continue; } err = privacyBuffer.flush(request->fd); if (err != NO_ERROR) { request->err = err; continue; } writeable++; - ALOGD("Section %d flushed %zu bytes to fd %d with spec %d", id, privacyBuffer.size(), request->fd, spec.dest); + ALOGD("Section %d flushed %zu bytes to fd %d with spec %d", id, + privacyBuffer.size(), request->fd, spec.dest); } privacyBuffer.clear(); } // The dropbox file if (requests->mainFd() >= 0) { - err = privacyBuffer.strip(get_default_dropbox_spec()); + PrivacySpec spec = requests->mainDest() < 0 ? + PrivacySpec::get_default_dropbox_spec() : + PrivacySpec::new_spec(requests->mainDest()); + err = privacyBuffer.strip(spec); if (err != NO_ERROR) return err; // the buffer data is corrupted. if (privacyBuffer.size() == 0) goto DONE; @@ -190,7 +194,8 @@ write_report_requests(const int id, const FdBuffer& buffer, ReportRequestSet* re err = privacyBuffer.flush(requests->mainFd()); if (err != NO_ERROR) { requests->setMainFd(-1); goto DONE; } writeable++; - ALOGD("Section %d flushed %zu bytes to dropbox %d", id, privacyBuffer.size(), requests->mainFd()); + ALOGD("Section %d flushed %zu bytes to dropbox %d with spec %d", id, + privacyBuffer.size(), requests->mainFd(), spec.dest); } DONE: diff --git a/cmds/incidentd/tests/PrivacyBuffer_test.cpp b/cmds/incidentd/tests/PrivacyBuffer_test.cpp index 32b9e42d270c..c7bfe5555743 100644 --- a/cmds/incidentd/tests/PrivacyBuffer_test.cpp +++ b/cmds/incidentd/tests/PrivacyBuffer_test.cpp @@ -73,7 +73,7 @@ public: } void assertStrip(uint8_t dest, string expected, Privacy* policy) { - PrivacySpec spec(dest); + PrivacySpec spec = PrivacySpec::new_spec(dest); EncodedBuffer::iterator bufData = buffer.data(); PrivacyBuffer privacyBuf(policy, bufData); ASSERT_EQ(privacyBuf.strip(spec), NO_ERROR); @@ -224,7 +224,8 @@ TEST_F(PrivacyBufferTest, ClearAndStrip) { Privacy* list[] = { create_privacy(1, OTHER_TYPE, DEST_LOCAL), NULL }; EncodedBuffer::iterator bufData = buffer.data(); PrivacyBuffer privacyBuf(create_message_privacy(300, list), bufData); - PrivacySpec spec1(DEST_EXPLICIT), spec2(DEST_LOCAL); + PrivacySpec spec1 = PrivacySpec::new_spec(DEST_EXPLICIT); + PrivacySpec spec2 = PrivacySpec::new_spec(DEST_LOCAL); ASSERT_EQ(privacyBuf.strip(spec1), NO_ERROR); assertBuffer(privacyBuf, STRING_FIELD_0); diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk index 565b092998af..eabbb96a392e 100644 --- a/cmds/statsd/Android.mk +++ b/cmds/statsd/Android.mk @@ -137,7 +137,7 @@ LOCAL_SHARED_LIBRARIES := $(statsd_common_shared_libraries) \ LOCAL_MODULE_CLASS := EXECUTABLES -#LOCAL_INIT_RC := statsd.rc +LOCAL_INIT_RC := statsd.rc include $(BUILD_EXECUTABLE) diff --git a/cmds/statsd/src/HashableDimensionKey.cpp b/cmds/statsd/src/HashableDimensionKey.cpp index 288ebe9dbbe9..857a6ddad0be 100644 --- a/cmds/statsd/src/HashableDimensionKey.cpp +++ b/cmds/statsd/src/HashableDimensionKey.cpp @@ -69,18 +69,17 @@ android::hash_t hashDimensionsValue(const DimensionsValue& value) { using std::string; - string HashableDimensionKey::toString() const { string flattened; DimensionsValueToString(getDimensionsValue(), &flattened); return flattened; } -bool compareDimensionsValue(const DimensionsValue& s1, const DimensionsValue& s2) { +bool EqualsTo(const DimensionsValue& s1, const DimensionsValue& s2) { if (s1.field() != s2.field()) { return false; } - if (s1.value_case() != s1.value_case()) { + if (s1.value_case() != s2.value_case()) { return false; } switch (s1.value_case()) { @@ -102,8 +101,8 @@ bool compareDimensionsValue(const DimensionsValue& s1, const DimensionsValue& s2 } bool allMatched = true; for (int i = 0; allMatched && i < s1.value_tuple().dimensions_value_size(); ++i) { - allMatched &= compareDimensionsValue(s1.value_tuple().dimensions_value(i), - s2.value_tuple().dimensions_value(i)); + allMatched &= EqualsTo(s1.value_tuple().dimensions_value(i), + s2.value_tuple().dimensions_value(i)); } return allMatched; } @@ -113,12 +112,54 @@ bool compareDimensionsValue(const DimensionsValue& s1, const DimensionsValue& s2 } } +bool LessThan(const DimensionsValue& s1, const DimensionsValue& s2) { + if (s1.field() != s2.field()) { + return s1.field() < s2.field(); + } + if (s1.value_case() != s2.value_case()) { + return s1.value_case() < s2.value_case(); + } + switch (s1.value_case()) { + case DimensionsValue::ValueCase::kValueStr: + return s1.value_str() < s2.value_str(); + case DimensionsValue::ValueCase::kValueInt: + return s1.value_int() < s2.value_int(); + case DimensionsValue::ValueCase::kValueLong: + return s1.value_long() < s2.value_long(); + case DimensionsValue::ValueCase::kValueBool: + return (int)s1.value_bool() < (int)s2.value_bool(); + case DimensionsValue::ValueCase::kValueFloat: + return s1.value_float() < s2.value_float(); + case DimensionsValue::ValueCase::kValueTuple: + { + if (s1.value_tuple().dimensions_value_size() != + s2.value_tuple().dimensions_value_size()) { + return s1.value_tuple().dimensions_value_size() < + s2.value_tuple().dimensions_value_size(); + } + for (int i = 0; i < s1.value_tuple().dimensions_value_size(); ++i) { + if (EqualsTo(s1.value_tuple().dimensions_value(i), + s2.value_tuple().dimensions_value(i))) { + continue; + } else { + return LessThan(s1.value_tuple().dimensions_value(i), + s2.value_tuple().dimensions_value(i)); + } + } + return false; + } + case DimensionsValue::ValueCase::VALUE_NOT_SET: + default: + return false; + } +} + bool HashableDimensionKey::operator==(const HashableDimensionKey& that) const { - return compareDimensionsValue(getDimensionsValue(), that.getDimensionsValue()); + return EqualsTo(getDimensionsValue(), that.getDimensionsValue()); }; bool HashableDimensionKey::operator<(const HashableDimensionKey& that) const { - return toString().compare(that.toString()) < 0; + return LessThan(getDimensionsValue(), that.getDimensionsValue()); }; } // namespace statsd diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp index edc9f2ce6b3c..a4066aa7bca5 100644 --- a/cmds/statsd/src/StatsLogProcessor.cpp +++ b/cmds/statsd/src/StatsLogProcessor.cpp @@ -91,23 +91,22 @@ void StatsLogProcessor::onAnomalyAlarmFired( } void StatsLogProcessor::mapIsolatedUidToHostUidIfNecessaryLocked(LogEvent* event) const { - std::vector<Field> uidFields; + std::set<Field, FieldCmp> uidFields; if (android::util::kAtomsWithAttributionChain.find(event->GetTagId()) != android::util::kAtomsWithAttributionChain.end()) { - findFields( - event->getFieldValueMap(), - buildAttributionUidFieldMatcher(event->GetTagId(), Position::ANY), - &uidFields); + FieldMatcher matcher; + buildAttributionUidFieldMatcher(event->GetTagId(), Position::ANY, &matcher); + findFields(event->getFieldValueMap(), matcher, &uidFields); } else if (android::util::kAtomsWithUidField.find(event->GetTagId()) != android::util::kAtomsWithUidField.end()) { - findFields( - event->getFieldValueMap(), - buildSimpleAtomFieldMatcher(event->GetTagId(), 1 /* uid is always the 1st field. */), - &uidFields); + FieldMatcher matcher; + buildSimpleAtomFieldMatcher( + event->GetTagId(), 1 /* uid is always the 1st field. */, &matcher); + findFields(event->getFieldValueMap(), matcher, &uidFields); } - for (size_t i = 0; i < uidFields.size(); ++i) { - DimensionsValue* value = event->findFieldValueOrNull(uidFields[i]); + for (const auto& uidField : uidFields) { + DimensionsValue* value = event->findFieldValueOrNull(uidField); if (value != nullptr && value->value_case() == DimensionsValue::ValueCase::kValueInt) { const int uid = mUidMap->getHostUidOrSelf(value->value_int()); value->set_value_int(uid); @@ -196,6 +195,14 @@ size_t StatsLogProcessor::GetMetricsSize(const ConfigKey& key) const { return it->second->byteSize(); } +void StatsLogProcessor::dumpStates(FILE* out, bool verbose) { + std::lock_guard<std::mutex> lock(mMetricsMutex); + fprintf(out, "MetricsManager count: %lu\n", (unsigned long)mMetricsManagers.size()); + for (auto metricsManager : mMetricsManagers) { + metricsManager.second->dumpStates(out, verbose); + } +} + void StatsLogProcessor::onDumpReport(const ConfigKey& key, const uint64_t& dumpTimeStampNs, ConfigMetricsReportList* report) { std::lock_guard<std::mutex> lock(mMetricsMutex); diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h index fb85aa837242..c19ff63e2858 100644 --- a/cmds/statsd/src/StatsLogProcessor.h +++ b/cmds/statsd/src/StatsLogProcessor.h @@ -61,6 +61,8 @@ public: return mUidMap; } + void dumpStates(FILE* out, bool verbose); + private: mutable mutex mMetricsMutex; diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp index 31994e1a92d1..f545bb0738e9 100644 --- a/cmds/statsd/src/StatsService.cpp +++ b/cmds/statsd/src/StatsService.cpp @@ -175,8 +175,13 @@ status_t StatsService::dump(int fd, const Vector<String16>& args) { return NO_MEMORY; // the fd is already open } + bool verbose = false; + if (args.size() > 0 && !args[0].compare(String16("-v"))) { + verbose = true; + } + // TODO: Proto format for incident reports - dump_impl(out); + dump_impl(out, verbose); fclose(out); return NO_ERROR; @@ -185,9 +190,9 @@ status_t StatsService::dump(int fd, const Vector<String16>& args) { /** * Write debugging data about statsd in text format. */ -void StatsService::dump_impl(FILE* out) { - mConfigManager->Dump(out); +void StatsService::dump_impl(FILE* out, bool verbose) { StatsdStats::getInstance().dumpStats(out); + mProcessor->dumpStates(out, verbose); } /** diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h index ba6bd2499820..be20893994f1 100644 --- a/cmds/statsd/src/StatsService.h +++ b/cmds/statsd/src/StatsService.h @@ -140,7 +140,7 @@ private: /** * Text output of dumpsys. */ - void dump_impl(FILE* out); + void dump_impl(FILE* out, bool verbose); /** * Print usage information for the commands diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index c9902965ced0..99fd7d1aba33 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -22,6 +22,10 @@ option java_package = "com.android.os"; option java_outer_classname = "AtomsProto"; import "frameworks/base/core/proto/android/app/enums.proto"; +import "frameworks/base/core/proto/android/os/enums.proto"; +import "frameworks/base/core/proto/android/server/enums.proto"; +import "frameworks/base/core/proto/android/telephony/enums.proto"; +import "frameworks/base/core/proto/android/view/enums.proto"; /** * The master atom class. This message defines all of the available @@ -84,33 +88,37 @@ message Atom { AppStartChanged app_start_changed = 48; AppStartCancelChanged app_start_cancel_changed = 49; AppStartFullyDrawnChanged app_start_fully_drawn_changed = 50; - LmkEventOccurred lmk_event_occurred = 51; + LmkKillOccurred lmk_kill_occurred = 51; PictureInPictureStateChanged picture_in_picture_state_changed = 52; WifiMulticastLockStateChanged wifi_multicast_lock_state_changed = 53; + LmkStateChanged lmk_state_changed = 54; + AppStartMemoryStateCaptured app_start_memory_state_captured = 55; + ShutdownSequenceReported shutdown_sequence_reported = 56; // TODO: Reorder the numbering so that the most frequent occur events occur in the first 15. } // Pulled events will start at field 10000. + // Next: 10019 oneof pulled { WifiBytesTransfer wifi_bytes_transfer = 10000; WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 10001; MobileBytesTransfer mobile_bytes_transfer = 10002; MobileBytesTransferByFgBg mobile_bytes_transfer_by_fg_bg = 10003; + BluetoothBytesTransfer bluetooth_bytes_transfer = 10006; KernelWakelock kernel_wakelock = 10004; SubsystemSleepState subsystem_sleep_state = 10005; - // 10006 and 10007 are free to use. CpuTimePerFreq cpu_time_per_freq = 10008; CpuTimePerUid cpu_time_per_uid = 10009; CpuTimePerUidFreq cpu_time_per_uid_freq = 10010; WifiActivityEnergyInfo wifi_activity_energy_info = 10011; ModemActivityInfo modem_activity_info = 10012; - ProcessMemoryStat process_memory_stat = 10013; - CpuSuspendTime cpu_suspend_time = 10014; - CpuIdleTime cpu_idle_time = 10015; + BluetoothActivityInfo bluetooth_activity_info = 10007; + ProcessMemoryState process_memory_state = 10013; + SystemElapsedRealtime system_elapsed_realtime = 10014; + SystemUptime system_uptime = 10015; CpuActiveTime cpu_active_time = 10016; CpuClusterTime cpu_cluster_time = 10017; DiskSpace disk_space = 10018; - SystemUptime system_uptime = 10019; } } @@ -162,18 +170,8 @@ message AttributionNode { * frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java */ message ScreenStateChanged { - // TODO: Use the real screen state. - enum State { - STATE_UNKNOWN = 0; - STATE_OFF = 1; - STATE_ON = 2; - STATE_DOZE = 3; - STATE_DOZE_SUSPEND = 4; - STATE_VR = 5; - STATE_ON_SUSPEND = 6; - } - // New screen state. - optional State display_state = 1; + // New screen state, from frameworks/base/core/proto/android/view/enums.proto. + optional android.view.DisplayStateEnum state = 1; } /** @@ -196,7 +194,6 @@ message UidProcessStateChanged { * frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java */ message ProcessLifeCycleStateChanged { - // TODO: Use the real (mapped) process states. optional int32 uid = 1; // TODO: should be a string tagged w/ uid annotation // TODO: What is this? @@ -412,13 +409,9 @@ message CameraStateChanged { message WakelockStateChanged { repeated AttributionNode attribution_node = 1; - // Type of wakelock. - enum Type { - PARTIAL = 0; - FULL = 1; - WINDOW = 2; - } - optional Type type = 2; + // The type (level) of the wakelock; e.g. a partial wakelock or a full wakelock. + // From frameworks/base/core/proto/android/os/enums.proto. + optional android.os.WakeLockLevelEnum level = 2; // The wakelock tag (Called tag in the Java API, sometimes name elsewhere). optional string tag = 3; @@ -475,13 +468,7 @@ message BatterySaverModeStateChanged { * frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java */ message DeviceIdleModeStateChanged { - // TODO: Use the enum matching BatteryStats.DEVICE_IDLE_MODE_. - enum State { - DEVICE_IDLE_MODE_OFF = 0; - DEVICE_IDLE_MODE_LIGHT = 1; - DEVICE_IDLE_MODE_DEEP = 2; - } - optional State state = 1; + optional android.server.DeviceIdleModeEnum state = 1; } @@ -492,13 +479,7 @@ message DeviceIdleModeStateChanged { * frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java */ message DeviceIdlingModeStateChanged { - // TODO: Use the enum matching BatteryStats.DEVICE_IDLE_MODE_. - enum State { - DEVICE_IDLE_MODE_OFF = 0; - DEVICE_IDLE_MODE_LIGHT = 1; - DEVICE_IDLE_MODE_DEEP = 2; - } - optional State state = 1; + optional android.server.DeviceIdleModeEnum state = 1; } /** @@ -530,15 +511,8 @@ message BatteryLevelChanged { * frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java */ message ChargingStateChanged { - // TODO: Link directly to BatteryManager.java's constants (via a proto). - enum State { - BATTERY_STATUS_UNKNOWN = 1; - BATTERY_STATUS_CHARGING = 2; - BATTERY_STATUS_DISCHARGING = 3; - BATTERY_STATUS_NOT_CHARGING = 4; - BATTERY_STATUS_FULL = 5; - } - optional State charging_state = 1; + // State of the battery, from frameworks/base/core/proto/android/os/enums.proto. + optional android.os.BatteryStatusEnum state = 1; } /** @@ -548,18 +522,8 @@ message ChargingStateChanged { * frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java */ message PluggedStateChanged { - // TODO: Link directly to BatteryManager.java's constants (via a proto). - enum State { - // Note that NONE is not in BatteryManager.java's constants. - BATTERY_PLUGGED_NONE = 0; - // Power source is an AC charger. - BATTERY_PLUGGED_AC = 1; - // Power source is a USB port. - BATTERY_PLUGGED_USB = 2; - // Power source is wireless. - BATTERY_PLUGGED_WIRELESS = 4; - } - optional State plugged_state = 1; + // Whether the device is plugged in, from frameworks/base/core/proto/android/os/enums.proto. + optional android.os.BatteryPluggedStateEnum state = 1; } /** @@ -613,13 +577,8 @@ message MobileRadioPowerStateChanged { // TODO: Add attribution instead of uid? optional int32 uid = 1; - // TODO: Reference telephony/java/android/telephony/DataConnectionRealTimeInfo.java states. - enum PowerState { - DC_POWER_STATE_LOW = 1; - DC_POWER_STATE_MEDIUM = 2; - DC_POWER_STATE_HIGH = 3; - } - optional PowerState power_state = 2; + // Power state, from frameworks/base/core/proto/android/telephony/enums.proto. + optional android.telephony.DataConnectionPowerStateEnum state = 2; } /** @@ -633,13 +592,8 @@ message WifiRadioPowerStateChanged { // TODO: Add attribution instead of uid? optional int32 uid = 1; - // TODO: Reference telephony/java/android/telephony/DataConnectionRealTimeInfo.java states. - enum PowerState { - DC_POWER_STATE_LOW = 1; - DC_POWER_STATE_MEDIUM = 2; - DC_POWER_STATE_HIGH = 3; - } - optional PowerState power_state = 2; + // Power state, from frameworks/base/core/proto/android/telephony/enums.proto. + optional android.telephony.DataConnectionPowerStateEnum state = 2; } /** @@ -679,15 +633,8 @@ message WifiLockStateChanged { * frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java */ message WifiSignalStrengthChanged { - // TODO: Reference the actual telephony/java/android/telephony/SignalStrength.java states. - enum SignalStrength { - SIGNAL_STRENGTH_NONE_OR_UNKNOWN = 0; - SIGNAL_STRENGTH_POOR = 1; - SIGNAL_STRENGTH_MODERATE = 2; - SIGNAL_STRENGTH_GOOD = 3; - SIGNAL_STRENGTH_GREAT = 4; - } - optional SignalStrength signal_strength = 1; + // Signal strength, from frameworks/base/core/proto/android/telephony/enums.proto. + optional android.telephony.SignalStrengthEnum signal_strength = 1; } /** @@ -723,21 +670,35 @@ message WifiMulticastLockStateChanged { } /** + * Logs shutdown reason and duration on next boot. + * + * Logged from: + * frameworks/base/core/java/com/android/server/BootReceiver.java + */ +message ShutdownSequenceReported { + // True if shutdown is for a reboot. Default: false if we do not know. + optional bool reboot = 1; + + // Reason for shutdown. Eg: userrequested. Default: "<EMPTY>". + optional string reason = 2; + + // Beginning of shutdown time in ms using wall clock time since unix epoch. + // Default: 0 if no start time received. + optional int64 start_time_ms = 3; + + // Duration of shutdown in ms. Default: 0 if no duration received. + optional int64 duration_ms = 4; +} + +/** * Logs phone signal strength changes. * * Logged from: * frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java */ message PhoneSignalStrengthChanged { - // TODO: Reference the actual telephony/java/android/telephony/SignalStrength.java states. - enum SignalStrength { - SIGNAL_STRENGTH_NONE_OR_UNKNOWN = 0; - SIGNAL_STRENGTH_POOR = 1; - SIGNAL_STRENGTH_MODERATE = 2; - SIGNAL_STRENGTH_GOOD = 3; - SIGNAL_STRENGTH_GREAT = 4; - } - optional SignalStrength signal_strength = 1; + // Signal strength, from frameworks/base/core/proto/android/telephony/enums.proto. + optional android.telephony.SignalStrengthEnum signal_strength = 1; } /** @@ -890,15 +851,7 @@ message AppStartChanged { // Device uptime when activity started. optional int64 activity_start_msec = 7; - // TODO: Update android/app/ActivityManagerInternal.java constants to depend on our proto enum. - enum TransitionReason { - APP_START_TRANSITION_REASON_UNKNOWN = 0; - SPLASH_SCREEN = 1; - WINDOWS_DRAWN = 2; - TIMEOUT = 3; - SNAPSHOT = 4; - } - optional TransitionReason reason = 8; + optional android.app.AppTransitionReasonEnum reason = 8; optional int32 transition_delay_msec = 9; // -1 if not set. @@ -1060,6 +1013,20 @@ message MobileBytesTransferByFgBg { } /** + * Pulls bytes transferred via bluetooth. It is pulled from Bluetooth controller. + * + * Pulled from: + * StatsCompanionService + */ +message BluetoothBytesTransfer { + optional int32 uid = 1; + + optional int64 rx_bytes = 2; + + optional int64 tx_bytes = 3; +} + +/** * Pulls the kernel wakelock durations. This atom is adapted from * android/internal/os/KernelWakelockStats.java * @@ -1229,32 +1196,106 @@ message ModemActivityInfo { optional uint64 energy_used = 10; } +/** + * Pulls Bluetooth Activity Energy Info + * Note: BluetoothBytesTransfer is pulled at the same time from the controller. + */ +message BluetoothActivityInfo { + // timestamp(wall clock) of record creation + optional uint64 timestamp_ms = 1; + // bluetooth stack state + optional int32 bluetooth_stack_state = 2; + // tx time in ms + optional uint64 controller_tx_time_ms = 3; + // rx time in ms + optional uint64 controller_rx_time_ms = 4; + // idle time in ms + optional uint64 controller_idle_time_ms = 5; + // product of current(mA), voltage(V) and time(ms) + optional uint64 energy_used = 6; +} + /* - * Logs the memory stats for a process + * Logs the memory stats for an app on startup. + * Logged from: + * frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java */ -message ProcessMemoryStat { +message AppStartMemoryStateCaptured { // The uid if available. -1 means not available. optional int32 uid = 1; // The process name. optional string process_name = 2; + // The activity name. + optional string activity_name = 3; + // # of page-faults - optional int64 pgfault = 3; + optional int64 pgfault = 4; // # of major page-faults - optional int64 pgmajfault = 4; + optional int64 pgmajfault = 5; + + // RSS + optional int64 rss_in_bytes = 6; - // RSS+CACHE(+SWAP) - optional int64 usage_in_bytes = 5; + // CACHE + optional int64 cache_in_bytes = 7; + + // SWAP + optional int64 swap_in_bytes = 8; } /* - * Logs the event when LMKD kills a process to reduce memory pressure + * Logs the memory stats for a process. + */ +message ProcessMemoryState { + // The uid if available. -1 means not available. + optional int32 uid = 1; + + // The process name. + optional string process_name = 2; + + // oom adj score. + optional int32 oom_score = 3; + + // # of page-faults + optional int64 pgfault = 4; + + // # of major page-faults + optional int64 pgmajfault = 5; + + // RSS + optional int64 rss_in_bytes = 6; + + // CACHE + optional int64 cache_in_bytes = 7; + + // SWAP + optional int64 swap_in_bytes = 8; +} + +/* + * Logs the change in Low Memory Killer Daemon (LMKD) state which is used as start/stop boundaries + * for LMK event. * Logged from: * system/core/lmkd/lmkd.c */ -message LmkEventOccurred { +message LmkStateChanged { + enum State { + UNKNOWN = 0; + START = 1; + STOP = 2; + } + optional State state = 1; +} + +/* + * Logs the event when Low Memory Killer Daemon (LMKD) kills a process to reduce memory pressure. + * Logged from: + * system/core/lmkd/lmkd.c + */ +message LmkKillOccurred { // The uid if available. -1 means not available. optional int32 uid = 1; @@ -1270,22 +1311,32 @@ message LmkEventOccurred { // # of major page-faults optional int64 pgmajfault = 5; - // RSS+CACHE(+SWAP) - optional int64 usage_in_bytes = 6; + // RSS + optional int64 rss_in_bytes = 6; + + // CACHE + optional int64 cache_in_bytes = 7; + + // SWAP + optional int64 swap_in_bytes = 8; } /* - * Cpu syspend time for cpu power calculation. + * Elapsed real time from SystemClock. */ -message CpuSuspendTime { - optional uint64 time = 1; +message SystemElapsedRealtime { + optional uint64 time_ms = 1; } /* - * Cpu idle time for cpu power calculation. + * Up time from SystemClock. */ -message CpuIdleTime { - optional uint64 time = 1; +message SystemUptime { + // Milliseconds since the system was booted. + // This clock stops when the system enters deep sleep (CPU off, display dark, device waiting + // for external input). + // It is not affected by clock scaling, idle, or other power saving mechanisms. + optional uint64 uptime_ms = 1; } /* @@ -1329,14 +1380,3 @@ message DiskSpace { // available bytes in download cache or temp directories optional uint64 temp_available_bytes = 3; } - -/* - * Pulls system up time. - */ -message SystemUptime { - // Milliseconds since the system was booted. - // This clock stops when the system enters deep sleep (CPU off, display dark, device waiting - // for external input). - // It is not affected by clock scaling, idle, or other power saving mechanisms. - optional uint64 uptime_ms = 1; -} diff --git a/cmds/statsd/src/condition/SimpleConditionTracker.cpp b/cmds/statsd/src/condition/SimpleConditionTracker.cpp index 7a1bb0c71373..5cfc349ea46a 100644 --- a/cmds/statsd/src/condition/SimpleConditionTracker.cpp +++ b/cmds/statsd/src/condition/SimpleConditionTracker.cpp @@ -289,7 +289,8 @@ void SimpleConditionTracker::evaluateCondition(const LogEvent& event, } // outputKey is the output values. e.g, uid:1234 - const std::vector<DimensionsValue> outputValues = getDimensionKeys(event, mOutputDimensions); + std::vector<DimensionsValue> outputValues; + getDimensionKeys(event, mOutputDimensions, &outputValues); if (outputValues.size() == 0) { // The original implementation would generate an empty string dimension hash when condition // is not sliced. diff --git a/cmds/statsd/src/condition/condition_util.cpp b/cmds/statsd/src/condition/condition_util.cpp index ddfb8d12a335..3b2d480b3ebf 100644 --- a/cmds/statsd/src/condition/condition_util.cpp +++ b/cmds/statsd/src/condition/condition_util.cpp @@ -116,28 +116,30 @@ void OrBooleanVector(const std::vector<bool>& ref, vector<bool> * ored) { } } -void getFieldsFromFieldMatcher(const FieldMatcher& matcher, const Field& parentField, - std::vector<Field> *allFields) { - Field newParent = parentField; - Field* leaf = getSingleLeaf(&newParent); - leaf->set_field(matcher.field()); +void getFieldsFromFieldMatcher(const FieldMatcher& matcher, Field* rootField, Field* leafField, + std::vector<Field> *allFields) { if (matcher.child_size() == 0) { - allFields->push_back(newParent); + allFields->push_back(*rootField); return; } for (int i = 0; i < matcher.child_size(); ++i) { - leaf->add_child(); - getFieldsFromFieldMatcher(matcher.child(i), newParent, allFields); + Field* newLeafField = leafField->add_child(); + newLeafField->set_field(matcher.child(i).field()); + getFieldsFromFieldMatcher(matcher.child(i), rootField, newLeafField, allFields); } } void getFieldsFromFieldMatcher(const FieldMatcher& matcher, std::vector<Field> *allFields) { - Field parentField; - getFieldsFromFieldMatcher(matcher, parentField, allFields); + if (!matcher.has_field()) { + return; + } + Field rootField; + rootField.set_field(matcher.field()); + getFieldsFromFieldMatcher(matcher, &rootField, &rootField, allFields); } void flattenValueLeaves(const DimensionsValue& value, - std::vector<DimensionsValue> *allLaves) { + std::vector<const DimensionsValue*> *allLaves) { switch (value.value_case()) { case DimensionsValue::ValueCase::kValueStr: case DimensionsValue::ValueCase::kValueInt: @@ -145,7 +147,7 @@ void flattenValueLeaves(const DimensionsValue& value, case DimensionsValue::ValueCase::kValueBool: case DimensionsValue::ValueCase::kValueFloat: case DimensionsValue::ValueCase::VALUE_NOT_SET: - allLaves->push_back(value); + allLaves->push_back(&value); break; case DimensionsValue::ValueCase::kValueTuple: for (int i = 0; i < value.value_tuple().dimensions_value_size(); ++i) { @@ -155,45 +157,44 @@ void flattenValueLeaves(const DimensionsValue& value, } } -std::vector<HashableDimensionKey> getDimensionKeysForCondition( - const LogEvent& event, const MetricConditionLink& link) { +void getDimensionKeysForCondition( + const LogEvent& event, const MetricConditionLink& link, + std::vector<HashableDimensionKey> *hashableDimensionKeys) { std::vector<Field> whatFields; getFieldsFromFieldMatcher(link.fields_in_what(), &whatFields); std::vector<Field> conditionFields; getFieldsFromFieldMatcher(link.fields_in_condition(), &conditionFields); - std::vector<HashableDimensionKey> hashableDimensionKeys; - // TODO(yanglu): here we could simplify the logic to get the leaf value node in what and // directly construct the full condition value tree. - std::vector<DimensionsValue> whatValues = getDimensionKeys(event, link.fields_in_what()); + std::vector<DimensionsValue> whatValues; + getDimensionKeys(event, link.fields_in_what(), &whatValues); for (size_t i = 0; i < whatValues.size(); ++i) { - std::vector<DimensionsValue> whatLeaves; + std::vector<const DimensionsValue*> whatLeaves; flattenValueLeaves(whatValues[i], &whatLeaves); if (whatLeaves.size() != whatFields.size() || whatLeaves.size() != conditionFields.size()) { ALOGE("Dimensions between what and condition not equal."); - return hashableDimensionKeys; + return; } FieldValueMap conditionValueMap; for (size_t j = 0; j < whatLeaves.size(); ++j) { - if (!setFieldInLeafValueProto(conditionFields[j], &whatLeaves[j])) { + DimensionsValue* conditionValue = &conditionValueMap[conditionFields[j]]; + *conditionValue = *whatLeaves[i]; + if (!setFieldInLeafValueProto(conditionFields[j], conditionValue)) { ALOGE("Not able to reset the field for condition leaf value."); - return hashableDimensionKeys; + return; } - conditionValueMap.insert(std::make_pair(conditionFields[j], whatLeaves[j])); } - std::vector<DimensionsValue> conditionValues; - findDimensionsValues(conditionValueMap, link.fields_in_condition(), &conditionValues); - if (conditionValues.size() != 1) { + std::vector<DimensionsValue> conditionValueTrees; + findDimensionsValues(conditionValueMap, link.fields_in_condition(), &conditionValueTrees); + if (conditionValueTrees.size() != 1) { ALOGE("Not able to find unambiguous field value in condition atom."); continue; } - hashableDimensionKeys.push_back(HashableDimensionKey(conditionValues[0])); + hashableDimensionKeys->push_back(HashableDimensionKey(conditionValueTrees[0])); } - - return hashableDimensionKeys; } } // namespace statsd diff --git a/cmds/statsd/src/condition/condition_util.h b/cmds/statsd/src/condition/condition_util.h index 598027b7e366..a7288beb69ca 100644 --- a/cmds/statsd/src/condition/condition_util.h +++ b/cmds/statsd/src/condition/condition_util.h @@ -40,8 +40,9 @@ ConditionState evaluateCombinationCondition(const std::vector<int>& children, const LogicalOperation& operation, const std::vector<ConditionState>& conditionCache); -std::vector<HashableDimensionKey> getDimensionKeysForCondition( - const LogEvent& event, const MetricConditionLink& link); +void getDimensionKeysForCondition( + const LogEvent& event, const MetricConditionLink& link, + std::vector<HashableDimensionKey> *dimensionKeys); } // namespace statsd } // namespace os } // namespace android diff --git a/cmds/statsd/src/dimension.cpp b/cmds/statsd/src/dimension.cpp index bb7a044fa8ce..04445ca0e230 100644 --- a/cmds/statsd/src/dimension.cpp +++ b/cmds/statsd/src/dimension.cpp @@ -38,7 +38,7 @@ DimensionsValue getSingleLeafValue(const DimensionsValue& value) { return *leafValue; } -void appendLeafNodeToParent(const Field& field, +void appendLeafNodeToTree(const Field& field, const DimensionsValue& value, DimensionsValue* parentValue) { if (field.child_size() <= 0) { @@ -58,24 +58,24 @@ void appendLeafNodeToParent(const Field& field, parentValue->mutable_value_tuple()->add_dimensions_value(); idx = parentValue->mutable_value_tuple()->dimensions_value_size() - 1; } - appendLeafNodeToParent( + appendLeafNodeToTree( field.child(0), value, parentValue->mutable_value_tuple()->mutable_dimensions_value(idx)); } -void addNodeToRootDimensionsValues(const Field& field, - const DimensionsValue& node, - std::vector<DimensionsValue>* rootValues) { - if (rootValues == nullptr) { +void appendLeafNodeToTrees(const Field& field, + const DimensionsValue& node, + std::vector<DimensionsValue>* rootTrees) { + if (rootTrees == nullptr) { return; } - if (rootValues->empty()) { - DimensionsValue rootValue; - appendLeafNodeToParent(field, node, &rootValue); - rootValues->push_back(rootValue); + if (rootTrees->empty()) { + DimensionsValue tree; + appendLeafNodeToTree(field, node, &tree); + rootTrees->push_back(tree); } else { - for (size_t i = 0; i < rootValues->size(); ++i) { - appendLeafNodeToParent(field, node, &rootValues->at(i)); + for (size_t i = 0; i < rootTrees->size(); ++i) { + appendLeafNodeToTree(field, node, &rootTrees->at(i)); } } } @@ -85,22 +85,25 @@ namespace { void findDimensionsValues( const FieldValueMap& fieldValueMap, const FieldMatcher& matcher, - const Field& field, + Field* rootField, + Field* leafField, std::vector<DimensionsValue>* rootDimensionsValues); void findNonRepeatedDimensionsValues( const FieldValueMap& fieldValueMap, const FieldMatcher& matcher, - const Field& field, + Field* rootField, + Field* leafField, std::vector<DimensionsValue>* rootValues) { if (matcher.child_size() > 0) { + Field* newLeafField = leafField->add_child(); for (const auto& childMatcher : matcher.child()) { - Field childField = field; - appendLeaf(&childField, childMatcher.field()); - findDimensionsValues(fieldValueMap, childMatcher, childField, rootValues); + newLeafField->set_field(childMatcher.field()); + findDimensionsValues(fieldValueMap, childMatcher, rootField, newLeafField, rootValues); } + leafField->clear_child(); } else { - auto ret = fieldValueMap.equal_range(field); + auto ret = fieldValueMap.equal_range(*rootField); int found = 0; for (auto it = ret.first; it != ret.second; ++it) { found++; @@ -113,40 +116,43 @@ void findNonRepeatedDimensionsValues( ALOGE("Found multiple values for optional field."); return; } - addNodeToRootDimensionsValues(field, ret.first->second, rootValues); + appendLeafNodeToTrees(*rootField, ret.first->second, rootValues); } } void findRepeatedDimensionsValues(const FieldValueMap& fieldValueMap, const FieldMatcher& matcher, - const Field& field, + Field* rootField, + Field* leafField, std::vector<DimensionsValue>* rootValues) { if (matcher.position() == Position::FIRST) { - Field first_field = field; - setPositionForLeaf(&first_field, 0); - findNonRepeatedDimensionsValues(fieldValueMap, matcher, first_field, rootValues); + leafField->set_position_index(0); + findNonRepeatedDimensionsValues(fieldValueMap, matcher, rootField, leafField, rootValues); + leafField->clear_position_index(); } else { - auto itLower = fieldValueMap.lower_bound(field); + auto itLower = fieldValueMap.lower_bound(*rootField); if (itLower == fieldValueMap.end()) { return; } - Field next_field = field; - getNextField(&next_field); - auto itUpper = fieldValueMap.lower_bound(next_field); + const int leafFieldNum = leafField->field(); + leafField->set_field(leafFieldNum + 1); + auto itUpper = fieldValueMap.lower_bound(*rootField); + // Resets the field number. + leafField->set_field(leafFieldNum); switch (matcher.position()) { case Position::LAST: { itUpper--; if (itUpper != fieldValueMap.end()) { - Field last_field = field; - int last_index = getPositionByReferenceField(field, itUpper->first); + int last_index = getPositionByReferenceField(*rootField, itUpper->first); if (last_index < 0) { return; } - setPositionForLeaf(&last_field, last_index); + leafField->set_position_index(last_index); findNonRepeatedDimensionsValues( - fieldValueMap, matcher, last_field, rootValues); + fieldValueMap, matcher, rootField, leafField, rootValues); + leafField->clear_position_index(); } } break; @@ -154,20 +160,20 @@ void findRepeatedDimensionsValues(const FieldValueMap& fieldValueMap, { std::set<int> indexes; for (auto it = itLower; it != itUpper; ++it) { - int index = getPositionByReferenceField(field, it->first); + int index = getPositionByReferenceField(*rootField, it->first); if (index >= 0) { indexes.insert(index); } } if (!indexes.empty()) { - Field any_field = field; std::vector<DimensionsValue> allValues; for (const int index : indexes) { - setPositionForLeaf(&any_field, index); + leafField->set_position_index(index); std::vector<DimensionsValue> newValues = *rootValues; findNonRepeatedDimensionsValues( - fieldValueMap, matcher, any_field, &newValues); + fieldValueMap, matcher, rootField, leafField, &newValues); allValues.insert(allValues.end(), newValues.begin(), newValues.end()); + leafField->clear_position_index(); } rootValues->clear(); rootValues->insert(rootValues->end(), allValues.begin(), allValues.end()); @@ -183,12 +189,15 @@ void findRepeatedDimensionsValues(const FieldValueMap& fieldValueMap, void findDimensionsValues( const FieldValueMap& fieldValueMap, const FieldMatcher& matcher, - const Field& field, + Field* rootField, + Field* leafField, std::vector<DimensionsValue>* rootDimensionsValues) { if (!matcher.has_position()) { - findNonRepeatedDimensionsValues(fieldValueMap, matcher, field, rootDimensionsValues); + findNonRepeatedDimensionsValues(fieldValueMap, matcher, rootField, leafField, + rootDimensionsValues); } else { - findRepeatedDimensionsValues(fieldValueMap, matcher, field, rootDimensionsValues); + findRepeatedDimensionsValues(fieldValueMap, matcher, rootField, leafField, + rootDimensionsValues); } } @@ -198,56 +207,49 @@ void findDimensionsValues( const FieldValueMap& fieldValueMap, const FieldMatcher& matcher, std::vector<DimensionsValue>* rootDimensionsValues) { - findDimensionsValues(fieldValueMap, matcher, - buildSimpleAtomField(matcher.field()), rootDimensionsValues); + Field rootField; + buildSimpleAtomField(matcher.field(), &rootField); + findDimensionsValues(fieldValueMap, matcher, &rootField, &rootField, rootDimensionsValues); } -FieldMatcher buildSimpleAtomFieldMatcher(const int tagId) { - FieldMatcher matcher; - matcher.set_field(tagId); - return matcher; +void buildSimpleAtomFieldMatcher(const int tagId, FieldMatcher* matcher) { + matcher->set_field(tagId); } -FieldMatcher buildSimpleAtomFieldMatcher(const int tagId, const int atomFieldNum) { - FieldMatcher matcher; - matcher.set_field(tagId); - matcher.add_child()->set_field(atomFieldNum); - return matcher; +void buildSimpleAtomFieldMatcher(const int tagId, const int fieldNum, FieldMatcher* matcher) { + matcher->set_field(tagId); + matcher->add_child()->set_field(fieldNum); } constexpr int ATTRIBUTION_FIELD_NUM_IN_ATOM_PROTO = 1; constexpr int UID_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO = 1; constexpr int TAG_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO = 2; -FieldMatcher buildAttributionUidFieldMatcher(const int tagId, const Position position) { - FieldMatcher matcher; - matcher.set_field(tagId); - auto child = matcher.add_child(); +void buildAttributionUidFieldMatcher(const int tagId, const Position position, + FieldMatcher* matcher) { + matcher->set_field(tagId); + auto child = matcher->add_child(); child->set_field(ATTRIBUTION_FIELD_NUM_IN_ATOM_PROTO); child->set_position(position); child->add_child()->set_field(UID_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO); - return matcher; } -FieldMatcher buildAttributionTagFieldMatcher(const int tagId, const Position position) { - FieldMatcher matcher; - matcher.set_field(tagId); - FieldMatcher* child = matcher.add_child(); +void buildAttributionTagFieldMatcher(const int tagId, const Position position, + FieldMatcher* matcher) { + matcher->set_field(tagId); + FieldMatcher* child = matcher->add_child(); child->set_field(ATTRIBUTION_FIELD_NUM_IN_ATOM_PROTO); child->set_position(position); child->add_child()->set_field(TAG_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO); - return matcher; } -FieldMatcher buildAttributionFieldMatcher(const int tagId, const Position position) { - FieldMatcher matcher; - matcher.set_field(tagId); - FieldMatcher* child = matcher.add_child(); +void buildAttributionFieldMatcher(const int tagId, const Position position, FieldMatcher* matcher) { + matcher->set_field(tagId); + FieldMatcher* child = matcher->add_child(); child->set_field(ATTRIBUTION_FIELD_NUM_IN_ATOM_PROTO); child->set_position(position); child->add_child()->set_field(UID_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO); child->add_child()->set_field(TAG_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO); - return matcher; } void DimensionsValueToString(const DimensionsValue& value, std::string *flattened) { @@ -284,28 +286,6 @@ void DimensionsValueToString(const DimensionsValue& value, std::string *flattene } } -void getDimensionsValueLeafNodes( - const DimensionsValue& value, std::vector<DimensionsValue> *leafNodes) { - switch (value.value_case()) { - case DimensionsValue::ValueCase::kValueStr: - case DimensionsValue::ValueCase::kValueInt: - case DimensionsValue::ValueCase::kValueLong: - case DimensionsValue::ValueCase::kValueBool: - case DimensionsValue::ValueCase::kValueFloat: - leafNodes->push_back(value); - break; - case DimensionsValue::ValueCase::kValueTuple: - for (int i = 0; i < value.value_tuple().dimensions_value_size(); ++i) { - getDimensionsValueLeafNodes(value.value_tuple().dimensions_value(i), leafNodes); - } - break; - case DimensionsValue::ValueCase::VALUE_NOT_SET: - break; - default: - break; - } -} - std::string DimensionsValueToString(const DimensionsValue& value) { std::string flatten; DimensionsValueToString(value, &flatten); diff --git a/cmds/statsd/src/dimension.h b/cmds/statsd/src/dimension.h index d0f96a2abe6b..e900c5e87227 100644 --- a/cmds/statsd/src/dimension.h +++ b/cmds/statsd/src/dimension.h @@ -33,8 +33,7 @@ const DimensionsValue* getSingleLeafValue(const DimensionsValue* value); DimensionsValue getSingleLeafValue(const DimensionsValue& value); // Appends the leaf node to the parent tree. -void appendLeafNodeToParent(const Field& field, const DimensionsValue& value, - DimensionsValue* parentValue); +void appendLeafNodeToTree(const Field& field, const DimensionsValue& value, DimensionsValue* tree); // Constructs the DimensionsValue protos from the FieldMatcher. Each DimensionsValue proto // represents a tree. When the input proto has repeated fields and the input "dimensions" wants @@ -45,13 +44,16 @@ void findDimensionsValues( std::vector<DimensionsValue>* rootDimensionsValues); // Utils to build FieldMatcher proto for simple one-depth atoms. -FieldMatcher buildSimpleAtomFieldMatcher(const int tagId, const int atomFieldNum); -FieldMatcher buildSimpleAtomFieldMatcher(const int tagId); +void buildSimpleAtomFieldMatcher(const int tagId, const int atomFieldNum, FieldMatcher* matcher); +void buildSimpleAtomFieldMatcher(const int tagId, FieldMatcher* matcher); // Utils to build FieldMatcher proto for attribution nodes. -FieldMatcher buildAttributionUidFieldMatcher(const int tagId, const Position position); -FieldMatcher buildAttributionTagFieldMatcher(const int tagId, const Position position); -FieldMatcher buildAttributionFieldMatcher(const int tagId, const Position position); +void buildAttributionUidFieldMatcher(const int tagId, const Position position, + FieldMatcher* matcher); +void buildAttributionTagFieldMatcher(const int tagId, const Position position, + FieldMatcher* matcher); +void buildAttributionFieldMatcher(const int tagId, const Position position, + FieldMatcher* matcher); // Utils to print pretty string for DimensionsValue proto. std::string DimensionsValueToString(const DimensionsValue& value); diff --git a/cmds/statsd/src/external/StatsPullerManagerImpl.cpp b/cmds/statsd/src/external/StatsPullerManagerImpl.cpp index e06ae48f7215..148c9ae9b249 100644 --- a/cmds/statsd/src/external/StatsPullerManagerImpl.cpp +++ b/cmds/statsd/src/external/StatsPullerManagerImpl.cpp @@ -64,12 +64,20 @@ StatsPullerManagerImpl::StatsPullerManagerImpl() mPullers.insert({android::util::CPU_TIME_PER_FREQ, make_shared<StatsCompanionServicePuller>(android::util::CPU_TIME_PER_FREQ)}); mPullers.insert({android::util::CPU_TIME_PER_UID, make_shared<CpuTimePerUidPuller>()}); mPullers.insert({android::util::CPU_TIME_PER_UID_FREQ, make_shared<CpuTimePerUidFreqPuller>()}); - mPullers.insert({android::util::CPU_SUSPEND_TIME, make_shared<StatsCompanionServicePuller>(android::util::CPU_SUSPEND_TIME)}); - mPullers.insert({android::util::CPU_IDLE_TIME, make_shared<StatsCompanionServicePuller>(android::util::CPU_IDLE_TIME)}); - mPullers.insert({android::util::DISK_SPACE, - make_shared<StatsCompanionServicePuller>(android::util::DISK_SPACE)}); + mPullers.insert( + {android::util::SYSTEM_ELAPSED_REALTIME, + make_shared<StatsCompanionServicePuller>(android::util::SYSTEM_ELAPSED_REALTIME)}); mPullers.insert({android::util::SYSTEM_UPTIME, make_shared<StatsCompanionServicePuller>(android::util::SYSTEM_UPTIME)}); + mPullers.insert({android::util::DISK_SPACE, + make_shared<StatsCompanionServicePuller>(android::util::DISK_SPACE)}); + mPullers.insert( + {android::util::BLUETOOTH_ACTIVITY_INFO, + make_shared<StatsCompanionServicePuller>(android::util::BLUETOOTH_ACTIVITY_INFO)}); + + mPullers.insert( + {android::util::BLUETOOTH_BYTES_TRANSFER, + make_shared<StatsCompanionServicePuller>(android::util::BLUETOOTH_BYTES_TRANSFER)}); mPullers.insert( {android::util::WIFI_ACTIVITY_ENERGY_INFO, make_shared<StatsCompanionServicePuller>(android::util::WIFI_ACTIVITY_ENERGY_INFO)}); diff --git a/cmds/statsd/src/field_util.cpp b/cmds/statsd/src/field_util.cpp index 4ff4f74f7979..acf64fe12e6d 100644 --- a/cmds/statsd/src/field_util.cpp +++ b/cmds/statsd/src/field_util.cpp @@ -102,24 +102,13 @@ bool setFieldInLeafValueProto(const Field &field, DimensionsValue* leafValue) { } } -Field buildAtomField(const int tagId, const Field &atomField) { - Field field; - *field.add_child() = atomField; - field.set_field(tagId); - return field; +void buildSimpleAtomField(const int tagId, const int atomFieldNum, Field *field) { + field->set_field(tagId); + field->add_child()->set_field(atomFieldNum); } -Field buildSimpleAtomField(const int tagId, const int atomFieldNum) { - Field field; - field.set_field(tagId); - field.add_child()->set_field(atomFieldNum); - return field; -} - -Field buildSimpleAtomField(const int tagId) { - Field field; - field.set_field(tagId); - return field; +void buildSimpleAtomField(const int tagId, Field *field) { + field->set_field(tagId); } void appendLeaf(Field *parent, int node_field_num) { @@ -145,18 +134,6 @@ void appendLeaf(Field *parent, int node_field_num, int position) { } } - -void getNextField(Field* field) { - if (field->child_size() <= 0) { - field->set_field(field->field() + 1); - return; - } - if (field->child_size() != 1) { - return; - } - getNextField(field->mutable_child(0)); -} - void increasePosition(Field *field) { if (!field->has_position_index()) { field->set_position_index(0); @@ -176,34 +153,30 @@ int getPositionByReferenceField(const Field& ref, const Field& field_with_index) return getPositionByReferenceField(ref.child(0), field_with_index.child(0)); } -void setPositionForLeaf(Field *field, int index) { - if (field->child_size() <= 0) { - field->set_position_index(index); - } else { - setPositionForLeaf(field->mutable_child(0), index); - } -} - namespace { + void findFields( const FieldValueMap& fieldValueMap, const FieldMatcher& matcher, - const Field& field, - std::vector<Field>* rootFields); + Field* rootField, + Field* leafField, + std::set<Field, FieldCmp>* rootFields); void findNonRepeatedFields( const FieldValueMap& fieldValueMap, const FieldMatcher& matcher, - const Field& field, - std::vector<Field>* rootFields) { + Field* rootField, + Field* leafField, + std::set<Field, FieldCmp>* rootFields) { if (matcher.child_size() > 0) { + Field* newLeafField = leafField->add_child(); for (const auto& childMatcher : matcher.child()) { - Field childField = field; - appendLeaf(&childField, childMatcher.field()); - findFields(fieldValueMap, childMatcher, childField, rootFields); + newLeafField->set_field(childMatcher.field()); + findFields(fieldValueMap, childMatcher, rootField, newLeafField, rootFields); } + leafField->clear_child(); } else { - auto ret = fieldValueMap.equal_range(field); + auto ret = fieldValueMap.equal_range(*rootField); int found = 0; for (auto it = ret.first; it != ret.second; ++it) { found++; @@ -216,38 +189,42 @@ void findNonRepeatedFields( ALOGE("Found multiple values for optional field."); return; } - rootFields->push_back(ret.first->first); + rootFields->insert(ret.first->first); } } void findRepeatedFields(const FieldValueMap& fieldValueMap, const FieldMatcher& matcher, - const Field& field, std::vector<Field>* rootFields) { + Field* rootField, Field* leafField, + std::set<Field, FieldCmp>* rootFields) { if (matcher.position() == Position::FIRST) { - Field first_field = field; - setPositionForLeaf(&first_field, 0); - findNonRepeatedFields(fieldValueMap, matcher, first_field, rootFields); + leafField->set_position_index(0); + findNonRepeatedFields(fieldValueMap, matcher, rootField, leafField, rootFields); + leafField->clear_position_index(); } else { - auto itLower = fieldValueMap.lower_bound(field); + auto itLower = fieldValueMap.lower_bound(*rootField); if (itLower == fieldValueMap.end()) { return; } - Field next_field = field; - getNextField(&next_field); - auto itUpper = fieldValueMap.lower_bound(next_field); + + const int leafFieldNum = leafField->field(); + leafField->set_field(leafFieldNum + 1); + auto itUpper = fieldValueMap.lower_bound(*rootField); + // Resets the field number. + leafField->set_field(leafFieldNum); switch (matcher.position()) { case Position::LAST: { itUpper--; if (itUpper != fieldValueMap.end()) { - Field last_field = field; - int last_index = getPositionByReferenceField(field, itUpper->first); + int last_index = getPositionByReferenceField(*rootField, itUpper->first); if (last_index < 0) { return; } - setPositionForLeaf(&last_field, last_index); + leafField->set_position_index(last_index); findNonRepeatedFields( - fieldValueMap, matcher, last_field, rootFields); + fieldValueMap, matcher, rootField, leafField, rootFields); + leafField->clear_position_index(); } } break; @@ -255,17 +232,17 @@ void findRepeatedFields(const FieldValueMap& fieldValueMap, const FieldMatcher& { std::set<int> indexes; for (auto it = itLower; it != itUpper; ++it) { - int index = getPositionByReferenceField(field, it->first); + int index = getPositionByReferenceField(*rootField, it->first); if (index >= 0) { indexes.insert(index); } } if (!indexes.empty()) { - Field any_field = field; for (const int index : indexes) { - setPositionForLeaf(&any_field, index); + leafField->set_position_index(index); findNonRepeatedFields( - fieldValueMap, matcher, any_field, rootFields); + fieldValueMap, matcher, rootField, leafField, rootFields); + leafField->clear_position_index(); } } } @@ -279,12 +256,13 @@ void findRepeatedFields(const FieldValueMap& fieldValueMap, const FieldMatcher& void findFields( const FieldValueMap& fieldValueMap, const FieldMatcher& matcher, - const Field& field, - std::vector<Field>* rootFields) { + Field* rootField, + Field* leafField, + std::set<Field, FieldCmp>* rootFields) { if (!matcher.has_position()) { - findNonRepeatedFields(fieldValueMap, matcher, field, rootFields); + findNonRepeatedFields(fieldValueMap, matcher, rootField, leafField, rootFields); } else { - findRepeatedFields(fieldValueMap, matcher, field, rootFields); + findRepeatedFields(fieldValueMap, matcher, rootField, leafField, rootFields); } } @@ -293,17 +271,24 @@ void findFields( void findFields( const FieldValueMap& fieldValueMap, const FieldMatcher& matcher, - std::vector<Field>* rootFields) { - return findFields(fieldValueMap, matcher, buildSimpleAtomField(matcher.field()), rootFields); + std::set<Field, FieldCmp>* rootFields) { + if (!matcher.has_field() || fieldValueMap.empty()) { + return; + } + Field rootField; + buildSimpleAtomField(matcher.field(), &rootField); + return findFields(fieldValueMap, matcher, &rootField, &rootField, rootFields); } void filterFields(const FieldMatcher& matcher, FieldValueMap* fieldValueMap) { - std::vector<Field> rootFields; + if (!matcher.has_field()) { + return; + } + std::set<Field, FieldCmp> rootFields; findFields(*fieldValueMap, matcher, &rootFields); - std::set<Field, FieldCmp> rootFieldSet(rootFields.begin(), rootFields.end()); auto it = fieldValueMap->begin(); while (it != fieldValueMap->end()) { - if (rootFieldSet.find(it->first) == rootFieldSet.end()) { + if (rootFields.find(it->first) == rootFields.end()) { it = fieldValueMap->erase(it); } else { it++; diff --git a/cmds/statsd/src/field_util.h b/cmds/statsd/src/field_util.h index a4dfdddf210b..b04465dc9862 100644 --- a/cmds/statsd/src/field_util.h +++ b/cmds/statsd/src/field_util.h @@ -20,7 +20,8 @@ #include "frameworks/base/cmds/statsd/src/statsd_internal.pb.h" #include "frameworks/base/cmds/statsd/src/stats_log.pb.h" -#include <unordered_map> +#include <map> +#include <set> namespace android { namespace os { @@ -54,15 +55,9 @@ Field* getSingleLeaf(Field* field); void appendLeaf(Field *parent, int node_field_num); void appendLeaf(Field *parent, int node_field_num, int position); -// Given the field sorting logic, this function is to increase the "field" at the leaf node. -void getNextField(Field* field); - // Increase the position index for the node. If the "position_index" is not set, set it as 0. void increasePosition(Field *field); -// Finds the leaf node and set the index there. -void setPositionForLeaf(Field *field, int index); - // Returns true if the matcher has specified at least one leaf node. bool hasLeafNode(const FieldMatcher& matcher); @@ -72,15 +67,13 @@ bool hasLeafNode(const FieldMatcher& matcher); int getPositionByReferenceField(const Field& reference, const Field& field_with_index); // Utils to build the Field proto for simple atom fields. -Field buildAtomField(const int tagId, const Field &atomField); -Field buildSimpleAtomField(const int tagId, const int atomFieldNum); -Field buildSimpleAtomField(const int tagId); +void buildSimpleAtomField(const int tagId, const int atomFieldNum, Field* field); +void buildSimpleAtomField(const int tagId, Field* field); // Find out all the fields specified by the matcher. void findFields( - const FieldValueMap& fieldValueMap, - const FieldMatcher& matcher, - std::vector<Field>* rootFields); + const FieldValueMap& fieldValueMap, const FieldMatcher& matcher, + std::set<Field, FieldCmp>* rootFields); // Filter out the fields not in the field matcher. void filterFields(const FieldMatcher& matcher, FieldValueMap* fieldValueMap); diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp index 63bde7d82372..77f54569cb47 100644 --- a/cmds/statsd/src/guardrail/StatsdStats.cpp +++ b/cmds/statsd/src/guardrail/StatsdStats.cpp @@ -45,6 +45,8 @@ const int FIELD_ID_CONFIG_STATS = 3; const int FIELD_ID_ATOM_STATS = 7; const int FIELD_ID_UIDMAP_STATS = 8; const int FIELD_ID_ANOMALY_ALARM_STATS = 9; +const int FIELD_ID_PULLED_ATOM_STATS = 10; +const int FIELD_ID_LOGGER_ERROR_STATS = 11; const int FIELD_ID_MATCHER_STATS_NAME = 1; const int FIELD_ID_MATCHER_STATS_COUNT = 2; @@ -60,6 +62,9 @@ const int FIELD_ID_ATOM_STATS_COUNT = 2; const int FIELD_ID_ANOMALY_ALARMS_REGISTERED = 1; +const int FIELD_ID_LOGGER_STATS_TIME = 1; +const int FIELD_ID_LOGGER_STATS_ERROR_CODE = 2; + std::map<int, long> StatsdStats::kPullerCooldownMap = { {android::util::KERNEL_WAKELOCK, 1}, {android::util::WIFI_BYTES_TRANSFER, 1}, @@ -282,6 +287,15 @@ void StatsdStats::noteAtomLogged(int atomId, int32_t timeSec) { mPushedAtomStats[atomId]++; } +void StatsdStats::noteLoggerError(int error) { + lock_guard<std::mutex> lock(mLock); + // grows strictly one at a time. so it won't > kMaxLoggerErrors + if (mLoggerErrors.size() == kMaxLoggerErrors) { + mLoggerErrors.pop_front(); + } + mLoggerErrors.push_back(std::make_pair(time(nullptr), error)); +} + void StatsdStats::reset() { lock_guard<std::mutex> lock(mLock); resetInternalLocked(); @@ -297,6 +311,7 @@ void StatsdStats::resetInternalLocked() { mAlertStats.clear(); mAnomalyAlarmRegisteredStats = 0; mMatcherStats.clear(); + mLoggerErrors.clear(); for (auto& config : mConfigStats) { config.second.clear_broadcast_sent_time_sec(); config.second.clear_data_drop_time_sec(); @@ -465,6 +480,14 @@ void StatsdStats::dumpStats(FILE* out) const { "lost=%d\n", mUidMapStats.bytes_used(), mUidMapStats.snapshots(), mUidMapStats.changes(), mUidMapStats.dropped_snapshots(), mUidMapStats.dropped_changes()); + + for (const auto& error : mLoggerErrors) { + time_t error_time = error.first; + struct tm* error_tm = localtime(&error_time); + char buffer[80]; + strftime(buffer, sizeof(buffer), "%Y-%m-%d %I:%M%p\n", error_tm); + fprintf(out, "Logger error %d at %s\n", error.second, buffer); + } } void StatsdStats::dumpStats(std::vector<uint8_t>* output, bool reset) { @@ -526,6 +549,14 @@ void StatsdStats::dumpStats(std::vector<uint8_t>* output, bool reset) { mUidMapStats.SerializeToArray(&buffer[0], numBytes); proto.write(FIELD_TYPE_MESSAGE | FIELD_ID_UIDMAP_STATS, &buffer[0], buffer.size()); + for (const auto& error : mLoggerErrors) { + long long token = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_LOGGER_ERROR_STATS | + FIELD_COUNT_REPEATED); + proto.write(FIELD_TYPE_INT32 | FIELD_ID_LOGGER_STATS_TIME, error.first); + proto.write(FIELD_TYPE_INT32 | FIELD_ID_LOGGER_STATS_ERROR_CODE, error.second); + proto.end(token); + } + output->clear(); size_t bufferSize = proto.size(); output->resize(bufferSize); diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h index 7cb48ead55d8..1f4bfa62c453 100644 --- a/cmds/statsd/src/guardrail/StatsdStats.h +++ b/cmds/statsd/src/guardrail/StatsdStats.h @@ -49,6 +49,8 @@ public: // The max number of old config stats we keep. const static int kMaxIceBoxSize = 20; + const static int kMaxLoggerErrors = 10; + const static int kMaxTimestampCount = 20; const static int kMaxLogSourceCount = 50; @@ -185,6 +187,11 @@ public: void notePullFromCache(int pullAtomId); /** + * Records statsd met an error while reading from logd. + */ + void noteLoggerError(int error); + + /** * Reset the historical stats. Including all stats in icebox, and the tracked stats about * metrics, matchers, and atoms. The active configs will be kept and StatsdStats will continue * to collect stats after reset() has been called. @@ -246,6 +253,9 @@ private: // Maps PullAtomId to its stats. The size is capped by the puller atom counts. std::map<int, PulledAtomStats> mPulledAtomStats; + // Logd errors. Size capped by kMaxLoggerErrors. + std::list<const std::pair<int, int>> mLoggerErrors; + // Stores the number of times statsd modified the anomaly alarm registered with // StatsCompanionService. int mAnomalyAlarmRegisteredStats = 0; diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp index 1ca793c81878..9e72f5bd4b72 100644 --- a/cmds/statsd/src/logd/LogEvent.cpp +++ b/cmds/statsd/src/logd/LogEvent.cpp @@ -198,7 +198,8 @@ void LogEvent::init(android_log_context context) { int seenListStart = 0; - Field field; + Field fieldTree; + Field* atomField = fieldTree.add_child(); do { elem = android_log_read_next(context); switch ((int)elem.type) { @@ -206,51 +207,37 @@ void LogEvent::init(android_log_context context) { // elem at [0] is EVENT_TYPE_LIST, [1] is the tag id. if (i == 1) { mTagId = elem.data.int32; + fieldTree.set_field(mTagId); } else { - increaseField(&field, seenListStart > 0/* is_child */); - DimensionsValue dimensionsValue; - dimensionsValue.set_value_int(elem.data.int32); - setFieldInLeafValueProto(field, &dimensionsValue); - mFieldValueMap.insert( - std::make_pair(buildAtomField(mTagId, field), dimensionsValue)); + increaseField(atomField, seenListStart > 0/* is_child */); + mFieldValueMap[fieldTree].set_value_int(elem.data.int32); } break; case EVENT_TYPE_FLOAT: { - increaseField(&field, seenListStart > 0/* is_child */); - DimensionsValue dimensionsValue; - dimensionsValue.set_value_float(elem.data.float32); - setFieldInLeafValueProto(field, &dimensionsValue); - mFieldValueMap.insert( - std::make_pair(buildAtomField(mTagId, field), dimensionsValue)); + increaseField(atomField, seenListStart > 0/* is_child */); + mFieldValueMap[fieldTree].set_value_float(elem.data.float32); } break; case EVENT_TYPE_STRING: { - increaseField(&field, seenListStart > 0/* is_child */); - DimensionsValue dimensionsValue; - dimensionsValue.set_value_str(string(elem.data.string, elem.len).c_str()); - setFieldInLeafValueProto(field, &dimensionsValue); - mFieldValueMap.insert( - std::make_pair(buildAtomField(mTagId, field), dimensionsValue)); + increaseField(atomField, seenListStart > 0/* is_child */); + mFieldValueMap[fieldTree].set_value_str( + string(elem.data.string, elem.len).c_str()); } break; case EVENT_TYPE_LONG: { - increaseField(&field, seenListStart > 0 /* is_child */); - DimensionsValue dimensionsValue; - dimensionsValue.set_value_long(elem.data.int64); - setFieldInLeafValueProto(field, &dimensionsValue); - mFieldValueMap.insert( - std::make_pair(buildAtomField(mTagId, field), dimensionsValue)); + increaseField(atomField, seenListStart > 0 /* is_child */); + mFieldValueMap[fieldTree].set_value_long(elem.data.int64); } break; case EVENT_TYPE_LIST: if (i >= 1) { if (seenListStart > 0) { - increasePosition(&field); + increasePosition(atomField); } else { - increaseField(&field, false /* is_child */); + increaseField(atomField, false /* is_child */); } seenListStart++; if (seenListStart >= 3) { @@ -262,10 +249,10 @@ void LogEvent::init(android_log_context context) { case EVENT_TYPE_LIST_STOP: seenListStart--; if (seenListStart == 0) { - field.clear_position_index(); + atomField->clear_position_index(); } else { - if (field.child_size() > 0) { - field.mutable_child(0)->clear_field(); + if (atomField->child_size() > 0) { + atomField->mutable_child(0)->clear_field(); } } break; @@ -393,14 +380,9 @@ bool LogEvent::GetAtomDimensionsValueProto(const FieldMatcher& matcher, bool LogEvent::GetSimpleAtomDimensionsValueProto(size_t atomField, DimensionsValue* dimensionsValue) const { - return GetAtomDimensionsValueProto( - buildSimpleAtomFieldMatcher(mTagId, atomField), dimensionsValue); -} - -DimensionsValue LogEvent::GetSimpleAtomDimensionsValueProto(size_t atomField) const { - DimensionsValue dimensionsValue; - GetSimpleAtomDimensionsValueProto(atomField, &dimensionsValue); - return dimensionsValue; + FieldMatcher matcher; + buildSimpleAtomFieldMatcher(mTagId, atomField, &matcher); + return GetAtomDimensionsValueProto(matcher, dimensionsValue); } DimensionsValue* LogEvent::findFieldValueOrNull(const Field& field) { diff --git a/cmds/statsd/src/logd/LogEvent.h b/cmds/statsd/src/logd/LogEvent.h index 5a4efd4b54a4..eb2c00845d00 100644 --- a/cmds/statsd/src/logd/LogEvent.h +++ b/cmds/statsd/src/logd/LogEvent.h @@ -92,7 +92,6 @@ public: * Get a DimensionsValue proto objects from Field. */ bool GetSimpleAtomDimensionsValueProto(size_t field, DimensionsValue* dimensionsValue) const; - DimensionsValue GetSimpleAtomDimensionsValueProto(size_t atomField) const; /** * Write test data to the LogEvent. This can only be used when the LogEvent is constructed diff --git a/cmds/statsd/src/logd/LogReader.cpp b/cmds/statsd/src/logd/LogReader.cpp index 5d43ef3f88bd..0fe896bb10c3 100644 --- a/cmds/statsd/src/logd/LogReader.cpp +++ b/cmds/statsd/src/logd/LogReader.cpp @@ -16,10 +16,11 @@ #include "logd/LogReader.h" -#include <utils/Errors.h> +#include "guardrail/StatsdStats.h" #include <time.h> #include <unistd.h> +#include <utils/Errors.h> using namespace android; using namespace std; @@ -92,16 +93,15 @@ int LogReader::connect_and_read() { // Read forever if (eventLogger) { - + log_msg msg; while (true) { - log_msg msg; - // Read a message err = android_logger_list_read(loggers, &msg); // err = 0 - no content, unexpected connection drop or EOF. // err = +ive number - size of retrieved data from logger // err = -ive number, OS supplied error _except_ for -EAGAIN if (err <= 0) { + StatsdStats::getInstance().noteLoggerError(err); fprintf(stderr, "logcat read failure: %s\n", strerror(err)); break; } diff --git a/cmds/statsd/src/matchers/matcher_util.cpp b/cmds/statsd/src/matchers/matcher_util.cpp index 48f62e702560..b6f440f2e348 100644 --- a/cmds/statsd/src/matchers/matcher_util.cpp +++ b/cmds/statsd/src/matchers/matcher_util.cpp @@ -93,25 +93,28 @@ bool combinationMatch(const vector<int>& children, const LogicalOperation& opera return matched; } -bool matchesNonRepeatedField( - const UidMap& uidMap, - const FieldValueMap& fieldMap, - const FieldValueMatcher&matcher, - const Field& field) { +namespace { + +bool matchFieldSimple(const UidMap& uidMap, const FieldValueMap& fieldMap, + const FieldValueMatcher&matcher, Field* rootField, Field* leafField); + +bool matchesNonRepeatedField(const UidMap& uidMap, const FieldValueMap& fieldMap, + const FieldValueMatcher&matcher, Field* rootField, Field* leafField) { if (matcher.value_matcher_case() == FieldValueMatcher::ValueMatcherCase::VALUE_MATCHER_NOT_SET) { return !fieldMap.empty() && fieldMap.begin()->first.field() == matcher.field(); } else if (matcher.value_matcher_case() == FieldValueMatcher::ValueMatcherCase::kMatchesTuple) { bool allMatched = true; + Field* newLeafField = leafField->add_child(); for (int i = 0; allMatched && i < matcher.matches_tuple().field_value_matcher_size(); ++i) { const auto& childMatcher = matcher.matches_tuple().field_value_matcher(i); - Field childField = field; - appendLeaf(&childField, childMatcher.field()); - allMatched &= matchFieldSimple(uidMap, fieldMap, childMatcher, childField); + newLeafField->set_field(childMatcher.field()); + allMatched &= matchFieldSimple(uidMap, fieldMap, childMatcher, rootField, newLeafField); } + leafField->clear_child(); return allMatched; } else { - auto ret = fieldMap.equal_range(field); + auto ret = fieldMap.equal_range(*rootField); int found = 0; for (auto it = ret.first; it != ret.second; ++it) { found++; @@ -132,7 +135,7 @@ bool matchesNonRepeatedField( break; case FieldValueMatcher::ValueMatcherCase::kEqString: { - if (IsAttributionUidField(field)) { + if (IsAttributionUidField(*rootField)) { const int uid = ret.first->second.value_int(); std::set<string> packageNames = uidMap.getAppNamesFromUid(uid, true /* normalize*/); @@ -171,19 +174,25 @@ bool matchesNonRepeatedField( } bool matchesRepeatedField(const UidMap& uidMap, const FieldValueMap& fieldMap, - const FieldValueMatcher&matcher, const Field& field) { + const FieldValueMatcher&matcher, + Field* rootField, Field* leafField) { if (matcher.position() == Position::FIRST) { - Field first_field = field; - setPositionForLeaf(&first_field, 0); - return matchesNonRepeatedField(uidMap, fieldMap, matcher, first_field); + leafField->set_position_index(0); + bool res = matchesNonRepeatedField(uidMap, fieldMap, matcher, rootField, leafField); + leafField->clear_position_index(); + return res; } else { - auto itLower = fieldMap.lower_bound(field); + auto itLower = fieldMap.lower_bound(*rootField); if (itLower == fieldMap.end()) { return false; } - Field next_field = field; - getNextField(&next_field); - auto itUpper = fieldMap.lower_bound(next_field); + + const int leafFieldNum = leafField->field(); + leafField->set_field(leafFieldNum + 1); + auto itUpper = fieldMap.lower_bound(*rootField); + // Resets the field number. + leafField->set_field(leafFieldNum); + switch (matcher.position()) { case Position::LAST: { @@ -191,31 +200,31 @@ bool matchesRepeatedField(const UidMap& uidMap, const FieldValueMap& fieldMap, if (itUpper == fieldMap.end()) { return false; } else { - Field last_field = field; - int last_index = getPositionByReferenceField(field, itUpper->first); + int last_index = getPositionByReferenceField(*rootField, itUpper->first); if (last_index < 0) { return false; } - setPositionForLeaf(&last_field, last_index); - return matchesNonRepeatedField(uidMap, fieldMap, matcher, last_field); + leafField->set_position_index(last_index); + bool res = matchesNonRepeatedField(uidMap, fieldMap, matcher, rootField, leafField); + leafField->clear_position_index(); + return res; } } break; case Position::ANY: { - std::set<int> indexes; + bool matched = false; for (auto it = itLower; it != itUpper; ++it) { - int index = getPositionByReferenceField(field, it->first); + int index = getPositionByReferenceField(*rootField, it->first); if (index >= 0) { - indexes.insert(index); + leafField->set_position_index(index); + matched |= matchesNonRepeatedField(uidMap, fieldMap, matcher, rootField, leafField); + leafField->clear_position_index(); + if (matched) { + break; + } } } - bool matched = false; - for (const int index : indexes) { - Field any_field = field; - setPositionForLeaf(&any_field, index); - matched |= matchesNonRepeatedField(uidMap, fieldMap, matcher, any_field); - } return matched; } default: @@ -226,14 +235,16 @@ bool matchesRepeatedField(const UidMap& uidMap, const FieldValueMap& fieldMap, } bool matchFieldSimple(const UidMap& uidMap, const FieldValueMap& fieldMap, - const FieldValueMatcher&matcher, const Field& field) { + const FieldValueMatcher&matcher, Field* rootField, Field* leafField) { if (!matcher.has_position()) { - return matchesNonRepeatedField(uidMap, fieldMap, matcher, field); + return matchesNonRepeatedField(uidMap, fieldMap, matcher, rootField, leafField); } else { - return matchesRepeatedField(uidMap, fieldMap, matcher, field); + return matchesRepeatedField(uidMap, fieldMap, matcher, rootField, leafField); } } +} // namespace + bool matchesSimple(const UidMap& uidMap, const SimpleAtomMatcher& simpleMatcher, const LogEvent& event) { if (simpleMatcher.field_value_matcher_size() <= 0) { @@ -247,13 +258,15 @@ bool matchesSimple(const UidMap& uidMap, const SimpleAtomMatcher& simpleMatcher, *root_field_matcher.mutable_matches_tuple()->add_field_value_matcher() = simpleMatcher.field_value_matcher(i); } - return matchFieldSimple(uidMap, event.getFieldValueMap(), root_field_matcher, root_field); + return matchFieldSimple( + uidMap, event.getFieldValueMap(), root_field_matcher, &root_field, &root_field); } -vector<DimensionsValue> getDimensionKeys(const LogEvent& event, const FieldMatcher& matcher) { - vector<DimensionsValue> values; - findDimensionsValues(event.getFieldValueMap(), matcher, &values); - return values; +void getDimensionKeys(const LogEvent& event, const FieldMatcher& matcher, + std::vector<DimensionsValue> *dimensionKeys) { + if (matcher.has_field()) { + findDimensionsValues(event.getFieldValueMap(), matcher, dimensionKeys); + } } } // namespace statsd } // namespace os diff --git a/cmds/statsd/src/matchers/matcher_util.h b/cmds/statsd/src/matchers/matcher_util.h index 704cb4c22e00..a45a9fb26a13 100644 --- a/cmds/statsd/src/matchers/matcher_util.h +++ b/cmds/statsd/src/matchers/matcher_util.h @@ -42,13 +42,11 @@ enum MatchingState { bool combinationMatch(const std::vector<int>& children, const LogicalOperation& operation, const std::vector<MatchingState>& matcherResults); -bool matchFieldSimple(const UidMap& uidMap, const FieldValueMap& dimensionsMap, - const FieldValueMatcher& matcher, const Field& field); - bool matchesSimple(const UidMap& uidMap, const SimpleAtomMatcher& simpleMatcher, const LogEvent& wrapper); -std::vector<DimensionsValue> getDimensionKeys(const LogEvent& event, const FieldMatcher& matcher); +void getDimensionKeys(const LogEvent& event, const FieldMatcher& matcher, + std::vector<DimensionsValue> *dimensionKeys); } // namespace statsd } // namespace os diff --git a/cmds/statsd/src/metrics/CountMetricProducer.h b/cmds/statsd/src/metrics/CountMetricProducer.h index 16fc7ee3c6e9..061b7a36817c 100644 --- a/cmds/statsd/src/metrics/CountMetricProducer.h +++ b/cmds/statsd/src/metrics/CountMetricProducer.h @@ -68,6 +68,8 @@ private: // Internal function to calculate the current used bytes. size_t byteSizeLocked() const override; + void dumpStatesLocked(FILE* out, bool verbose) const override{}; + // Util function to flush the old packet. void flushIfNeededLocked(const uint64_t& newEventTime); diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp index e26fe5649090..000874cf8f44 100644 --- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp +++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp @@ -233,6 +233,21 @@ void DurationMetricProducer::flushIfNeededLocked(const uint64_t& eventTime) { mCurrentBucketNum += numBucketsForward; } +void DurationMetricProducer::dumpStatesLocked(FILE* out, bool verbose) const { + if (mCurrentSlicedDuration.size() == 0) { + return; + } + + fprintf(out, "DurationMetric %lld dimension size %lu\n", (long long)mMetricId, + (unsigned long)mCurrentSlicedDuration.size()); + if (verbose) { + for (const auto& slice : mCurrentSlicedDuration) { + fprintf(out, "\t%s\n", slice.first.c_str()); + slice.second->dumpStates(out, verbose); + } + } +} + bool DurationMetricProducer::hitGuardRailLocked(const HashableDimensionKey& newKey) { // the key is not new, we are good. if (mCurrentSlicedDuration.find(newKey) != mCurrentSlicedDuration.end()) { @@ -275,7 +290,8 @@ void DurationMetricProducer::onMatchedLogEventInternalLocked( auto it = mCurrentSlicedDuration.find(eventKey); - std::vector<DimensionsValue> values = getDimensionKeys(event, mInternalDimensions); + std::vector<DimensionsValue> values; + getDimensionKeys(event, mInternalDimensions, &values); if (values.empty()) { if (matcherIndex == mStartIndex) { it->second->noteStart(DEFAULT_DIMENSION_KEY, condition, diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h index e06b9a14563d..d8cab92a2b84 100644 --- a/cmds/statsd/src/metrics/DurationMetricProducer.h +++ b/cmds/statsd/src/metrics/DurationMetricProducer.h @@ -68,6 +68,8 @@ private: // Internal function to calculate the current used bytes. size_t byteSizeLocked() const override; + void dumpStatesLocked(FILE* out, bool verbose) const override; + // Util function to flush the old packet. void flushIfNeededLocked(const uint64_t& eventTime); diff --git a/cmds/statsd/src/metrics/EventMetricProducer.h b/cmds/statsd/src/metrics/EventMetricProducer.h index a57b07d6648e..9da0dd0569d6 100644 --- a/cmds/statsd/src/metrics/EventMetricProducer.h +++ b/cmds/statsd/src/metrics/EventMetricProducer.h @@ -62,6 +62,8 @@ private: // Internal function to calculate the current used bytes. size_t byteSizeLocked() const override; + void dumpStatesLocked(FILE* out, bool verbose) const override{}; + // Maps to a EventMetricDataWrapper. Storing atom events in ProtoOutputStream // is more space efficient than storing LogEvent. std::unique_ptr<android::util::ProtoOutputStream> mProto; diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp index 24dc5b0fba53..1072c5aae6e4 100644 --- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp +++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp @@ -58,6 +58,7 @@ const int FIELD_ID_BUCKET_INFO = 3; const int FIELD_ID_START_BUCKET_NANOS = 1; const int FIELD_ID_END_BUCKET_NANOS = 2; const int FIELD_ID_ATOM = 3; +const int FIELD_ID_TIMESTAMP = 4; GaugeMetricProducer::GaugeMetricProducer(const ConfigKey& key, const GaugeMetric& metric, const int conditionIndex, @@ -67,7 +68,7 @@ GaugeMetricProducer::GaugeMetricProducer(const ConfigKey& key, const GaugeMetric : MetricProducer(metric.id(), key, startTimeNs, conditionIndex, wizard), mStatsPullerManager(statsPullerManager), mPullTagId(pullTagId) { - mCurrentSlicedBucket = std::make_shared<DimToGaugeFieldsMap>(); + mCurrentSlicedBucket = std::make_shared<DimToGaugeAtomsMap>(); mCurrentSlicedBucketForAnomaly = std::make_shared<DimToValMap>(); int64_t bucketSizeMills = 0; if (metric.has_bucket()) { @@ -77,6 +78,7 @@ GaugeMetricProducer::GaugeMetricProducer(const ConfigKey& key, const GaugeMetric } mBucketSizeNs = bucketSizeMills * 1000000; + mSamplingType = metric.sampling_type(); mFieldFilter = metric.gauge_fields_filter(); // TODO: use UidMap if uid->pkg_name is required @@ -89,7 +91,7 @@ GaugeMetricProducer::GaugeMetricProducer(const ConfigKey& key, const GaugeMetric } // Kicks off the puller immediately. - if (mPullTagId != -1) { + if (mPullTagId != -1 && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) { mStatsPullerManager->RegisterReceiver(mPullTagId, this, bucketSizeMills); } @@ -154,12 +156,23 @@ void GaugeMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, (long long)bucket.mBucketStartNs); protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_BUCKET_NANOS, (long long)bucket.mBucketEndNs); - long long atomToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_ATOM); - writeFieldValueTreeToStream(*bucket.mGaugeFields, protoOutput); - protoOutput->end(atomToken); + + if (!bucket.mGaugeAtoms.empty()) { + long long atomsToken = + protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_ATOM); + for (const auto& atom : bucket.mGaugeAtoms) { + writeFieldValueTreeToStream(*atom.mFields, protoOutput); + } + protoOutput->end(atomsToken); + + for (const auto& atom : bucket.mGaugeAtoms) { + protoOutput->write(FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED | FIELD_ID_TIMESTAMP, + (long long)atom.mTimestamps); + } + } protoOutput->end(bucketInfoToken); - VLOG("\t bucket [%lld - %lld] includes %d gauge fields.", (long long)bucket.mBucketStartNs, - (long long)bucket.mBucketEndNs, (int)bucket.mGaugeFields->size()); + VLOG("\t bucket [%lld - %lld] includes %d atoms.", (long long)bucket.mBucketStartNs, + (long long)bucket.mBucketEndNs, (int)bucket.mGaugeAtoms.size()); } protoOutput->end(wrapperToken); } @@ -181,14 +194,26 @@ void GaugeMetricProducer::onConditionChangedLocked(const bool conditionMet, if (mPullTagId == -1) { return; } - // No need to pull again. Either scheduled pull or condition on true happened - if (!mCondition) { - return; + + bool triggerPuller = false; + switch(mSamplingType) { + // When the metric wants to do random sampling and there is already one gauge atom for the + // current bucket, do not do it again. + case GaugeMetric::RANDOM_ONE_SAMPLE: { + triggerPuller = mCondition && mCurrentSlicedBucket->empty(); + break; + } + case GaugeMetric::ALL_CONDITION_CHANGES: { + triggerPuller = true; + break; + } + default: + break; } - // Already have gauge metric for the current bucket, do not do it again. - if (mCurrentSlicedBucket->size() > 0) { + if (!triggerPuller) { return; } + vector<std::shared_ptr<LogEvent>> allData; if (!mStatsPullerManager->Pull(mPullTagId, &allData)) { ALOGE("Stats puller failed for tag: %d", mPullTagId); @@ -257,20 +282,24 @@ void GaugeMetricProducer::onMatchedLogEventInternalLocked( } flushIfNeededLocked(eventTimeNs); - // For gauge metric, we just simply use the first gauge in the given bucket. - if (mCurrentSlicedBucket->find(eventKey) != mCurrentSlicedBucket->end()) { + // When gauge metric wants to randomly sample the output atom, we just simply use the first + // gauge in the given bucket. + if (mCurrentSlicedBucket->find(eventKey) != mCurrentSlicedBucket->end() && + mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) { return; } - std::shared_ptr<FieldValueMap> gaugeFields = getGaugeFields(event); if (hitGuardRailLocked(eventKey)) { return; } - (*mCurrentSlicedBucket)[eventKey] = gaugeFields; + GaugeAtom gaugeAtom; + gaugeAtom.mFields = getGaugeFields(event); + gaugeAtom.mTimestamps = eventTimeNs; + (*mCurrentSlicedBucket)[eventKey].push_back(gaugeAtom); // Anomaly detection on gauge metric only works when there is one numeric // field specified. if (mAnomalyTrackers.size() > 0) { - if (gaugeFields->size() == 1) { - const DimensionsValue& dimensionsValue = gaugeFields->begin()->second; + if (gaugeAtom.mFields->size() == 1) { + const DimensionsValue& dimensionsValue = gaugeAtom.mFields->begin()->second; long gaugeVal = 0; if (dimensionsValue.has_value_int()) { gaugeVal = (long)dimensionsValue.value_int(); @@ -289,7 +318,10 @@ void GaugeMetricProducer::updateCurrentSlicedBucketForAnomaly() { mCurrentSlicedBucketForAnomaly->clear(); status_t err = NO_ERROR; for (const auto& slice : *mCurrentSlicedBucket) { - const DimensionsValue& dimensionsValue = slice.second->begin()->second; + if (slice.second.empty() || slice.second.front().mFields->empty()) { + continue; + } + const DimensionsValue& dimensionsValue = slice.second.front().mFields->begin()->second; long gaugeVal = 0; if (dimensionsValue.has_value_int()) { gaugeVal = (long)dimensionsValue.value_int(); @@ -318,7 +350,7 @@ void GaugeMetricProducer::flushIfNeededLocked(const uint64_t& eventTimeNs) { info.mBucketNum = mCurrentBucketNum; for (const auto& slice : *mCurrentSlicedBucket) { - info.mGaugeFields = slice.second; + info.mGaugeAtoms = slice.second; auto& bucketList = mPastBuckets[slice.first]; bucketList.push_back(info); VLOG("gauge metric %lld, dump key value: %s", @@ -334,7 +366,7 @@ void GaugeMetricProducer::flushIfNeededLocked(const uint64_t& eventTimeNs) { } mCurrentSlicedBucketForAnomaly = std::make_shared<DimToValMap>(); - mCurrentSlicedBucket = std::make_shared<DimToGaugeFieldsMap>(); + mCurrentSlicedBucket = std::make_shared<DimToGaugeAtomsMap>(); // Adjusts the bucket start time int64_t numBucketsForward = (eventTimeNs - mCurrentBucketStartTimeNs) / mBucketSizeNs; diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h index f267e987f464..6c013477af37 100644 --- a/cmds/statsd/src/metrics/GaugeMetricProducer.h +++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h @@ -32,15 +32,20 @@ namespace android { namespace os { namespace statsd { +struct GaugeAtom { + std::shared_ptr<FieldValueMap> mFields; + int64_t mTimestamps; +}; + struct GaugeBucket { int64_t mBucketStartNs; int64_t mBucketEndNs; - std::shared_ptr<FieldValueMap> mGaugeFields; + std::vector<GaugeAtom> mGaugeAtoms; uint64_t mBucketNum; }; -typedef std::unordered_map<HashableDimensionKey, std::shared_ptr<FieldValueMap>> - DimToGaugeFieldsMap; +typedef std::unordered_map<HashableDimensionKey, std::vector<GaugeAtom>> + DimToGaugeAtomsMap; // This gauge metric producer first register the puller to automatically pull the gauge at the // beginning of each bucket. If the condition is met, insert it to the bucket info. Otherwise @@ -48,7 +53,7 @@ typedef std::unordered_map<HashableDimensionKey, std::shared_ptr<FieldValueMap>> // producer always reports the guage at the earliest time of the bucket when the condition is met. class GaugeMetricProducer : public virtual MetricProducer, public virtual PullDataReceiver { public: - GaugeMetricProducer(const ConfigKey& key, const GaugeMetric& countMetric, + GaugeMetricProducer(const ConfigKey& key, const GaugeMetric& gaugeMetric, const int conditionIndex, const sp<ConditionWizard>& wizard, const int pullTagId, const int64_t startTimeNs); @@ -83,6 +88,8 @@ private: // Internal function to calculate the current used bytes. size_t byteSizeLocked() const override; + void dumpStatesLocked(FILE* out, bool verbose) const override{}; + // Util function to flush the old packet. void flushIfNeededLocked(const uint64_t& eventTime); @@ -95,7 +102,7 @@ private: std::unordered_map<HashableDimensionKey, std::vector<GaugeBucket>> mPastBuckets; // The current bucket. - std::shared_ptr<DimToGaugeFieldsMap> mCurrentSlicedBucket; + std::shared_ptr<DimToGaugeAtomsMap> mCurrentSlicedBucket; // The current bucket for anomaly detection. std::shared_ptr<DimToValMap> mCurrentSlicedBucketForAnomaly; @@ -106,6 +113,8 @@ private: // Whitelist of fields to report. Empty means all are reported. FieldFilter mFieldFilter; + GaugeMetric::SamplingType mSamplingType; + // apply a whitelist on the original input std::shared_ptr<FieldValueMap> getGaugeFields(const LogEvent& event); diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp index d620a7ebee00..e74924a81fbf 100644 --- a/cmds/statsd/src/metrics/MetricProducer.cpp +++ b/cmds/statsd/src/metrics/MetricProducer.cpp @@ -32,8 +32,7 @@ void MetricProducer::onMatchedLogEventLocked(const size_t matcherIndex, const Lo ConditionKey conditionKey; if (mConditionSliced) { for (const auto& link : mConditionLinks) { - conditionKey.insert(std::make_pair(link.condition(), - getDimensionKeysForCondition(event, link))); + getDimensionKeysForCondition(event, link, &conditionKey[link.condition()]); } if (mWizard->query(mConditionTrackerIndex, conditionKey) != ConditionState::kTrue) { condition = false; @@ -44,8 +43,9 @@ void MetricProducer::onMatchedLogEventLocked(const size_t matcherIndex, const Lo condition = mCondition; } - if (mDimensions.child_size() > 0) { - vector<DimensionsValue> dimensionValues = getDimensionKeys(event, mDimensions); + if (mDimensions.has_field() && mDimensions.child_size() > 0) { + vector<DimensionsValue> dimensionValues; + getDimensionKeys(event, mDimensions, &dimensionValues); for (const DimensionsValue& dimensionValue : dimensionValues) { onMatchedLogEventInternalLocked( matcherIndex, HashableDimensionKey(dimensionValue), conditionKey, condition, event); diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h index 3779c4487d23..6f33073c633c 100644 --- a/cmds/statsd/src/metrics/MetricProducer.h +++ b/cmds/statsd/src/metrics/MetricProducer.h @@ -96,6 +96,11 @@ public: return onDumpReportLocked(dumpTimeNs, report); } + void dumpStates(FILE* out, bool verbose) const { + std::lock_guard<std::mutex> lock(mMutex); + dumpStatesLocked(out, verbose); + } + // Returns the memory in bytes currently used to store this metric's data. Does not change // state. size_t byteSize() const { @@ -128,6 +133,7 @@ protected: android::util::ProtoOutputStream* protoOutput) = 0; virtual void onDumpReportLocked(const uint64_t dumpTimeNs, StatsLogReport* report) = 0; virtual size_t byteSizeLocked() const = 0; + virtual void dumpStatesLocked(FILE* out, bool verbose) const = 0; const int64_t mMetricId; diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp index f92951703030..d0737de8acf3 100644 --- a/cmds/statsd/src/metrics/MetricsManager.cpp +++ b/cmds/statsd/src/metrics/MetricsManager.cpp @@ -154,6 +154,20 @@ void MetricsManager::onDumpReport(const uint64_t& dumpTimeStampNs, ConfigMetrics } } +void MetricsManager::dumpStates(FILE* out, bool verbose) { + fprintf(out, "ConfigKey %s, allowed source:", mConfigKey.ToString().c_str()); + { + std::lock_guard<std::mutex> lock(mAllowedLogSourcesMutex); + for (const auto& source : mAllowedLogSources) { + fprintf(out, "%d ", source); + } + } + fprintf(out, "\n"); + for (const auto& producer : mAllMetricProducers) { + producer->dumpStates(out, verbose); + } +} + void MetricsManager::onDumpReport(ProtoOutputStream* protoOutput) { VLOG("=========================Metric Reports Start=========================="); uint64_t dumpTimeStampNs = time(nullptr) * NS_PER_SEC; diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h index a0239fcd1127..9cdbafc75fb1 100644 --- a/cmds/statsd/src/metrics/MetricsManager.h +++ b/cmds/statsd/src/metrics/MetricsManager.h @@ -61,6 +61,8 @@ public: return !mAllowedPkg.empty(); } + void dumpStates(FILE* out, bool verbose); + // Config source owner can call onDumpReport() to get all the metrics collected. virtual void onDumpReport(android::util::ProtoOutputStream* protoOutput); virtual void onDumpReport(const uint64_t& dumpTimeStampNs, ConfigMetricsReport* report); @@ -68,7 +70,6 @@ public: // Computes the total byte size of all metrics managed by a single config source. // Does not change the state. virtual size_t byteSize(); - private: const ConfigKey mConfigKey; diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h index 3e7032d8cf2d..9f750cf419b5 100644 --- a/cmds/statsd/src/metrics/ValueMetricProducer.h +++ b/cmds/statsd/src/metrics/ValueMetricProducer.h @@ -67,6 +67,8 @@ private: // Internal function to calculate the current used bytes. size_t byteSizeLocked() const override; + void dumpStatesLocked(FILE* out, bool verbose) const override{}; + // Util function to flush the old packet. void flushIfNeededLocked(const uint64_t& eventTime); diff --git a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h index 371460e804bd..c2d2cea2a1ff 100644 --- a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h +++ b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h @@ -97,6 +97,8 @@ public: // Predict the anomaly timestamp given the current status. virtual int64_t predictAnomalyTimestampNs(const DurationAnomalyTracker& anomalyTracker, const uint64_t currentTimestamp) const = 0; + // Dump internal states for debugging + virtual void dumpStates(FILE* out, bool verbose) const = 0; protected: // Starts the anomaly alarm. diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp index 0c99391d491f..412a0c935766 100644 --- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp +++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp @@ -291,6 +291,11 @@ int64_t MaxDurationTracker::predictAnomalyTimestampNs(const DurationAnomalyTrack return currentTimestamp; } +void MaxDurationTracker::dumpStates(FILE* out, bool verbose) const { + fprintf(out, "\t\t sub-durations %lu\n", (unsigned long)mInfos.size()); + fprintf(out, "\t\t current duration %lld\n", (long long)mDuration); +} + } // namespace statsd } // namespace os } // namespace android diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h index 5d3c15804638..661d1311293a 100644 --- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h +++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h @@ -48,9 +48,10 @@ public: int64_t predictAnomalyTimestampNs(const DurationAnomalyTracker& anomalyTracker, const uint64_t currentTimestamp) const override; + void dumpStates(FILE* out, bool verbose) const override; private: - std::map<HashableDimensionKey, DurationInfo> mInfos; + std::unordered_map<HashableDimensionKey, DurationInfo> mInfos; void noteConditionChanged(const HashableDimensionKey& key, bool conditionMet, const uint64_t timestamp); diff --git a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp index 6bf42287e6dd..75d7c0898d78 100644 --- a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp +++ b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp @@ -314,6 +314,12 @@ int64_t OringDurationTracker::predictAnomalyTimestampNs( return eventTimestampNs + thresholdNs; } +void OringDurationTracker::dumpStates(FILE* out, bool verbose) const { + fprintf(out, "\t\t started count %lu\n", (unsigned long)mStarted.size()); + fprintf(out, "\t\t paused count %lu\n", (unsigned long)mPaused.size()); + fprintf(out, "\t\t current duration %lld\n", (long long)mDuration); +} + } // namespace statsd } // namespace os } // namespace android diff --git a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h index 638b7ad7af26..43469ca9a551 100644 --- a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h +++ b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h @@ -48,6 +48,7 @@ public: int64_t predictAnomalyTimestampNs(const DurationAnomalyTracker& anomalyTracker, const uint64_t currentTimestamp) const override; + void dumpStates(FILE* out, bool verbose) const override; private: // We don't need to keep track of individual durations. The information that's needed is: @@ -55,10 +56,10 @@ private: // 2) which keys are paused (started but condition was false) // 3) whenever a key stops, we remove it from the started set. And if the set becomes empty, // it means everything has stopped, we then record the end time. - std::map<HashableDimensionKey, int> mStarted; - std::map<HashableDimensionKey, int> mPaused; + std::unordered_map<HashableDimensionKey, int> mStarted; + std::unordered_map<HashableDimensionKey, int> mPaused; int64_t mLastStartTime; - std::map<HashableDimensionKey, ConditionKey> mConditionKeyMap; + std::unordered_map<HashableDimensionKey, ConditionKey> mConditionKeyMap; // return true if we should not allow newKey to be tracked because we are above the threshold bool hitGuardRail(const HashableDimensionKey& newKey); diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto index f73c4a5303cf..af21ca4d82e8 100644 --- a/cmds/statsd/src/stats_log.proto +++ b/cmds/statsd/src/stats_log.proto @@ -100,7 +100,9 @@ message GaugeBucketInfo { optional int64 end_bucket_nanos = 2; - optional Atom atom = 3; + repeated Atom atom = 3; + + repeated int64 timestamp_nanos = 4; } message GaugeMetricData { @@ -262,4 +264,10 @@ message StatsdStatsReport { optional int64 min_pull_interval_sec = 4; } repeated PulledAtomStats pulled_atom_stats = 10; + + message LoggerErrorStats { + optional int32 logger_disconnection_sec = 1; + optional int32 error_code = 2; + } + repeated LoggerErrorStats logger_error_stats = 11; }
\ No newline at end of file diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto index 07bbcb2190e8..2ea79a64a5ea 100644 --- a/cmds/statsd/src/statsd_config.proto +++ b/cmds/statsd/src/statsd_config.proto @@ -222,6 +222,12 @@ message GaugeMetric { optional TimeUnit bucket = 6; repeated MetricConditionLink links = 7; + + enum SamplingType { + RANDOM_ONE_SAMPLE = 1; + ALL_CONDITION_CHANGES = 2; + } + optional SamplingType sampling_type = 9 [default = RANDOM_ONE_SAMPLE] ; } message ValueMetric { diff --git a/cmds/statsd/src/storage/StorageManager.cpp b/cmds/statsd/src/storage/StorageManager.cpp index 83b72d966a39..00d86582951f 100644 --- a/cmds/statsd/src/storage/StorageManager.cpp +++ b/cmds/statsd/src/storage/StorageManager.cpp @@ -63,7 +63,7 @@ static void parseFileName(char* name, int64_t* result) { } static string getFilePath(const char* path, int64_t timestamp, int64_t uid, int64_t configID) { - return StringPrintf("%s/%lld-%d-%lld", path, (long long)timestamp, (int)uid, + return StringPrintf("%s/%lld_%d_%lld", path, (long long)timestamp, (int)uid, (long long)configID); } diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp index e56a6c57848f..a80fdc5606b7 100644 --- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp +++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp @@ -153,23 +153,26 @@ TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent) { EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1 /* uid field */); EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid1); EXPECT_EQ(data.bucket_info_size(), 3); + EXPECT_EQ(data.bucket_info(0).atom_size(), 1); EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).atom().app_start_changed().type(), AppStartChanged::HOT); - EXPECT_EQ(data.bucket_info(0).atom().app_start_changed().activity_name(), "activity_name2"); - EXPECT_EQ(data.bucket_info(0).atom().app_start_changed().activity_start_msec(), 102L); + EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().type(), AppStartChanged::HOT); + EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().activity_name(), "activity_name2"); + EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().activity_start_msec(), 102L); + EXPECT_EQ(data.bucket_info(1).atom_size(), 1); EXPECT_EQ(data.bucket_info(1).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); EXPECT_EQ(data.bucket_info(1).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).atom().app_start_changed().type(), AppStartChanged::WARM); - EXPECT_EQ(data.bucket_info(1).atom().app_start_changed().activity_name(), "activity_name4"); - EXPECT_EQ(data.bucket_info(1).atom().app_start_changed().activity_start_msec(), 104L); + EXPECT_EQ(data.bucket_info(1).atom(0).app_start_changed().type(), AppStartChanged::WARM); + EXPECT_EQ(data.bucket_info(1).atom(0).app_start_changed().activity_name(), "activity_name4"); + EXPECT_EQ(data.bucket_info(1).atom(0).app_start_changed().activity_start_msec(), 104L); + EXPECT_EQ(data.bucket_info(2).atom_size(), 1); EXPECT_EQ(data.bucket_info(2).start_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); EXPECT_EQ(data.bucket_info(2).end_bucket_nanos(), bucketStartTimeNs + 3 * bucketSizeNs); - EXPECT_EQ(data.bucket_info(2).atom().app_start_changed().type(), AppStartChanged::COLD); - EXPECT_EQ(data.bucket_info(2).atom().app_start_changed().activity_name(), "activity_name5"); - EXPECT_EQ(data.bucket_info(2).atom().app_start_changed().activity_start_msec(), 105L); + EXPECT_EQ(data.bucket_info(2).atom(0).app_start_changed().type(), AppStartChanged::COLD); + EXPECT_EQ(data.bucket_info(2).atom(0).app_start_changed().activity_name(), "activity_name5"); + EXPECT_EQ(data.bucket_info(2).atom(0).app_start_changed().activity_start_msec(), 105L); data = gaugeMetrics.data(1); @@ -178,11 +181,12 @@ TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent) { EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1 /* uid field */); EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid2); EXPECT_EQ(data.bucket_info_size(), 1); + EXPECT_EQ(data.bucket_info(0).atom_size(), 1); EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + 3 * bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).atom().app_start_changed().type(), AppStartChanged::COLD); - EXPECT_EQ(data.bucket_info(0).atom().app_start_changed().activity_name(), "activity_name7"); - EXPECT_EQ(data.bucket_info(0).atom().app_start_changed().activity_start_msec(), 201L); + EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().type(), AppStartChanged::COLD); + EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().activity_name(), "activity_name7"); + EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().activity_start_msec(), 201L); } #else diff --git a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp index eda16a2ffbfd..4504a95c8ef0 100644 --- a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp +++ b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp @@ -123,11 +123,13 @@ TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks) { auto crashEvent10 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 2); auto screenTurnedOnEvent = - CreateScreenStateChangedEvent(ScreenStateChanged::STATE_ON, bucketStartTimeNs + 2); + CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON, + bucketStartTimeNs + 2); auto screenTurnedOffEvent = - CreateScreenStateChangedEvent(ScreenStateChanged::STATE_OFF, bucketStartTimeNs + 200); + CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF, + bucketStartTimeNs + 200); auto screenTurnedOnEvent2 = - CreateScreenStateChangedEvent(ScreenStateChanged::STATE_ON, + CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 2 * bucketSizeNs - 100); auto syncOnEvent1 = diff --git a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp index e656b98c66ad..1186a166dfab 100644 --- a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp +++ b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp @@ -73,11 +73,13 @@ TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensions) { EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); auto screenTurnedOnEvent = - CreateScreenStateChangedEvent(ScreenStateChanged::STATE_ON, bucketStartTimeNs + 1); + CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON, + bucketStartTimeNs + 1); auto screenTurnedOffEvent = - CreateScreenStateChangedEvent(ScreenStateChanged::STATE_OFF, bucketStartTimeNs + 200); + CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF, + bucketStartTimeNs + 200); auto screenTurnedOnEvent2 = - CreateScreenStateChangedEvent(ScreenStateChanged::STATE_ON, + CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + bucketSizeNs + 500); std::vector<AttributionNode> attributions1 = @@ -156,7 +158,8 @@ TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensions) { events.clear(); events.push_back(CreateScreenStateChangedEvent( - ScreenStateChanged::STATE_OFF, bucketStartTimeNs + 2 * bucketSizeNs + 90)); + android::view::DisplayStateEnum::DISPLAY_STATE_OFF, + bucketStartTimeNs + 2 * bucketSizeNs + 90)); events.push_back(CreateAcquireWakelockEvent( attributions1, "wl3", bucketStartTimeNs + 2 * bucketSizeNs + 100)); events.push_back(CreateReleaseWakelockEvent( diff --git a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp index 897328d4635e..4ad209712905 100644 --- a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp @@ -149,8 +149,8 @@ TEST(CountMetricProducerTest, TestEventsWithSlicedCondition) { metric.set_condition(StringToId("APP_IN_BACKGROUND_PER_UID_AND_SCREEN_ON")); MetricConditionLink* link = metric.add_links(); link->set_condition(StringToId("APP_IN_BACKGROUND_PER_UID")); - *link->mutable_fields_in_what() = buildSimpleAtomFieldMatcher(tagId, 1); - *link->mutable_fields_in_condition() = buildSimpleAtomFieldMatcher(conditionTagId, 2); + buildSimpleAtomFieldMatcher(tagId, 1, link->mutable_fields_in_what()); + buildSimpleAtomFieldMatcher(conditionTagId, 2, link->mutable_fields_in_condition()); LogEvent event1(tagId, bucketStartTimeNs + 1); event1.write("111"); // uid diff --git a/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp b/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp index 34cde607988e..da00cae125c7 100644 --- a/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp @@ -98,8 +98,8 @@ TEST(EventMetricProducerTest, TestEventsWithSlicedCondition) { metric.set_condition(StringToId("APP_IN_BACKGROUND_PER_UID_AND_SCREEN_ON")); MetricConditionLink* link = metric.add_links(); link->set_condition(StringToId("APP_IN_BACKGROUND_PER_UID")); - *link->mutable_fields_in_what() = buildSimpleAtomFieldMatcher(tagId, 1); - *link->mutable_fields_in_condition() = buildSimpleAtomFieldMatcher(conditionTagId, 2); + buildSimpleAtomFieldMatcher(tagId, 1, link->mutable_fields_in_what()); + buildSimpleAtomFieldMatcher(conditionTagId, 2, link->mutable_fields_in_condition()); LogEvent event1(tagId, bucketStartTimeNs + 1); EXPECT_TRUE(event1.write("111")); diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp index 82772d854db2..4533ac610057 100644 --- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp @@ -78,7 +78,7 @@ TEST(GaugeMetricProducerTest, TestNoCondition) { gaugeProducer.onDataPulled(allData); EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); - auto it = gaugeProducer.mCurrentSlicedBucket->begin()->second->begin(); + auto it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin(); EXPECT_EQ(10, it->second.value_int()); it++; EXPECT_EQ(11, it->second.value_int()); @@ -94,14 +94,14 @@ TEST(GaugeMetricProducerTest, TestNoCondition) { allData.push_back(event2); gaugeProducer.onDataPulled(allData); EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); - it = gaugeProducer.mCurrentSlicedBucket->begin()->second->begin(); + it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin(); EXPECT_EQ(24, it->second.value_int()); it++; EXPECT_EQ(25, it->second.value_int()); // One dimension. EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size()); EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.begin()->second.size()); - it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeFields->begin(); + it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.front().mFields->begin(); EXPECT_EQ(10L, it->second.value_int()); it++; EXPECT_EQ(11L, it->second.value_int()); @@ -112,7 +112,7 @@ TEST(GaugeMetricProducerTest, TestNoCondition) { // One dimension. EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size()); EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size()); - it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeFields->begin(); + it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.front().mFields->begin(); EXPECT_EQ(24L, it->second.value_int()); it++; EXPECT_EQ(25L, it->second.value_int()); @@ -151,7 +151,8 @@ TEST(GaugeMetricProducerTest, TestWithCondition) { gaugeProducer.onConditionChanged(true, bucketStartTimeNs + 8); EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); EXPECT_EQ(100, - gaugeProducer.mCurrentSlicedBucket->begin()->second->begin()->second.value_int()); + gaugeProducer.mCurrentSlicedBucket->begin()-> + second.front().mFields->begin()->second.value_int()); EXPECT_EQ(0UL, gaugeProducer.mPastBuckets.size()); vector<shared_ptr<LogEvent>> allData; @@ -165,17 +166,18 @@ TEST(GaugeMetricProducerTest, TestWithCondition) { EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); EXPECT_EQ(110, - gaugeProducer.mCurrentSlicedBucket->begin()->second->begin()->second.value_int()); + gaugeProducer.mCurrentSlicedBucket->begin()-> + second.front().mFields->begin()->second.value_int()); EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size()); EXPECT_EQ(100, gaugeProducer.mPastBuckets.begin()->second.back() - .mGaugeFields->begin()->second.value_int()); + .mGaugeAtoms.front().mFields->begin()->second.value_int()); gaugeProducer.onConditionChanged(false, bucket2StartTimeNs + 10); gaugeProducer.flushIfNeededLocked(bucket3StartTimeNs + 10); EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size()); EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size()); EXPECT_EQ(110L, gaugeProducer.mPastBuckets.begin()->second.back() - .mGaugeFields->begin()->second.value_int()); + .mGaugeAtoms.front().mFields->begin()->second.value_int()); EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.begin()->second.back().mBucketNum); } @@ -214,7 +216,8 @@ TEST(GaugeMetricProducerTest, TestAnomalyDetection) { gaugeProducer.onDataPulled({event1}); EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); EXPECT_EQ(13L, - gaugeProducer.mCurrentSlicedBucket->begin()->second->begin()->second.value_int()); + gaugeProducer.mCurrentSlicedBucket->begin()-> + second.front().mFields->begin()->second.value_int()); EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_DIMENSION_KEY), 0U); std::shared_ptr<LogEvent> event2 = @@ -226,7 +229,8 @@ TEST(GaugeMetricProducerTest, TestAnomalyDetection) { gaugeProducer.onDataPulled({event2}); EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); EXPECT_EQ(15L, - gaugeProducer.mCurrentSlicedBucket->begin()->second->begin()->second.value_int()); + gaugeProducer.mCurrentSlicedBucket->begin()-> + second.front().mFields->begin()->second.value_int()); EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_DIMENSION_KEY), event2->GetTimestampNs() / NS_PER_SEC + refPeriodSec); @@ -239,7 +243,8 @@ TEST(GaugeMetricProducerTest, TestAnomalyDetection) { gaugeProducer.onDataPulled({event3}); EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); EXPECT_EQ(26L, - gaugeProducer.mCurrentSlicedBucket->begin()->second->begin()->second.value_int()); + gaugeProducer.mCurrentSlicedBucket->begin()-> + second.front().mFields->begin()->second.value_int()); EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_DIMENSION_KEY), event2->GetTimestampNs() / NS_PER_SEC + refPeriodSec); @@ -250,7 +255,7 @@ TEST(GaugeMetricProducerTest, TestAnomalyDetection) { event4->init(); gaugeProducer.onDataPulled({event4}); EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); - EXPECT_TRUE(gaugeProducer.mCurrentSlicedBucket->begin()->second->empty()); + EXPECT_TRUE(gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->empty()); } } // namespace statsd diff --git a/cmds/statsd/tests/statsd_test_util.cpp b/cmds/statsd/tests/statsd_test_util.cpp index 718b2e177d52..9f4582dc6994 100644 --- a/cmds/statsd/tests/statsd_test_util.cpp +++ b/cmds/statsd/tests/statsd_test_util.cpp @@ -48,7 +48,7 @@ AtomMatcher CreateReleaseWakelockAtomMatcher() { } AtomMatcher CreateScreenStateChangedAtomMatcher( - const string& name, ScreenStateChanged::State state) { + const string& name, android::view::DisplayStateEnum state) { AtomMatcher atom_matcher; atom_matcher.set_id(StringToId(name)); auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher(); @@ -60,11 +60,13 @@ AtomMatcher CreateScreenStateChangedAtomMatcher( } AtomMatcher CreateScreenTurnedOnAtomMatcher() { - return CreateScreenStateChangedAtomMatcher("ScreenTurnedOn", ScreenStateChanged::STATE_ON); + return CreateScreenStateChangedAtomMatcher("ScreenTurnedOn", + android::view::DisplayStateEnum::DISPLAY_STATE_ON); } AtomMatcher CreateScreenTurnedOffAtomMatcher() { - return CreateScreenStateChangedAtomMatcher("ScreenTurnedOff", ScreenStateChanged::STATE_OFF); + return CreateScreenStateChangedAtomMatcher("ScreenTurnedOff", + ::android::view::DisplayStateEnum::DISPLAY_STATE_OFF); } AtomMatcher CreateSyncStateChangedAtomMatcher( @@ -209,7 +211,7 @@ FieldMatcher CreateDimensions(const int atomId, const std::vector<int>& fields) } std::unique_ptr<LogEvent> CreateScreenStateChangedEvent( - const ScreenStateChanged::State state, uint64_t timestampNs) { + const android::view::DisplayStateEnum state, uint64_t timestampNs) { auto event = std::make_unique<LogEvent>(android::util::SCREEN_STATE_CHANGED, timestampNs); EXPECT_TRUE(event->write(state)); event->init(); @@ -221,7 +223,7 @@ std::unique_ptr<LogEvent> CreateWakelockStateChangedEvent( const WakelockStateChanged::State state, uint64_t timestampNs) { auto event = std::make_unique<LogEvent>(android::util::WAKELOCK_STATE_CHANGED, timestampNs); event->write(attributions); - event->write(WakelockStateChanged::PARTIAL); + event->write(android::os::WakeLockLevelEnum::PARTIAL_WAKE_LOCK); event->write(wakelockName); event->write(state); event->init(); diff --git a/cmds/statsd/tests/statsd_test_util.h b/cmds/statsd/tests/statsd_test_util.h index 1fc33ded13c1..ff8fef0c46b6 100644 --- a/cmds/statsd/tests/statsd_test_util.h +++ b/cmds/statsd/tests/statsd_test_util.h @@ -84,7 +84,7 @@ FieldMatcher CreateAttributionUidDimensions(const int atomId, // Create log event for screen state changed. std::unique_ptr<LogEvent> CreateScreenStateChangedEvent( - const ScreenStateChanged::State state, uint64_t timestampNs); + const android::view::DisplayStateEnum state, uint64_t timestampNs); // Create log event for app moving to background. std::unique_ptr<LogEvent> CreateMoveToBackgroundEvent(const int uid, uint64_t timestampNs); diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/SequencePusher.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/SequencePusher.java index d4b2aa4ff241..5dcce9acb401 100644 --- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/SequencePusher.java +++ b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/SequencePusher.java @@ -90,7 +90,7 @@ public class SequencePusher { case 2: case 10: StatsLog.write(StatsLog.CHARGING_STATE_CHANGED, - StatsLog.CHARGING_STATE_CHANGED__CHARGING_STATE__BATTERY_STATUS_CHARGING + StatsLog.CHARGING_STATE_CHANGED__STATE__BATTERY_STATUS_CHARGING /* charging_state */); break; case 3: @@ -103,7 +103,7 @@ public class SequencePusher { case 4: case 12: StatsLog.write(StatsLog.CHARGING_STATE_CHANGED, - StatsLog.CHARGING_STATE_CHANGED__CHARGING_STATE__BATTERY_STATUS_NOT_CHARGING + StatsLog.CHARGING_STATE_CHANGED__STATE__BATTERY_STATUS_NOT_CHARGING /* charging_state */); break; case 5: @@ -115,7 +115,7 @@ public class SequencePusher { break; case 6: StatsLog.write(StatsLog.SCREEN_STATE_CHANGED, - StatsLog.SCREEN_STATE_CHANGED__DISPLAY_STATE__STATE_ON /* display_state */); + StatsLog.SCREEN_STATE_CHANGED__STATE__DISPLAY_STATE_ON /* display_state */); break; case 7: for (int i = 0; i < mBurst; i++) { @@ -125,7 +125,7 @@ public class SequencePusher { break; case 14: StatsLog.write(StatsLog.SCREEN_STATE_CHANGED, - StatsLog.SCREEN_STATE_CHANGED__DISPLAY_STATE__STATE_OFF /* display_state */); + StatsLog.SCREEN_STATE_CHANGED__STATE__DISPLAY_STATE_OFF /* display_state */); break; case 15: for (int i = 0; i < mBurst; i++) { @@ -147,14 +147,14 @@ public class SequencePusher { public void finish() { // Screen goes back to off. This will ensure that conditions get back to false. StatsLog.write(StatsLog.SCREEN_STATE_CHANGED, - StatsLog.SCREEN_STATE_CHANGED__DISPLAY_STATE__STATE_OFF /* display_state */); + StatsLog.SCREEN_STATE_CHANGED__STATE__DISPLAY_STATE_OFF /* display_state */); for (int i = 0; i < mBurst; i++) { StatsLog.write(StatsLog.AUDIO_STATE_CHANGED, i /* uid */, StatsLog.AUDIO_STATE_CHANGED__STATE__OFF /* state */); } // Stop charging, to ensure the corresponding durations are closed. StatsLog.write(StatsLog.CHARGING_STATE_CHANGED, - StatsLog.CHARGING_STATE_CHANGED__CHARGING_STATE__BATTERY_STATUS_NOT_CHARGING + StatsLog.CHARGING_STATE_CHANGED__STATE__BATTERY_STATUS_NOT_CHARGING /* charging_state */); // Stop scanning GPS, to ensure the corresponding conditions get back to false. for (int i = 0; i < mBurst; i++) { |