summaryrefslogtreecommitdiff
path: root/cmds
diff options
context:
space:
mode:
Diffstat (limited to 'cmds')
-rw-r--r--cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java5
-rw-r--r--cmds/bootanimation/Android.bp2
-rw-r--r--cmds/bootanimation/BootAnimation.cpp111
-rw-r--r--cmds/bootanimation/BootAnimation.h6
-rw-r--r--cmds/hid/jni/com_android_commands_hid_Device.cpp59
-rw-r--r--cmds/hid/jni/com_android_commands_hid_Device.h2
-rw-r--r--cmds/hid/src/com/android/commands/hid/Device.java33
-rw-r--r--cmds/idmap2/Android.bp1
-rw-r--r--cmds/idmap2/idmap2/Commands.h1
-rw-r--r--cmds/idmap2/idmap2/Create.cpp1
-rw-r--r--cmds/idmap2/idmap2/CreateMultiple.cpp1
-rw-r--r--cmds/idmap2/idmap2/Main.cpp6
-rw-r--r--cmds/idmap2/idmap2/Scan.cpp257
-rw-r--r--cmds/idmap2/idmap2d/Idmap2Service.h2
-rw-r--r--cmds/idmap2/idmap2d/aidl/android/os/OverlayablePolicy.aidl1
-rw-r--r--cmds/idmap2/include/idmap2/FileUtils.h14
-rw-r--r--cmds/idmap2/libidmap2/FileUtils.cpp60
-rw-r--r--cmds/idmap2/libidmap2/PolicyUtils.cpp2
-rw-r--r--cmds/idmap2/libidmap2/ResourceMapping.cpp7
-rw-r--r--cmds/idmap2/libidmap2_policies/include/idmap2/Policies.h11
-rw-r--r--cmds/idmap2/tests/FileUtilsTests.cpp57
-rw-r--r--cmds/idmap2/tests/Idmap2BinaryTests.cpp125
-rw-r--r--cmds/idmap2/tests/R.h68
-rw-r--r--cmds/idmap2/tests/ResourceMappingTests.cpp18
-rw-r--r--cmds/idmap2/tests/TestConstants.h14
-rw-r--r--cmds/idmap2/tests/data/overlay/overlay-no-name-static.apkbin3477 -> 3485 bytes
-rw-r--r--cmds/idmap2/tests/data/overlay/overlay-no-name.apkbin3389 -> 3393 bytes
-rw-r--r--cmds/idmap2/tests/data/overlay/overlay-shared.apkbin3757 -> 3757 bytes
-rw-r--r--cmds/idmap2/tests/data/overlay/overlay-static-1.apkbin3469 -> 3477 bytes
-rw-r--r--cmds/idmap2/tests/data/overlay/overlay-static-2.apkbin3469 -> 3477 bytes
-rw-r--r--cmds/idmap2/tests/data/overlay/overlay.apkbin3489 -> 3489 bytes
-rw-r--r--cmds/idmap2/tests/data/signature-overlay/signature-overlay.apkbin1315 -> 1299 bytes
-rw-r--r--cmds/idmap2/tests/data/system-overlay-invalid/res/values/values.xml1
-rw-r--r--cmds/idmap2/tests/data/system-overlay-invalid/system-overlay-invalid.apkbin1827 -> 1907 bytes
-rw-r--r--cmds/idmap2/tests/data/system-overlay/system-overlay.apkbin1319 -> 1387 bytes
-rw-r--r--cmds/idmap2/tests/data/target/res/values/overlayable.xml4
-rw-r--r--cmds/idmap2/tests/data/target/res/values/values.xml1
-rw-r--r--cmds/idmap2/tests/data/target/target-no-overlayable.apkbin2311 -> 2391 bytes
-rw-r--r--cmds/idmap2/tests/data/target/target.apkbin5097 -> 5201 bytes
-rwxr-xr-xcmds/idmap2/valgrind.sh2
-rw-r--r--cmds/incidentd/src/IncidentService.cpp4
-rw-r--r--cmds/incidentd/tests/section_list.cpp2
-rw-r--r--cmds/input/Android.bp5
-rwxr-xr-xcmds/input/input3
-rw-r--r--cmds/input/src/com/android/commands/input/Input.java435
-rw-r--r--cmds/locksettings/TEST_MAPPING2
-rw-r--r--cmds/screencap/Android.bp2
-rw-r--r--cmds/screencap/screencap.cpp103
-rw-r--r--cmds/statsd/Android.bp22
-rw-r--r--cmds/statsd/TEST_MAPPING12
-rw-r--r--cmds/statsd/src/StatsLogProcessor.cpp79
-rw-r--r--cmds/statsd/src/StatsLogProcessor.h34
-rw-r--r--cmds/statsd/src/StatsService.cpp56
-rw-r--r--cmds/statsd/src/StatsService.h5
-rw-r--r--cmds/statsd/src/atoms.proto90
-rw-r--r--cmds/statsd/src/condition/CombinationConditionTracker.cpp81
-rw-r--r--cmds/statsd/src/condition/CombinationConditionTracker.h12
-rw-r--r--cmds/statsd/src/condition/ConditionTracker.h63
-rw-r--r--cmds/statsd/src/condition/SimpleConditionTracker.cpp107
-rw-r--r--cmds/statsd/src/condition/SimpleConditionTracker.h21
-rw-r--r--cmds/statsd/src/external/StatsPullerManager.cpp81
-rw-r--r--cmds/statsd/src/external/StatsPullerManager.h13
-rw-r--r--cmds/statsd/src/hash.h1
-rw-r--r--cmds/statsd/src/matchers/AtomMatchingTracker.h118
-rw-r--r--cmds/statsd/src/matchers/CombinationAtomMatchingTracker.cpp (renamed from cmds/statsd/src/matchers/CombinationLogMatchingTracker.cpp)52
-rw-r--r--cmds/statsd/src/matchers/CombinationAtomMatchingTracker.h (renamed from cmds/statsd/src/matchers/CombinationLogMatchingTracker.h)29
-rw-r--r--cmds/statsd/src/matchers/EventMatcherWizard.h6
-rw-r--r--cmds/statsd/src/matchers/LogMatchingTracker.h96
-rw-r--r--cmds/statsd/src/matchers/SimpleAtomMatchingTracker.cpp (renamed from cmds/statsd/src/matchers/SimpleLogMatchingTracker.cpp)38
-rw-r--r--cmds/statsd/src/matchers/SimpleAtomMatchingTracker.h (renamed from cmds/statsd/src/matchers/SimpleLogMatchingTracker.h)29
-rw-r--r--cmds/statsd/src/matchers/matcher_util.cpp11
-rw-r--r--cmds/statsd/src/matchers/matcher_util.h4
-rw-r--r--cmds/statsd/src/metrics/CountMetricProducer.cpp5
-rw-r--r--cmds/statsd/src/metrics/CountMetricProducer.h6
-rw-r--r--cmds/statsd/src/metrics/DurationMetricProducer.cpp7
-rw-r--r--cmds/statsd/src/metrics/DurationMetricProducer.h9
-rw-r--r--cmds/statsd/src/metrics/EventMetricProducer.cpp5
-rw-r--r--cmds/statsd/src/metrics/EventMetricProducer.h6
-rw-r--r--cmds/statsd/src/metrics/GaugeMetricProducer.cpp9
-rw-r--r--cmds/statsd/src/metrics/GaugeMetricProducer.h17
-rw-r--r--cmds/statsd/src/metrics/MetricProducer.cpp3
-rw-r--r--cmds/statsd/src/metrics/MetricProducer.h21
-rw-r--r--cmds/statsd/src/metrics/MetricsManager.cpp63
-rw-r--r--cmds/statsd/src/metrics/MetricsManager.h33
-rw-r--r--cmds/statsd/src/metrics/ValueMetricProducer.cpp67
-rw-r--r--cmds/statsd/src/metrics/ValueMetricProducer.h46
-rw-r--r--cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp438
-rw-r--r--cmds/statsd/src/metrics/parsing_utils/config_update_utils.h147
-rw-r--r--cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp (renamed from cmds/statsd/src/metrics/metrics_manager_util.cpp)461
-rw-r--r--cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h (renamed from cmds/statsd/src/metrics/metrics_manager_util.h)74
-rw-r--r--cmds/statsd/src/packages/PackageInfoListener.h2
-rw-r--r--cmds/statsd/src/packages/UidMap.h1
-rw-r--r--cmds/statsd/src/shell/ShellSubscriber.cpp4
-rw-r--r--cmds/statsd/src/stats_log_util.h2
-rw-r--r--cmds/statsd/tests/LogEntryMatcher_test.cpp28
-rw-r--r--cmds/statsd/tests/MetricsManager_test.cpp558
-rw-r--r--cmds/statsd/tests/StatsLogProcessor_test.cpp54
-rw-r--r--cmds/statsd/tests/UidMap_test.cpp2
-rw-r--r--cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp18
-rw-r--r--cmds/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp264
-rw-r--r--cmds/statsd/tests/external/StatsPullerManager_test.cpp16
-rw-r--r--cmds/statsd/tests/metrics/CountMetricProducer_test.cpp19
-rw-r--r--cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp61
-rw-r--r--cmds/statsd/tests/metrics/EventMetricProducer_test.cpp12
-rw-r--r--cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp161
-rw-r--r--cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp1297
-rw-r--r--cmds/statsd/tests/metrics/metrics_test_helper.h9
-rw-r--r--cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp897
-rw-r--r--cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp802
-rw-r--r--cmds/statsd/tests/shell/ShellSubscriber_test.cpp4
-rw-r--r--cmds/statsd/tests/statsd_test_util.cpp16
-rw-r--r--cmds/statsd/tests/statsd_test_util.h4
-rw-r--r--cmds/uinput/Android.bp18
-rw-r--r--cmds/uinput/MODULE_LICENSE_APACHE20
-rw-r--r--cmds/uinput/NOTICE190
-rw-r--r--cmds/uinput/README.md166
-rw-r--r--cmds/uinput/jni/Android.bp23
-rw-r--r--cmds/uinput/jni/com_android_commands_uinput_Device.cpp351
-rw-r--r--cmds/uinput/jni/com_android_commands_uinput_Device.h67
-rw-r--r--cmds/uinput/src/com/android/commands/uinput/Device.java232
-rw-r--r--cmds/uinput/src/com/android/commands/uinput/Event.java454
-rw-r--r--cmds/uinput/src/com/android/commands/uinput/InputAbsInfo.aidl26
-rw-r--r--cmds/uinput/src/com/android/commands/uinput/Uinput.java140
-rwxr-xr-xcmds/uinput/uinput9
124 files changed, 6431 insertions, 3381 deletions
diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
index ed717c491467..4b7eda096e54 100644
--- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
+++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
@@ -19,6 +19,7 @@ package com.android.commands.bmgr;
import android.annotation.IntDef;
import android.annotation.UserIdInt;
import android.app.backup.BackupManager;
+import android.app.backup.BackupManager.OperationType;
import android.app.backup.BackupManagerMonitor;
import android.app.backup.BackupProgress;
import android.app.backup.BackupTransport;
@@ -666,7 +667,7 @@ public class Bmgr {
// The rest of the 'list' options work with a restore session on the current transport
try {
- mRestore = mBmgr.beginRestoreSessionForUser(userId, null, null);
+ mRestore = mBmgr.beginRestoreSessionForUser(userId, null, null, OperationType.BACKUP);
if (mRestore == null) {
System.err.println(BMGR_ERR_NO_RESTORESESSION_FOR_USER + userId);
return;
@@ -821,7 +822,7 @@ public class Bmgr {
try {
boolean didRestore = false;
- mRestore = mBmgr.beginRestoreSessionForUser(userId, null, null);
+ mRestore = mBmgr.beginRestoreSessionForUser(userId, null, null, OperationType.BACKUP);
if (mRestore == null) {
System.err.println(BMGR_ERR_NO_RESTORESESSION_FOR_USER + userId);
return;
diff --git a/cmds/bootanimation/Android.bp b/cmds/bootanimation/Android.bp
index 757c2b2a4cfa..0f569971ff62 100644
--- a/cmds/bootanimation/Android.bp
+++ b/cmds/bootanimation/Android.bp
@@ -60,7 +60,7 @@ cc_library_shared {
shared_libs: [
"libui",
- "libhwui",
+ "libjnigraphics",
"libEGL",
"libGLESv1_CM",
"libgui",
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index bb2de17b42f3..9c796128df84 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -34,6 +34,7 @@
#include <cutils/atomic.h>
#include <cutils/properties.h>
+#include <android/imagedecoder.h>
#include <androidfw/AssetManager.h>
#include <binder/IPCThreadState.h>
#include <utils/Errors.h>
@@ -52,14 +53,6 @@
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
-// TODO: Fix Skia.
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-parameter"
-#include <SkBitmap.h>
-#include <SkImage.h>
-#include <SkStream.h>
-#pragma GCC diagnostic pop
-
#include <GLES/gl.h>
#include <GLES/glext.h>
#include <EGL/eglext.h>
@@ -114,8 +107,8 @@ static constexpr size_t TEXT_POS_LEN_MAX = 16;
// ---------------------------------------------------------------------------
BootAnimation::BootAnimation(sp<Callbacks> callbacks)
- : Thread(false), mClockEnabled(true), mTimeIsAccurate(false), mTimeFormat12Hour(false),
- mTimeCheckThread(nullptr), mCallbacks(callbacks), mLooper(new Looper(false)) {
+ : Thread(false), mLooper(new Looper(false)), mClockEnabled(true), mTimeIsAccurate(false),
+ mTimeFormat12Hour(false), mTimeCheckThread(nullptr), mCallbacks(callbacks) {
mSession = new SurfaceComposerClient();
std::string powerCtl = android::base::GetProperty("sys.powerctl", "");
@@ -165,22 +158,51 @@ void BootAnimation::binderDied(const wp<IBinder>&) {
requestExit();
}
+static void* decodeImage(const void* encodedData, size_t dataLength, AndroidBitmapInfo* outInfo) {
+ AImageDecoder* decoder = nullptr;
+ AImageDecoder_createFromBuffer(encodedData, dataLength, &decoder);
+ if (!decoder) {
+ return nullptr;
+ }
+
+ const AImageDecoderHeaderInfo* info = AImageDecoder_getHeaderInfo(decoder);
+ outInfo->width = AImageDecoderHeaderInfo_getWidth(info);
+ outInfo->height = AImageDecoderHeaderInfo_getHeight(info);
+ outInfo->format = AImageDecoderHeaderInfo_getAndroidBitmapFormat(info);
+ outInfo->stride = AImageDecoder_getMinimumStride(decoder);
+ outInfo->flags = 0;
+
+ const size_t size = outInfo->stride * outInfo->height;
+ void* pixels = malloc(size);
+ int result = AImageDecoder_decodeImage(decoder, pixels, outInfo->stride, size);
+ AImageDecoder_delete(decoder);
+
+ if (result != ANDROID_IMAGE_DECODER_SUCCESS) {
+ free(pixels);
+ return nullptr;
+ }
+ return pixels;
+}
+
status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets,
const char* name) {
Asset* asset = assets.open(name, Asset::ACCESS_BUFFER);
if (asset == nullptr)
return NO_INIT;
- SkBitmap bitmap;
- sk_sp<SkData> data = SkData::MakeWithoutCopy(asset->getBuffer(false),
- asset->getLength());
- sk_sp<SkImage> image = SkImage::MakeFromEncoded(data);
- image->asLegacyBitmap(&bitmap, SkImage::kRO_LegacyBitmapMode);
+
+ AndroidBitmapInfo bitmapInfo;
+ void* pixels = decodeImage(asset->getBuffer(false), asset->getLength(), &bitmapInfo);
+ auto pixelDeleter = std::unique_ptr<void, decltype(free)*>{ pixels, free };
+
asset->close();
delete asset;
- const int w = bitmap.width();
- const int h = bitmap.height();
- const void* p = bitmap.getPixels();
+ if (!pixels) {
+ return NO_INIT;
+ }
+
+ const int w = bitmapInfo.width;
+ const int h = bitmapInfo.height;
GLint crop[4] = { 0, h, w, -h };
texture->w = w;
@@ -189,22 +211,22 @@ status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets,
glGenTextures(1, &texture->name);
glBindTexture(GL_TEXTURE_2D, texture->name);
- switch (bitmap.colorType()) {
- case kAlpha_8_SkColorType:
+ switch (bitmapInfo.format) {
+ case ANDROID_BITMAP_FORMAT_A_8:
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_ALPHA,
- GL_UNSIGNED_BYTE, p);
+ GL_UNSIGNED_BYTE, pixels);
break;
- case kARGB_4444_SkColorType:
+ case ANDROID_BITMAP_FORMAT_RGBA_4444:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA,
- GL_UNSIGNED_SHORT_4_4_4_4, p);
+ GL_UNSIGNED_SHORT_4_4_4_4, pixels);
break;
- case kN32_SkColorType:
+ case ANDROID_BITMAP_FORMAT_RGBA_8888:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA,
- GL_UNSIGNED_BYTE, p);
+ GL_UNSIGNED_BYTE, pixels);
break;
- case kRGB_565_SkColorType:
+ case ANDROID_BITMAP_FORMAT_RGB_565:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB,
- GL_UNSIGNED_SHORT_5_6_5, p);
+ GL_UNSIGNED_SHORT_5_6_5, pixels);
break;
default:
break;
@@ -220,20 +242,21 @@ status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets,
}
status_t BootAnimation::initTexture(FileMap* map, int* width, int* height) {
- SkBitmap bitmap;
- sk_sp<SkData> data = SkData::MakeWithoutCopy(map->getDataPtr(),
- map->getDataLength());
- sk_sp<SkImage> image = SkImage::MakeFromEncoded(data);
- image->asLegacyBitmap(&bitmap, SkImage::kRO_LegacyBitmapMode);
+ AndroidBitmapInfo bitmapInfo;
+ void* pixels = decodeImage(map->getDataPtr(), map->getDataLength(), &bitmapInfo);
+ auto pixelDeleter = std::unique_ptr<void, decltype(free)*>{ pixels, free };
// FileMap memory is never released until application exit.
// Release it now as the texture is already loaded and the memory used for
// the packed resource can be released.
delete map;
- const int w = bitmap.width();
- const int h = bitmap.height();
- const void* p = bitmap.getPixels();
+ if (!pixels) {
+ return NO_INIT;
+ }
+
+ const int w = bitmapInfo.width;
+ const int h = bitmapInfo.height;
GLint crop[4] = { 0, h, w, -h };
int tw = 1 << (31 - __builtin_clz(w));
@@ -241,28 +264,28 @@ status_t BootAnimation::initTexture(FileMap* map, int* width, int* height) {
if (tw < w) tw <<= 1;
if (th < h) th <<= 1;
- switch (bitmap.colorType()) {
- case kN32_SkColorType:
+ switch (bitmapInfo.format) {
+ case ANDROID_BITMAP_FORMAT_RGBA_8888:
if (!mUseNpotTextures && (tw != w || th != h)) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tw, th, 0, GL_RGBA,
GL_UNSIGNED_BYTE, nullptr);
glTexSubImage2D(GL_TEXTURE_2D, 0,
- 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, p);
+ 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
} else {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA,
- GL_UNSIGNED_BYTE, p);
+ GL_UNSIGNED_BYTE, pixels);
}
break;
- case kRGB_565_SkColorType:
+ case ANDROID_BITMAP_FORMAT_RGB_565:
if (!mUseNpotTextures && (tw != w || th != h)) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tw, th, 0, GL_RGB,
GL_UNSIGNED_SHORT_5_6_5, nullptr);
glTexSubImage2D(GL_TEXTURE_2D, 0,
- 0, 0, w, h, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, p);
+ 0, 0, w, h, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
} else {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB,
- GL_UNSIGNED_SHORT_5_6_5, p);
+ GL_UNSIGNED_SHORT_5_6_5, pixels);
}
break;
default:
@@ -394,7 +417,7 @@ status_t BootAnimation::readyToRun() {
// this guest property specifies multi-display IDs to show the boot animation
// multiple ids can be set with comma (,) as separator, for example:
// setprop persist.boot.animation.displays 19260422155234049,19261083906282754
- Vector<uint64_t> physicalDisplayIds;
+ Vector<PhysicalDisplayId> physicalDisplayIds;
char displayValue[PROPERTY_VALUE_MAX] = "";
property_get(DISPLAYS_PROP_NAME, displayValue, "");
bool isValid = displayValue[0] != '\0';
@@ -412,7 +435,7 @@ status_t BootAnimation::readyToRun() {
}
if (isValid) {
std::istringstream stream(displayValue);
- for (PhysicalDisplayId id; stream >> id; ) {
+ for (PhysicalDisplayId id; stream >> id.value; ) {
physicalDisplayIds.add(id);
if (stream.peek() == ',')
stream.ignore();
diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
index 6ba7fd450fbb..9e6e4aa42f1c 100644
--- a/cmds/bootanimation/BootAnimation.h
+++ b/cmds/bootanimation/BootAnimation.h
@@ -32,8 +32,6 @@
#include <EGL/egl.h>
#include <GLES/gl.h>
-class SkBitmap;
-
namespace android {
class Surface;
@@ -150,6 +148,8 @@ private:
// Display event handling
class DisplayEventCallback;
+ std::unique_ptr<DisplayEventReceiver> mDisplayEventReceiver;
+ sp<Looper> mLooper;
int displayEventCallback(int fd, int events, void* data);
void processDisplayEvents();
@@ -202,8 +202,6 @@ private:
sp<TimeCheckThread> mTimeCheckThread = nullptr;
sp<Callbacks> mCallbacks;
Animation* mAnimation = nullptr;
- std::unique_ptr<DisplayEventReceiver> mDisplayEventReceiver;
- sp<Looper> mLooper;
};
// ---------------------------------------------------------------------------
diff --git a/cmds/hid/jni/com_android_commands_hid_Device.cpp b/cmds/hid/jni/com_android_commands_hid_Device.cpp
index 1e200c52a207..437a87e8df54 100644
--- a/cmds/hid/jni/com_android_commands_hid_Device.cpp
+++ b/cmds/hid/jni/com_android_commands_hid_Device.cpp
@@ -27,9 +27,9 @@
#include <cstring>
#include <memory>
-#include <android/log.h>
#include <android/looper.h>
#include <jni.h>
+#include <log/log.h>
#include <nativehelper/JNIHelp.h>
#include <nativehelper/ScopedLocalRef.h>
#include <nativehelper/ScopedPrimitiveArray.h>
@@ -37,10 +37,8 @@
#include <android-base/stringprintf.h>
-#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
-#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)
-#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
-#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
+// Log debug messages about the output.
+static constexpr bool DEBUG_OUTPUT = false;
namespace android {
namespace uhid {
@@ -61,7 +59,7 @@ static int handleLooperEvents(int /* fd */, int events, void* data) {
static void checkAndClearException(JNIEnv* env, const char* methodName) {
if (env->ExceptionCheck()) {
- LOGE("An exception was thrown by callback '%s'.", methodName);
+ ALOGE("An exception was thrown by callback '%s'.", methodName);
env->ExceptionClear();
}
}
@@ -115,9 +113,9 @@ void DeviceCallback::onDeviceGetReport(uint32_t requestId, uint8_t reportId) {
checkAndClearException(env, "onDeviceGetReport");
}
-void DeviceCallback::onDeviceOutput(const std::vector<uint8_t>& data) {
+void DeviceCallback::onDeviceOutput(uint8_t rType, const std::vector<uint8_t>& data) {
JNIEnv* env = getJNIEnv();
- env->CallVoidMethod(mCallbackObject, gDeviceCallbackClassInfo.onDeviceOutput,
+ env->CallVoidMethod(mCallbackObject, gDeviceCallbackClassInfo.onDeviceOutput, rType,
toJbyteArray(env, data).get());
checkAndClearException(env, "onDeviceOutput");
}
@@ -133,13 +131,13 @@ std::unique_ptr<Device> Device::open(int32_t id, const char* name, int32_t vid,
std::unique_ptr<DeviceCallback> callback) {
size_t size = descriptor.size();
if (size > HID_MAX_DESCRIPTOR_SIZE) {
- LOGE("Received invalid hid report with descriptor size %zu, skipping", size);
+ ALOGE("Received invalid hid report with descriptor size %zu, skipping", size);
return nullptr;
}
android::base::unique_fd fd(::open(UHID_PATH, O_RDWR | O_CLOEXEC));
if (!fd.ok()) {
- LOGE("Failed to open uhid: %s", strerror(errno));
+ ALOGE("Failed to open uhid: %s", strerror(errno));
return nullptr;
}
@@ -159,14 +157,14 @@ std::unique_ptr<Device> Device::open(int32_t id, const char* name, int32_t vid,
errno = 0;
ssize_t ret = TEMP_FAILURE_RETRY(::write(fd, &ev, sizeof(ev)));
if (ret < 0 || ret != sizeof(ev)) {
- LOGE("Failed to create uhid node: %s", strerror(errno));
+ ALOGE("Failed to create uhid node: %s", strerror(errno));
return nullptr;
}
// Wait for the device to actually be created.
ret = TEMP_FAILURE_RETRY(::read(fd, &ev, sizeof(ev)));
if (ret < 0 || ev.type != UHID_START) {
- LOGE("uhid node failed to start: %s", strerror(errno));
+ ALOGE("uhid node failed to start: %s", strerror(errno));
return nullptr;
}
// using 'new' to access non-public constructor
@@ -177,7 +175,7 @@ Device::Device(int32_t id, android::base::unique_fd fd, std::unique_ptr<DeviceCa
: mId(id), mFd(std::move(fd)), mDeviceCallback(std::move(callback)) {
ALooper* aLooper = ALooper_forThread();
if (aLooper == NULL) {
- LOGE("Could not get ALooper, ALooper_forThread returned NULL");
+ ALOGE("Could not get ALooper, ALooper_forThread returned NULL");
aLooper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
}
ALooper_addFd(aLooper, mFd, 0, ALOOPER_EVENT_INPUT, handleLooperEvents,
@@ -189,7 +187,7 @@ Device::~Device() {
if (looper != NULL) {
ALooper_removeFd(looper, mFd);
} else {
- LOGE("Could not remove fd, ALooper_forThread() returned NULL!");
+ ALOGE("Could not remove fd, ALooper_forThread() returned NULL!");
}
struct uhid_event ev = {};
ev.type = UHID_DESTROY;
@@ -200,13 +198,13 @@ Device::~Device() {
static void writeEvent(int fd, struct uhid_event& ev, const char* messageType) {
ssize_t ret = TEMP_FAILURE_RETRY(::write(fd, &ev, sizeof(ev)));
if (ret < 0 || ret != sizeof(ev)) {
- LOGE("Failed to send uhid_event %s: %s", messageType, strerror(errno));
+ ALOGE("Failed to send uhid_event %s: %s", messageType, strerror(errno));
}
}
void Device::sendReport(const std::vector<uint8_t>& report) const {
if (report.size() > UHID_DATA_MAX) {
- LOGE("Received invalid report of size %zu, skipping", report.size());
+ ALOGE("Received invalid report of size %zu, skipping", report.size());
return;
}
@@ -230,14 +228,14 @@ void Device::sendGetFeatureReportReply(uint32_t id, const std::vector<uint8_t>&
int Device::handleEvents(int events) {
if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
- LOGE("uhid node was closed or an error occurred. events=0x%x", events);
+ ALOGE("uhid node was closed or an error occurred. events=0x%x", events);
mDeviceCallback->onDeviceError();
return 0;
}
struct uhid_event ev;
ssize_t ret = TEMP_FAILURE_RETRY(::read(mFd, &ev, sizeof(ev)));
if (ret < 0) {
- LOGE("Failed to read from uhid node: %s", strerror(errno));
+ ALOGE("Failed to read from uhid node: %s", strerror(errno));
mDeviceCallback->onDeviceError();
return 0;
}
@@ -254,23 +252,28 @@ int Device::handleEvents(int events) {
case UHID_SET_REPORT: {
const struct uhid_set_report_req& set_report = ev.u.set_report;
if (set_report.size > UHID_DATA_MAX) {
- LOGE("SET_REPORT contains too much data: size = %" PRIu16, set_report.size);
+ ALOGE("SET_REPORT contains too much data: size = %" PRIu16, set_report.size);
return 0;
}
std::vector<uint8_t> data(set_report.data, set_report.data + set_report.size);
- LOGI("Received SET_REPORT: id=%" PRIu32 " rnum=%" PRIu8 " data=%s", set_report.id,
- set_report.rnum, toString(data).c_str());
+ if (DEBUG_OUTPUT) {
+ ALOGD("Received SET_REPORT: id=%" PRIu32 " rnum=%" PRIu8 " data=%s", set_report.id,
+ set_report.rnum, toString(data).c_str());
+ }
break;
}
case UHID_OUTPUT: {
struct uhid_output_req& output = ev.u.output;
std::vector<uint8_t> data(output.data, output.data + output.size);
- mDeviceCallback->onDeviceOutput(data);
+ if (DEBUG_OUTPUT) {
+ ALOGD("UHID_OUTPUT rtype=%" PRIu8 " data=%s", output.rtype, toString(data).c_str());
+ }
+ mDeviceCallback->onDeviceOutput(output.rtype, data);
break;
}
default: {
- LOGI("Unhandled event type: %" PRIu32, ev.type);
+ ALOGI("Unhandled event type: %" PRIu32, ev.type);
break;
}
}
@@ -318,7 +321,7 @@ static void sendReport(JNIEnv* env, jclass /* clazz */, jlong ptr, jbyteArray ra
if (d) {
d->sendReport(report);
} else {
- LOGE("Could not send report, Device* is null!");
+ ALOGE("Could not send report, Device* is null!");
}
}
@@ -329,7 +332,7 @@ static void sendGetFeatureReportReply(JNIEnv* env, jclass /* clazz */, jlong ptr
std::vector<uint8_t> report = getData(env, rawReport);
d->sendGetFeatureReportReply(id, report);
} else {
- LOGE("Could not send get feature report reply, Device* is null!");
+ ALOGE("Could not send get feature report reply, Device* is null!");
}
}
@@ -354,7 +357,7 @@ static JNINativeMethod sMethods[] = {
int register_com_android_commands_hid_Device(JNIEnv* env) {
jclass clazz = env->FindClass("com/android/commands/hid/Device$DeviceCallback");
if (clazz == NULL) {
- LOGE("Unable to find class 'DeviceCallback'");
+ ALOGE("Unable to find class 'DeviceCallback'");
return JNI_ERR;
}
uhid::gDeviceCallbackClassInfo.onDeviceOpen =
@@ -362,12 +365,12 @@ int register_com_android_commands_hid_Device(JNIEnv* env) {
uhid::gDeviceCallbackClassInfo.onDeviceGetReport =
env->GetMethodID(clazz, "onDeviceGetReport", "(II)V");
uhid::gDeviceCallbackClassInfo.onDeviceOutput =
- env->GetMethodID(clazz, "onDeviceOutput", "([B)V");
+ env->GetMethodID(clazz, "onDeviceOutput", "(B[B)V");
uhid::gDeviceCallbackClassInfo.onDeviceError =
env->GetMethodID(clazz, "onDeviceError", "()V");
if (uhid::gDeviceCallbackClassInfo.onDeviceOpen == NULL ||
uhid::gDeviceCallbackClassInfo.onDeviceError == NULL) {
- LOGE("Unable to obtain onDeviceOpen or onDeviceError methods");
+ ALOGE("Unable to obtain onDeviceOpen or onDeviceError methods");
return JNI_ERR;
}
diff --git a/cmds/hid/jni/com_android_commands_hid_Device.h b/cmds/hid/jni/com_android_commands_hid_Device.h
index 7202b45adcde..5483b40831a0 100644
--- a/cmds/hid/jni/com_android_commands_hid_Device.h
+++ b/cmds/hid/jni/com_android_commands_hid_Device.h
@@ -31,7 +31,7 @@ public:
void onDeviceOpen();
void onDeviceGetReport(uint32_t requestId, uint8_t reportId);
- void onDeviceOutput(const std::vector<uint8_t>& data);
+ void onDeviceOutput(uint8_t rType, const std::vector<uint8_t>& data);
void onDeviceError();
private:
diff --git a/cmds/hid/src/com/android/commands/hid/Device.java b/cmds/hid/src/com/android/commands/hid/Device.java
index dade41511ae6..20b4bd86baec 100644
--- a/cmds/hid/src/com/android/commands/hid/Device.java
+++ b/cmds/hid/src/com/android/commands/hid/Device.java
@@ -26,6 +26,12 @@ import android.util.SparseArray;
import com.android.internal.os.SomeArgs;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.IOException;
+import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Map;
@@ -38,12 +44,16 @@ public class Device {
private static final int MSG_SEND_GET_FEATURE_REPORT_REPLY = 3;
private static final int MSG_CLOSE_DEVICE = 4;
+ // Sync with linux uhid_event_type::UHID_OUTPUT
+ private static final byte UHID_EVENT_TYPE_UHID_OUTPUT = 6;
+
private final int mId;
private final HandlerThread mThread;
private final DeviceHandler mHandler;
// mFeatureReports is limited to 256 entries, because the report number is 8-bit
private final SparseArray<byte[]> mFeatureReports;
private final Map<ByteBuffer, byte[]> mOutputs;
+ private final OutputStream mOutputStream;
private long mTimeToSend;
private final Object mCond = new Object();
@@ -66,6 +76,7 @@ public class Device {
mHandler = new DeviceHandler(mThread.getLooper());
mFeatureReports = featureReports;
mOutputs = outputs;
+ mOutputStream = System.out;
SomeArgs args = SomeArgs.obtain();
args.argi1 = id;
args.argi2 = vid;
@@ -188,7 +199,27 @@ public class Device {
}
// native callback
- public void onDeviceOutput(byte[] data) {
+ public void onDeviceOutput(byte rtype, byte[] data) {
+ JSONObject json = new JSONObject();
+ try {
+ json.put("eventId", UHID_EVENT_TYPE_UHID_OUTPUT);
+ json.put("deviceId", mId);
+ json.put("reportType", rtype);
+ JSONArray dataArray = new JSONArray();
+ for (int i = 0; i < data.length; i++) {
+ dataArray.put(data[i] & 0xFF);
+ }
+ json.put("reportData", dataArray);
+ } catch (JSONException e) {
+ throw new RuntimeException("Could not create JSON object ", e);
+ }
+ try {
+ mOutputStream.write(json.toString().getBytes());
+ mOutputStream.flush();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
if (mOutputs == null) {
Log.e(TAG, "Received OUTPUT request, but 'outputs' section is not found");
return;
diff --git a/cmds/idmap2/Android.bp b/cmds/idmap2/Android.bp
index 878cef94b674..e21a6b288fb3 100644
--- a/cmds/idmap2/Android.bp
+++ b/cmds/idmap2/Android.bp
@@ -181,7 +181,6 @@ cc_binary {
"idmap2/Dump.cpp",
"idmap2/Lookup.cpp",
"idmap2/Main.cpp",
- "idmap2/Scan.cpp",
],
target: {
android: {
diff --git a/cmds/idmap2/idmap2/Commands.h b/cmds/idmap2/idmap2/Commands.h
index 69eea8d262d2..4099671066a2 100644
--- a/cmds/idmap2/idmap2/Commands.h
+++ b/cmds/idmap2/idmap2/Commands.h
@@ -26,6 +26,5 @@ android::idmap2::Result<android::idmap2::Unit> Create(const std::vector<std::str
android::idmap2::Result<android::idmap2::Unit> CreateMultiple(const std::vector<std::string>& args);
android::idmap2::Result<android::idmap2::Unit> Dump(const std::vector<std::string>& args);
android::idmap2::Result<android::idmap2::Unit> Lookup(const std::vector<std::string>& args);
-android::idmap2::Result<android::idmap2::Unit> Scan(const std::vector<std::string>& args);
#endif // IDMAP2_IDMAP2_COMMANDS_H_
diff --git a/cmds/idmap2/idmap2/Create.cpp b/cmds/idmap2/idmap2/Create.cpp
index 9682b6ead293..648b78e24c23 100644
--- a/cmds/idmap2/idmap2/Create.cpp
+++ b/cmds/idmap2/idmap2/Create.cpp
@@ -20,6 +20,7 @@
#include <fstream>
#include <memory>
#include <ostream>
+#include <string>
#include <vector>
#include "androidfw/ResourceTypes.h"
diff --git a/cmds/idmap2/idmap2/CreateMultiple.cpp b/cmds/idmap2/idmap2/CreateMultiple.cpp
index abdfaf4dccab..19622c4ef65a 100644
--- a/cmds/idmap2/idmap2/CreateMultiple.cpp
+++ b/cmds/idmap2/idmap2/CreateMultiple.cpp
@@ -20,6 +20,7 @@
#include <fstream>
#include <memory>
#include <ostream>
+#include <string>
#include <vector>
#include "Commands.h"
diff --git a/cmds/idmap2/idmap2/Main.cpp b/cmds/idmap2/idmap2/Main.cpp
index fb093f0f22a4..aa6d0e76698f 100644
--- a/cmds/idmap2/idmap2/Main.cpp
+++ b/cmds/idmap2/idmap2/Main.cpp
@@ -53,8 +53,10 @@ void PrintUsage(const NameToFunctionMap& commands, std::ostream& out) {
int main(int argc, char** argv) {
SYSTRACE << "main";
const NameToFunctionMap commands = {
- {"create", Create}, {"create-multiple", CreateMultiple}, {"dump", Dump}, {"lookup", Lookup},
- {"scan", Scan},
+ {"create", Create},
+ {"create-multiple", CreateMultiple},
+ {"dump", Dump},
+ {"lookup", Lookup},
};
if (argc <= 1) {
PrintUsage(commands, std::cerr);
diff --git a/cmds/idmap2/idmap2/Scan.cpp b/cmds/idmap2/idmap2/Scan.cpp
deleted file mode 100644
index 36250450cc74..000000000000
--- a/cmds/idmap2/idmap2/Scan.cpp
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <dirent.h>
-
-#include <fstream>
-#include <memory>
-#include <ostream>
-#include <set>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "Commands.h"
-#include "android-base/properties.h"
-#include "idmap2/CommandLineOptions.h"
-#include "idmap2/CommandUtils.h"
-#include "idmap2/FileUtils.h"
-#include "idmap2/Idmap.h"
-#include "idmap2/Policies.h"
-#include "idmap2/PolicyUtils.h"
-#include "idmap2/ResourceUtils.h"
-#include "idmap2/Result.h"
-#include "idmap2/SysTrace.h"
-#include "idmap2/XmlParser.h"
-
-using android::idmap2::CommandLineOptions;
-using android::idmap2::Error;
-using android::idmap2::Idmap;
-using android::idmap2::Result;
-using android::idmap2::Unit;
-using android::idmap2::policy::kPolicyOdm;
-using android::idmap2::policy::kPolicyOem;
-using android::idmap2::policy::kPolicyProduct;
-using android::idmap2::policy::kPolicyPublic;
-using android::idmap2::policy::kPolicySystem;
-using android::idmap2::policy::kPolicyVendor;
-using android::idmap2::utils::ExtractOverlayManifestInfo;
-using android::idmap2::utils::FindFiles;
-using android::idmap2::utils::OverlayManifestInfo;
-using android::idmap2::utils::PoliciesToBitmaskResult;
-
-using PolicyBitmask = android::ResTable_overlayable_policy_header::PolicyBitmask;
-
-namespace {
-
-struct InputOverlay {
- bool operator<(InputOverlay const& rhs) const {
- return priority < rhs.priority || (priority == rhs.priority && apk_path < rhs.apk_path);
- }
-
- std::string apk_path; // NOLINT(misc-non-private-member-variables-in-classes)
- std::string idmap_path; // NOLINT(misc-non-private-member-variables-in-classes)
- int priority; // NOLINT(misc-non-private-member-variables-in-classes)
- std::vector<std::string> policies; // NOLINT(misc-non-private-member-variables-in-classes)
- bool ignore_overlayable; // NOLINT(misc-non-private-member-variables-in-classes)
-};
-
-bool VendorIsQOrLater() {
- constexpr int kQSdkVersion = 29;
- constexpr int kBase = 10;
- std::string version_prop = android::base::GetProperty("ro.vndk.version", "29");
- int version = strtol(version_prop.data(), nullptr, kBase);
-
- // If the string cannot be parsed, it is a development sdk codename.
- return version >= kQSdkVersion || version == 0;
-}
-
-Result<std::unique_ptr<std::vector<std::string>>> FindApkFiles(const std::vector<std::string>& dirs,
- bool recursive) {
- SYSTRACE << "FindApkFiles " << dirs << " " << recursive;
- const auto predicate = [](unsigned char type, const std::string& path) -> bool {
- static constexpr size_t kExtLen = 4; // strlen(".apk")
- return type == DT_REG && path.size() > kExtLen &&
- path.compare(path.size() - kExtLen, kExtLen, ".apk") == 0;
- };
- // pass apk paths through a set to filter out duplicates
- std::set<std::string> paths;
- for (const auto& dir : dirs) {
- const auto apk_paths = FindFiles(dir, recursive, predicate);
- if (!apk_paths) {
- return Error("failed to open directory %s", dir.c_str());
- }
- paths.insert(apk_paths->cbegin(), apk_paths->cend());
- }
- return std::make_unique<std::vector<std::string>>(paths.cbegin(), paths.cend());
-}
-
-std::vector<std::string> PoliciesForPath(const std::string& apk_path) {
- // clang-format off
- static const std::vector<std::pair<std::string, std::string>> values = {
- {"/odm/", kPolicyOdm},
- {"/oem/", kPolicyOem},
- {"/product/", kPolicyProduct},
- {"/system/", kPolicySystem},
- {"/system_ext/", kPolicySystem},
- {"/vendor/", kPolicyVendor},
- };
- // clang-format on
-
- std::vector<std::string> fulfilled_policies = {kPolicyPublic};
- for (auto const& pair : values) {
- if (apk_path.compare(0, pair.first.size(), pair.first) == 0) {
- fulfilled_policies.emplace_back(pair.second);
- break;
- }
- }
-
- return fulfilled_policies;
-}
-
-} // namespace
-
-Result<Unit> Scan(const std::vector<std::string>& args) {
- SYSTRACE << "Scan " << args;
- std::vector<std::string> input_directories;
- std::string target_package_name;
- std::string target_apk_path;
- std::string output_directory;
- std::vector<std::string> override_policies;
- bool recursive = false;
-
- const CommandLineOptions opts =
- CommandLineOptions("idmap2 scan")
- .MandatoryOption("--input-directory", "directory containing overlay apks to scan",
- &input_directories)
- .OptionalFlag("--recursive", "also scan subfolders of overlay-directory", &recursive)
- .MandatoryOption("--target-package-name", "package name of target package",
- &target_package_name)
- .MandatoryOption("--target-apk-path", "path to target apk", &target_apk_path)
- .MandatoryOption("--output-directory",
- "directory in which to write artifacts (idmap files and overlays.list)",
- &output_directory)
- .OptionalOption(
- "--override-policy",
- "input: an overlayable policy this overlay fulfills "
- "(if none or supplied, the overlays will not have their policies overriden",
- &override_policies);
- const auto opts_ok = opts.Parse(args);
- if (!opts_ok) {
- return opts_ok.GetError();
- }
-
- const auto apk_paths = FindApkFiles(input_directories, recursive);
- if (!apk_paths) {
- return Error(apk_paths.GetError(), "failed to find apk files");
- }
-
- std::vector<InputOverlay> interesting_apks;
- for (const std::string& path : **apk_paths) {
- Result<OverlayManifestInfo> overlay_info =
- ExtractOverlayManifestInfo(path, /* assert_overlay */ false);
- if (!overlay_info) {
- return overlay_info.GetError();
- }
-
- if (!overlay_info->is_static) {
- continue;
- }
-
- if (overlay_info->target_package.empty() ||
- overlay_info->target_package != target_package_name) {
- continue;
- }
-
- if (overlay_info->priority < 0) {
- continue;
- }
-
- // Note that conditional property enablement/exclusion only applies if
- // the attribute is present. In its absence, all overlays are presumed enabled.
- if (!overlay_info->requiredSystemPropertyName.empty() &&
- !overlay_info->requiredSystemPropertyValue.empty()) {
- // if property set & equal to value, then include overlay - otherwise skip
- if (android::base::GetProperty(overlay_info->requiredSystemPropertyName, "") !=
- overlay_info->requiredSystemPropertyValue) {
- continue;
- }
- }
-
- std::vector<std::string> fulfilled_policies;
- if (!override_policies.empty()) {
- fulfilled_policies = override_policies;
- } else {
- fulfilled_policies = PoliciesForPath(path);
- }
-
- bool ignore_overlayable = false;
- if (std::find(fulfilled_policies.begin(), fulfilled_policies.end(), kPolicyVendor) !=
- fulfilled_policies.end() &&
- !VendorIsQOrLater()) {
- // If the overlay is on a pre-Q vendor partition, do not enforce overlayable
- // restrictions on this overlay because the pre-Q platform has no understanding of
- // overlayable.
- ignore_overlayable = true;
- }
-
- std::string idmap_path = Idmap::CanonicalIdmapPathFor(output_directory, path);
-
- // Sort the static overlays in ascending priority order
- InputOverlay input{path, idmap_path, overlay_info->priority, fulfilled_policies,
- ignore_overlayable};
- interesting_apks.insert(
- std::lower_bound(interesting_apks.begin(), interesting_apks.end(), input), input);
- }
-
- std::stringstream stream;
- for (const auto& overlay : interesting_apks) {
- const auto policy_bitmask = PoliciesToBitmaskResult(overlay.policies);
- if (!policy_bitmask) {
- LOG(WARNING) << "failed to create idmap for overlay apk path \"" << overlay.apk_path
- << "\": " << policy_bitmask.GetErrorMessage();
- continue;
- }
-
- if (!Verify(overlay.idmap_path, target_apk_path, overlay.apk_path, *policy_bitmask,
- !overlay.ignore_overlayable)) {
- std::vector<std::string> create_args = {"--target-apk-path", target_apk_path,
- "--overlay-apk-path", overlay.apk_path,
- "--idmap-path", overlay.idmap_path};
- if (overlay.ignore_overlayable) {
- create_args.emplace_back("--ignore-overlayable");
- }
-
- for (const std::string& policy : overlay.policies) {
- create_args.emplace_back("--policy");
- create_args.emplace_back(policy);
- }
-
- const auto create_ok = Create(create_args);
- if (!create_ok) {
- LOG(WARNING) << "failed to create idmap for overlay apk path \"" << overlay.apk_path
- << "\": " << create_ok.GetError().GetMessage();
- continue;
- }
- }
-
- stream << overlay.idmap_path << std::endl;
- }
-
- std::cout << stream.str();
-
- return Unit{};
-}
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.h b/cmds/idmap2/idmap2d/Idmap2Service.h
index abee999dd2b2..1a445192aff8 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.h
+++ b/cmds/idmap2/idmap2d/Idmap2Service.h
@@ -17,6 +17,8 @@
#ifndef IDMAP2_IDMAP2D_IDMAP2SERVICE_H_
#define IDMAP2_IDMAP2D_IDMAP2SERVICE_H_
+#include <string>
+
#include <android-base/unique_fd.h>
#include <binder/BinderService.h>
diff --git a/cmds/idmap2/idmap2d/aidl/android/os/OverlayablePolicy.aidl b/cmds/idmap2/idmap2d/aidl/android/os/OverlayablePolicy.aidl
index 02b27a8800b6..403d8c55de16 100644
--- a/cmds/idmap2/idmap2d/aidl/android/os/OverlayablePolicy.aidl
+++ b/cmds/idmap2/idmap2d/aidl/android/os/OverlayablePolicy.aidl
@@ -29,4 +29,5 @@ interface OverlayablePolicy {
const int ODM_PARTITION = 0x00000020;
const int OEM_PARTITION = 0x00000040;
const int ACTOR_SIGNATURE = 0x00000080;
+ const int CONFIG_SIGNATURE = 0x0000100;
}
diff --git a/cmds/idmap2/include/idmap2/FileUtils.h b/cmds/idmap2/include/idmap2/FileUtils.h
index 3f03236d5e1a..c4e0e1fd8ef0 100644
--- a/cmds/idmap2/include/idmap2/FileUtils.h
+++ b/cmds/idmap2/include/idmap2/FileUtils.h
@@ -17,27 +17,13 @@
#ifndef IDMAP2_INCLUDE_IDMAP2_FILEUTILS_H_
#define IDMAP2_INCLUDE_IDMAP2_FILEUTILS_H_
-#include <sys/types.h>
-
-#include <functional>
-#include <memory>
#include <string>
-#include <vector>
namespace android::idmap2::utils {
constexpr const char* kIdmapCacheDir = "/data/resource-cache";
constexpr const mode_t kIdmapFilePermissionMask = 0133; // u=rw,g=r,o=r
-typedef std::function<bool(unsigned char type /* DT_* from dirent.h */, const std::string& path)>
- FindFilesPredicate;
-std::unique_ptr<std::vector<std::string>> FindFiles(const std::string& root, bool recurse,
- const FindFilesPredicate& predicate);
-
-std::unique_ptr<std::string> ReadFile(int fd);
-
-std::unique_ptr<std::string> ReadFile(const std::string& path);
-
bool UidHasWriteAccessToPath(uid_t uid, const std::string& path);
} // namespace android::idmap2::utils
diff --git a/cmds/idmap2/libidmap2/FileUtils.cpp b/cmds/idmap2/libidmap2/FileUtils.cpp
index 3e8e32989a09..3af1f70ebe39 100644
--- a/cmds/idmap2/libidmap2/FileUtils.cpp
+++ b/cmds/idmap2/libidmap2/FileUtils.cpp
@@ -16,19 +16,7 @@
#include "idmap2/FileUtils.h"
-#include <dirent.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <cerrno>
-#include <climits>
-#include <cstdlib>
-#include <cstring>
-#include <fstream>
-#include <memory>
#include <string>
-#include <utility>
-#include <vector>
#include "android-base/file.h"
#include "android-base/macros.h"
@@ -37,54 +25,6 @@
namespace android::idmap2::utils {
-std::unique_ptr<std::vector<std::string>> FindFiles(const std::string& root, bool recurse,
- const FindFilesPredicate& predicate) {
- DIR* dir = opendir(root.c_str());
- if (dir == nullptr) {
- return nullptr;
- }
- std::unique_ptr<std::vector<std::string>> vector(new std::vector<std::string>());
- struct dirent* dirent;
- while ((dirent = readdir(dir)) != nullptr) {
- const std::string path = root + "/" + dirent->d_name;
- if (predicate(dirent->d_type, path)) {
- vector->push_back(path);
- }
- if (recurse && dirent->d_type == DT_DIR && strcmp(dirent->d_name, ".") != 0 &&
- strcmp(dirent->d_name, "..") != 0) {
- auto sub_vector = FindFiles(path, recurse, predicate);
- if (!sub_vector) {
- closedir(dir);
- return nullptr;
- }
- vector->insert(vector->end(), sub_vector->begin(), sub_vector->end());
- }
- }
- closedir(dir);
-
- return vector;
-}
-
-std::unique_ptr<std::string> ReadFile(const std::string& path) {
- std::unique_ptr<std::string> str(new std::string());
- std::ifstream fin(path);
- str->append({std::istreambuf_iterator<char>(fin), std::istreambuf_iterator<char>()});
- fin.close();
- return str;
-}
-
-std::unique_ptr<std::string> ReadFile(int fd) {
- static constexpr const size_t kBufSize = 1024;
-
- std::unique_ptr<std::string> str(new std::string());
- char buf[kBufSize];
- ssize_t r;
- while ((r = read(fd, buf, sizeof(buf))) > 0) {
- str->append(buf, r);
- }
- return r == 0 ? std::move(str) : nullptr;
-}
-
#ifdef __ANDROID__
bool UidHasWriteAccessToPath(uid_t uid, const std::string& path) {
// resolve symlinks and relative paths; the directories must exist
diff --git a/cmds/idmap2/libidmap2/PolicyUtils.cpp b/cmds/idmap2/libidmap2/PolicyUtils.cpp
index fc5182af61c1..4e3f54d2583e 100644
--- a/cmds/idmap2/libidmap2/PolicyUtils.cpp
+++ b/cmds/idmap2/libidmap2/PolicyUtils.cpp
@@ -17,6 +17,8 @@
#include "include/idmap2/PolicyUtils.h"
#include <sstream>
+#include <string>
+#include <vector>
#include "android-base/strings.h"
#include "idmap2/Policies.h"
diff --git a/cmds/idmap2/libidmap2/ResourceMapping.cpp b/cmds/idmap2/libidmap2/ResourceMapping.cpp
index 34589a1c39dc..fd8b4eb86b4a 100644
--- a/cmds/idmap2/libidmap2/ResourceMapping.cpp
+++ b/cmds/idmap2/libidmap2/ResourceMapping.cpp
@@ -61,10 +61,13 @@ Result<Unit> CheckOverlayable(const LoadedPackage& target_package,
const ResourceId& target_resource) {
static constexpr const PolicyBitmask sDefaultPolicies =
PolicyFlags::ODM_PARTITION | PolicyFlags::OEM_PARTITION | PolicyFlags::SYSTEM_PARTITION |
- PolicyFlags::VENDOR_PARTITION | PolicyFlags::PRODUCT_PARTITION | PolicyFlags::SIGNATURE;
+ PolicyFlags::VENDOR_PARTITION | PolicyFlags::PRODUCT_PARTITION | PolicyFlags::SIGNATURE |
+ PolicyFlags::CONFIG_SIGNATURE;
// If the resource does not have an overlayable definition, allow the resource to be overlaid if
- // the overlay is preinstalled or signed with the same signature as the target.
+ // the overlay is preinstalled, signed with the same signature as the target or signed with the
+ // same signature as reference package defined in SystemConfig under 'overlay-config-signature'
+ // tag.
if (!target_package.DefinesOverlayable()) {
return (sDefaultPolicies & fulfilled_policies) != 0
? Result<Unit>({})
diff --git a/cmds/idmap2/libidmap2_policies/include/idmap2/Policies.h b/cmds/idmap2/libidmap2_policies/include/idmap2/Policies.h
index 5bd353af4ad3..cdce45191094 100644
--- a/cmds/idmap2/libidmap2_policies/include/idmap2/Policies.h
+++ b/cmds/idmap2/libidmap2_policies/include/idmap2/Policies.h
@@ -14,11 +14,12 @@
* limitations under the License.
*/
-#ifndef IDMAP2_INCLUDE_IDMAP2_POLICIES_H_
-#define IDMAP2_INCLUDE_IDMAP2_POLICIES_H_
+#ifndef IDMAP2_LIBIDMAP2_POLICIES_INCLUDE_IDMAP2_POLICIES_H_
+#define IDMAP2_LIBIDMAP2_POLICIES_INCLUDE_IDMAP2_POLICIES_H_
#include <array>
#include <string>
+#include <utility>
#include <vector>
#include "android-base/stringprintf.h"
@@ -37,16 +38,18 @@ constexpr const char* kPolicyOdm = "odm";
constexpr const char* kPolicyOem = "oem";
constexpr const char* kPolicyProduct = "product";
constexpr const char* kPolicyPublic = "public";
+constexpr const char* kPolicyConfigSignature = "config_signature";
constexpr const char* kPolicySignature = "signature";
constexpr const char* kPolicySystem = "system";
constexpr const char* kPolicyVendor = "vendor";
-inline static const std::array<std::pair<StringPiece, PolicyFlags>, 8> kPolicyStringToFlag = {
+inline static const std::array<std::pair<StringPiece, PolicyFlags>, 9> kPolicyStringToFlag = {
std::pair{kPolicyActor, PolicyFlags::ACTOR_SIGNATURE},
{kPolicyOdm, PolicyFlags::ODM_PARTITION},
{kPolicyOem, PolicyFlags::OEM_PARTITION},
{kPolicyProduct, PolicyFlags::PRODUCT_PARTITION},
{kPolicyPublic, PolicyFlags::PUBLIC},
+ {kPolicyConfigSignature, PolicyFlags::CONFIG_SIGNATURE},
{kPolicySignature, PolicyFlags::SIGNATURE},
{kPolicySystem, PolicyFlags::SYSTEM_PARTITION},
{kPolicyVendor, PolicyFlags::VENDOR_PARTITION},
@@ -76,4 +79,4 @@ inline static std::string PoliciesToDebugString(PolicyBitmask policies) {
} // namespace android::idmap2::policy
-#endif // IDMAP2_INCLUDE_IDMAP2_POLICIES_H_
+#endif // IDMAP2_LIBIDMAP2_POLICIES_INCLUDE_IDMAP2_POLICIES_H_
diff --git a/cmds/idmap2/tests/FileUtilsTests.cpp b/cmds/idmap2/tests/FileUtilsTests.cpp
index 8af4037be954..5750ca1f49c5 100644
--- a/cmds/idmap2/tests/FileUtilsTests.cpp
+++ b/cmds/idmap2/tests/FileUtilsTests.cpp
@@ -14,73 +14,16 @@
* limitations under the License.
*/
-#include <dirent.h>
-#include <fcntl.h>
-
-#include <set>
#include <string>
#include "TestHelpers.h"
-#include "android-base/macros.h"
#include "android-base/stringprintf.h"
-#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "idmap2/FileUtils.h"
#include "private/android_filesystem_config.h"
-using ::testing::NotNull;
-
namespace android::idmap2::utils {
-TEST(FileUtilsTests, FindFilesFindEverythingNonRecursive) {
- const auto& root = GetTestDataPath();
- auto v = utils::FindFiles(root, false,
- [](unsigned char type ATTRIBUTE_UNUSED,
- const std::string& path ATTRIBUTE_UNUSED) -> bool { return true; });
- ASSERT_THAT(v, NotNull());
- ASSERT_EQ(v->size(), 7U);
- ASSERT_EQ(std::set<std::string>(v->begin(), v->end()), std::set<std::string>({
- root + "/.",
- root + "/..",
- root + "/overlay",
- root + "/target",
- root + "/signature-overlay",
- root + "/system-overlay",
- root + "/system-overlay-invalid",
- }));
-}
-
-TEST(FileUtilsTests, FindFilesFindApkFilesRecursive) {
- const auto& root = GetTestDataPath();
- auto v = utils::FindFiles(root, true, [](unsigned char type, const std::string& path) -> bool {
- return type == DT_REG && path.size() > 4 && path.compare(path.size() - 4, 4, ".apk") == 0;
- });
- ASSERT_THAT(v, NotNull());
- ASSERT_EQ(v->size(), 11U);
- ASSERT_EQ(std::set<std::string>(v->begin(), v->end()),
- std::set<std::string>(
- {root + "/target/target.apk", root + "/target/target-no-overlayable.apk",
- root + "/overlay/overlay.apk", root + "/overlay/overlay-no-name.apk",
- root + "/overlay/overlay-no-name-static.apk", root + "/overlay/overlay-shared.apk",
- root + "/overlay/overlay-static-1.apk", root + "/overlay/overlay-static-2.apk",
- root + "/signature-overlay/signature-overlay.apk",
- root + "/system-overlay/system-overlay.apk",
- root + "/system-overlay-invalid/system-overlay-invalid.apk"}));
-}
-
-TEST(FileUtilsTests, ReadFile) {
- int pipefd[2];
- ASSERT_EQ(pipe2(pipefd, O_CLOEXEC), 0);
-
- ASSERT_EQ(write(pipefd[1], "foobar", 6), 6);
- close(pipefd[1]);
-
- auto data = ReadFile(pipefd[0]);
- ASSERT_THAT(data, NotNull());
- ASSERT_EQ(*data, "foobar");
- close(pipefd[0]);
-}
-
#ifdef __ANDROID__
TEST(FileUtilsTests, UidHasWriteAccessToPath) {
constexpr const char* tmp_path = "/data/local/tmp/test@idmap";
diff --git a/cmds/idmap2/tests/Idmap2BinaryTests.cpp b/cmds/idmap2/tests/Idmap2BinaryTests.cpp
index d896cf9c11ba..61751b33dcba 100644
--- a/cmds/idmap2/tests/Idmap2BinaryTests.cpp
+++ b/cmds/idmap2/tests/Idmap2BinaryTests.cpp
@@ -159,131 +159,6 @@ TEST_F(Idmap2BinaryTests, Dump) {
unlink(GetIdmapPath().c_str());
}
-TEST_F(Idmap2BinaryTests, Scan) {
- SKIP_TEST_IF_CANT_EXEC_IDMAP2;
-
- const std::string overlay_static_no_name_apk_path =
- GetTestDataPath() + "/overlay/overlay-no-name-static.apk";
- const std::string overlay_static_1_apk_path = GetTestDataPath() + "/overlay/overlay-static-1.apk";
- const std::string overlay_static_2_apk_path = GetTestDataPath() + "/overlay/overlay-static-2.apk";
- const std::string idmap_static_no_name_path =
- Idmap::CanonicalIdmapPathFor(GetTempDirPath(), overlay_static_no_name_apk_path);
- const std::string idmap_static_1_path =
- Idmap::CanonicalIdmapPathFor(GetTempDirPath(), overlay_static_1_apk_path);
- const std::string idmap_static_2_path =
- Idmap::CanonicalIdmapPathFor(GetTempDirPath(), overlay_static_2_apk_path);
-
- // single input directory, recursive
- // clang-format off
- auto result = ExecuteBinary({"idmap2",
- "scan",
- "--input-directory", GetTestDataPath(),
- "--recursive",
- "--target-package-name", "test.target",
- "--target-apk-path", GetTargetApkPath(),
- "--output-directory", GetTempDirPath(),
- "--override-policy", "public"});
- // clang-format on
- ASSERT_THAT(result, NotNull());
- ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
- std::stringstream expected;
- expected << idmap_static_no_name_path << std::endl;
- expected << idmap_static_1_path << std::endl;
- expected << idmap_static_2_path << std::endl;
- ASSERT_EQ(result->stdout, expected.str());
-
- auto idmap_static_no_name_raw_string = utils::ReadFile(idmap_static_no_name_path);
- auto idmap_static_no_name_raw_stream = std::istringstream(*idmap_static_no_name_raw_string);
- auto idmap_static_no_name = Idmap::FromBinaryStream(idmap_static_no_name_raw_stream);
- ASSERT_TRUE(idmap_static_no_name);
- ASSERT_IDMAP(**idmap_static_no_name, GetTargetApkPath(), overlay_static_no_name_apk_path);
-
- auto idmap_static_1_raw_string = utils::ReadFile(idmap_static_1_path);
- auto idmap_static_1_raw_stream = std::istringstream(*idmap_static_1_raw_string);
- auto idmap_static_1 = Idmap::FromBinaryStream(idmap_static_1_raw_stream);
- ASSERT_TRUE(idmap_static_1);
- ASSERT_IDMAP(**idmap_static_1, GetTargetApkPath(), overlay_static_1_apk_path);
-
- auto idmap_static_2_raw_string = utils::ReadFile(idmap_static_2_path);
- auto idmap_static_2_raw_stream = std::istringstream(*idmap_static_2_raw_string);
- auto idmap_static_2 = Idmap::FromBinaryStream(idmap_static_2_raw_stream);
- ASSERT_TRUE(idmap_static_2);
- ASSERT_IDMAP(**idmap_static_2, GetTargetApkPath(), overlay_static_2_apk_path);
-
- unlink(idmap_static_no_name_path.c_str());
- unlink(idmap_static_2_path.c_str());
- unlink(idmap_static_1_path.c_str());
-
- // multiple input directories, non-recursive
- // clang-format off
- result = ExecuteBinary({"idmap2",
- "scan",
- "--input-directory", GetTestDataPath() + "/target",
- "--input-directory", GetTestDataPath() + "/overlay",
- "--target-package-name", "test.target",
- "--target-apk-path", GetTargetApkPath(),
- "--output-directory", GetTempDirPath(),
- "--override-policy", "public"});
- // clang-format on
- ASSERT_THAT(result, NotNull());
- ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
- ASSERT_EQ(result->stdout, expected.str());
- unlink(idmap_static_no_name_path.c_str());
- unlink(idmap_static_2_path.c_str());
- unlink(idmap_static_1_path.c_str());
-
- // the same input directory given twice, but no duplicate entries
- // clang-format off
- result = ExecuteBinary({"idmap2",
- "scan",
- "--input-directory", GetTestDataPath(),
- "--input-directory", GetTestDataPath(),
- "--recursive",
- "--target-package-name", "test.target",
- "--target-apk-path", GetTargetApkPath(),
- "--output-directory", GetTempDirPath(),
- "--override-policy", "public"});
- // clang-format on
- ASSERT_THAT(result, NotNull());
- ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
- ASSERT_EQ(result->stdout, expected.str());
- unlink(idmap_static_no_name_path.c_str());
- unlink(idmap_static_2_path.c_str());
- unlink(idmap_static_1_path.c_str());
-
- // no APKs in input-directory: ok, but no output
- // clang-format off
- result = ExecuteBinary({"idmap2",
- "scan",
- "--input-directory", GetTempDirPath(),
- "--target-package-name", "test.target",
- "--target-apk-path", GetTargetApkPath(),
- "--output-directory", GetTempDirPath(),
- "--override-policy", "public"});
- // clang-format on
- ASSERT_THAT(result, NotNull());
- ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
- ASSERT_EQ(result->stdout, "");
-
- // the signature idmap failing to generate should not cause scanning to fail
- // clang-format off
- result = ExecuteBinary({"idmap2",
- "scan",
- "--input-directory", GetTestDataPath(),
- "--recursive",
- "--target-package-name", "test.target",
- "--target-apk-path", GetTargetApkPath(),
- "--output-directory", GetTempDirPath(),
- "--override-policy", "public"});
- // clang-format on
- ASSERT_THAT(result, NotNull());
- ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
- ASSERT_EQ(result->stdout, expected.str());
- unlink(idmap_static_no_name_path.c_str());
- unlink(idmap_static_2_path.c_str());
- unlink(idmap_static_1_path.c_str());
-}
-
TEST_F(Idmap2BinaryTests, Lookup) {
SKIP_TEST_IF_CANT_EXEC_IDMAP2;
diff --git a/cmds/idmap2/tests/R.h b/cmds/idmap2/tests/R.h
index aed263a49aa3..854b57fb22aa 100644
--- a/cmds/idmap2/tests/R.h
+++ b/cmds/idmap2/tests/R.h
@@ -14,10 +14,12 @@
* limitations under the License.
*/
-#ifndef IDMAP2_TESTS_R_H
-#define IDMAP2_TESTS_R_H
+#ifndef IDMAP2_TESTS_R_H_
+#define IDMAP2_TESTS_R_H_
-#include <idmap2/ResourceUtils.h>
+#include <string>
+
+#include "idmap2/ResourceUtils.h"
namespace android::idmap2 {
@@ -29,42 +31,43 @@ static std::string hexify(ResourceId id) {
// clang-format off
namespace R::target {
- namespace integer {
+ namespace integer { // NOLINT(runtime/indentation_namespace)
constexpr ResourceId int1 = 0x7f010000;
- namespace literal {
+ namespace literal { // NOLINT(runtime/indentation_namespace)
inline const std::string int1 = hexify(R::target::integer::int1);
}
}
- namespace string {
+ namespace string { // NOLINT(runtime/indentation_namespace)
constexpr ResourceId not_overlayable = 0x7f020003;
constexpr ResourceId other = 0x7f020004;
constexpr ResourceId policy_actor = 0x7f020005;
- constexpr ResourceId policy_odm = 0x7f020006;
- constexpr ResourceId policy_oem = 0x7f020007;
- constexpr ResourceId policy_product = 0x7f020008;
- constexpr ResourceId policy_public = 0x7f020009;
- constexpr ResourceId policy_signature = 0x7f02000a;
- constexpr ResourceId policy_system = 0x7f02000b;
- constexpr ResourceId policy_system_vendor = 0x7f02000c;
- constexpr ResourceId str1 = 0x7f02000d;
- constexpr ResourceId str3 = 0x7f02000f;
- constexpr ResourceId str4 = 0x7f020010;
+ constexpr ResourceId policy_config_signature = 0x7f020006;
+ constexpr ResourceId policy_odm = 0x7f020007;
+ constexpr ResourceId policy_oem = 0x7f020008;
+ constexpr ResourceId policy_product = 0x7f020009;
+ constexpr ResourceId policy_public = 0x7f02000a;
+ constexpr ResourceId policy_signature = 0x7f02000b;
+ constexpr ResourceId policy_system = 0x7f02000c;
+ constexpr ResourceId policy_system_vendor = 0x7f02000d;
+ constexpr ResourceId str1 = 0x7f02000e;
+ constexpr ResourceId str3 = 0x7f020010;
+ constexpr ResourceId str4 = 0x7f020011;
- namespace literal {
+ namespace literal { // NOLINT(runtime/indentation_namespace)
inline const std::string str1 = hexify(R::target::string::str1);
inline const std::string str3 = hexify(R::target::string::str3);
inline const std::string str4 = hexify(R::target::string::str4);
}
- }
-}
+ } // namespace string
+} // namespace R::target
namespace R::overlay {
- namespace integer {
+ namespace integer { // NOLINT(runtime/indentation_namespace)
constexpr ResourceId int1 = 0x7f010000;
}
- namespace string {
+ namespace string { // NOLINT(runtime/indentation_namespace)
constexpr ResourceId str1 = 0x7f020000;
constexpr ResourceId str3 = 0x7f020001;
constexpr ResourceId str4 = 0x7f020002;
@@ -72,10 +75,10 @@ namespace R::overlay {
}
namespace R::overlay_shared {
- namespace integer {
+ namespace integer { // NOLINT(runtime/indentation_namespace)
constexpr ResourceId int1 = 0x00010000;
}
- namespace string {
+ namespace string { // NOLINT(runtime/indentation_namespace)
constexpr ResourceId str1 = 0x00020000;
constexpr ResourceId str3 = 0x00020001;
constexpr ResourceId str4 = 0x00020002;
@@ -92,16 +95,17 @@ namespace R::system_overlay_invalid::string {
constexpr ResourceId not_overlayable = 0x7f010000;
constexpr ResourceId other = 0x7f010001;
constexpr ResourceId policy_actor = 0x7f010002;
- constexpr ResourceId policy_odm = 0x7f010003;
- constexpr ResourceId policy_oem = 0x7f010004;
- constexpr ResourceId policy_product = 0x7f010005;
- constexpr ResourceId policy_public = 0x7f010006;
- constexpr ResourceId policy_signature = 0x7f010007;
- constexpr ResourceId policy_system = 0x7f010008;
- constexpr ResourceId policy_system_vendor = 0x7f010009;
-};
+ constexpr ResourceId policy_config_signature = 0x7f010003;
+ constexpr ResourceId policy_odm = 0x7f010004;
+ constexpr ResourceId policy_oem = 0x7f010005;
+ constexpr ResourceId policy_product = 0x7f010006;
+ constexpr ResourceId policy_public = 0x7f010007;
+ constexpr ResourceId policy_signature = 0x7f010008;
+ constexpr ResourceId policy_system = 0x7f010009;
+ constexpr ResourceId policy_system_vendor = 0x7f01000a;
+} // namespace R::system_overlay_invalid::string
// clang-format on
} // namespace android::idmap2
-#endif // IDMAP2_TESTS_R_H
+#endif // IDMAP2_TESTS_R_H_
diff --git a/cmds/idmap2/tests/ResourceMappingTests.cpp b/cmds/idmap2/tests/ResourceMappingTests.cpp
index de039f440e33..3ec6ac24b238 100644
--- a/cmds/idmap2/tests/ResourceMappingTests.cpp
+++ b/cmds/idmap2/tests/ResourceMappingTests.cpp
@@ -237,7 +237,7 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsPolicySystemPublicInvalidIgnore
ASSERT_TRUE(resources) << resources.GetErrorMessage();
auto& res = *resources;
- ASSERT_EQ(res.GetTargetToOverlayMap().size(), 10U);
+ ASSERT_EQ(res.GetTargetToOverlayMap().size(), 11U);
ASSERT_RESULT(MappingExists(res, R::target::string::not_overlayable, Res_value::TYPE_REFERENCE,
R::system_overlay_invalid::string::not_overlayable,
false /* rewrite */));
@@ -256,6 +256,10 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsPolicySystemPublicInvalidIgnore
ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, Res_value::TYPE_REFERENCE,
R::system_overlay_invalid::string::policy_public,
false /* rewrite */));
+ ASSERT_RESULT(MappingExists(res, R::target::string::policy_config_signature,
+ Res_value::TYPE_REFERENCE,
+ R::system_overlay_invalid::string::policy_config_signature,
+ false /* rewrite */));
ASSERT_RESULT(MappingExists(res, R::target::string::policy_signature, Res_value::TYPE_REFERENCE,
R::system_overlay_invalid::string::policy_signature,
false /* rewrite */));
@@ -298,8 +302,9 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPoliciesPublicFail) {
ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 0U);
}
-// Overlays that are pre-installed or are signed with the same signature as the target can overlay
-// packages that have not defined overlayable resources.
+// Overlays that are pre-installed or are signed with the same signature as the target or are signed
+// with the same signature as the reference package can overlay packages that have not defined
+// overlayable resources.
TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPolicies) {
auto CheckEntries = [&](const PolicyBitmask& fulfilled_policies) -> void {
auto resources = TestGetResourceMapping("/target/target-no-overlayable.apk",
@@ -309,7 +314,7 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPolicies) {
ASSERT_TRUE(resources) << resources.GetErrorMessage();
auto& res = *resources;
- ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 10U);
+ ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 11U);
ASSERT_RESULT(MappingExists(res, R::target::string::not_overlayable, Res_value::TYPE_REFERENCE,
R::system_overlay_invalid::string::not_overlayable,
false /* rewrite */));
@@ -330,6 +335,10 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPolicies) {
ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, Res_value::TYPE_REFERENCE,
R::system_overlay_invalid::string::policy_public,
false /* rewrite */));
+ ASSERT_RESULT(MappingExists(res, R::target::string::policy_config_signature,
+ Res_value::TYPE_REFERENCE,
+ R::system_overlay_invalid::string::policy_config_signature,
+ false /* rewrite */));
ASSERT_RESULT(MappingExists(res, R::target::string::policy_signature, Res_value::TYPE_REFERENCE,
R::system_overlay_invalid::string::policy_signature,
false /* rewrite */));
@@ -342,6 +351,7 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPolicies) {
};
CheckEntries(PolicyFlags::SIGNATURE);
+ CheckEntries(PolicyFlags::CONFIG_SIGNATURE);
CheckEntries(PolicyFlags::PRODUCT_PARTITION);
CheckEntries(PolicyFlags::SYSTEM_PARTITION);
CheckEntries(PolicyFlags::VENDOR_PARTITION);
diff --git a/cmds/idmap2/tests/TestConstants.h b/cmds/idmap2/tests/TestConstants.h
index 6bc924e5ac3c..9641f6b55670 100644
--- a/cmds/idmap2/tests/TestConstants.h
+++ b/cmds/idmap2/tests/TestConstants.h
@@ -14,17 +14,17 @@
* limitations under the License.
*/
-#ifndef IDMAP2_TESTS_TESTCONSTANTS_H
-#define IDMAP2_TESTS_TESTCONSTANTS_H
+#ifndef IDMAP2_TESTS_TESTCONSTANTS_H_
+#define IDMAP2_TESTS_TESTCONSTANTS_H_
namespace android::idmap2::TestConstants {
-constexpr const auto TARGET_CRC = 0x41c60c8c;
-constexpr const auto TARGET_CRC_STRING = "41c60c8c";
+constexpr const auto TARGET_CRC = 0x7c2d4719;
+constexpr const auto TARGET_CRC_STRING = "7c2d4719";
-constexpr const auto OVERLAY_CRC = 0xc054fb26;
-constexpr const auto OVERLAY_CRC_STRING = "c054fb26";
+constexpr const auto OVERLAY_CRC = 0x5afff726;
+constexpr const auto OVERLAY_CRC_STRING = "5afff726";
} // namespace android::idmap2::TestConstants
-#endif // IDMAP2_TESTS_TESTCONSTANTS_H
+#endif // IDMAP2_TESTS_TESTCONSTANTS_H_
diff --git a/cmds/idmap2/tests/data/overlay/overlay-no-name-static.apk b/cmds/idmap2/tests/data/overlay/overlay-no-name-static.apk
index 7c25985e5a61..dab25b1f8131 100644
--- a/cmds/idmap2/tests/data/overlay/overlay-no-name-static.apk
+++ b/cmds/idmap2/tests/data/overlay/overlay-no-name-static.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/overlay/overlay-no-name.apk b/cmds/idmap2/tests/data/overlay/overlay-no-name.apk
index c75f3e1dbddf..c8b95c2601ad 100644
--- a/cmds/idmap2/tests/data/overlay/overlay-no-name.apk
+++ b/cmds/idmap2/tests/data/overlay/overlay-no-name.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/overlay/overlay-shared.apk b/cmds/idmap2/tests/data/overlay/overlay-shared.apk
index 93dcc82f9358..0a8b7372172e 100644
--- a/cmds/idmap2/tests/data/overlay/overlay-shared.apk
+++ b/cmds/idmap2/tests/data/overlay/overlay-shared.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/overlay/overlay-static-1.apk b/cmds/idmap2/tests/data/overlay/overlay-static-1.apk
index 5b8a6e4a90ed..fd41182f8493 100644
--- a/cmds/idmap2/tests/data/overlay/overlay-static-1.apk
+++ b/cmds/idmap2/tests/data/overlay/overlay-static-1.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/overlay/overlay-static-2.apk b/cmds/idmap2/tests/data/overlay/overlay-static-2.apk
index 698a1fd6e702..b24765fc666a 100644
--- a/cmds/idmap2/tests/data/overlay/overlay-static-2.apk
+++ b/cmds/idmap2/tests/data/overlay/overlay-static-2.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/overlay/overlay.apk b/cmds/idmap2/tests/data/overlay/overlay.apk
index 1db303ff05b5..870575efa10c 100644
--- a/cmds/idmap2/tests/data/overlay/overlay.apk
+++ b/cmds/idmap2/tests/data/overlay/overlay.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/signature-overlay/signature-overlay.apk b/cmds/idmap2/tests/data/signature-overlay/signature-overlay.apk
index 51e19de082ed..e0fd20499671 100644
--- a/cmds/idmap2/tests/data/signature-overlay/signature-overlay.apk
+++ b/cmds/idmap2/tests/data/signature-overlay/signature-overlay.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/system-overlay-invalid/res/values/values.xml b/cmds/idmap2/tests/data/system-overlay-invalid/res/values/values.xml
index 7119d8283061..ebaf49c34762 100644
--- a/cmds/idmap2/tests/data/system-overlay-invalid/res/values/values.xml
+++ b/cmds/idmap2/tests/data/system-overlay-invalid/res/values/values.xml
@@ -26,6 +26,7 @@
<string name="policy_odm">policy_odm</string>
<string name="policy_oem">policy_oem</string>
<string name="policy_actor">policy_actor</string>
+ <string name="policy_config_signature">policy_config_signature</string>
<!-- Requests to overlay a resource that is not declared as overlayable. -->
<string name="not_overlayable">not_overlayable</string>
diff --git a/cmds/idmap2/tests/data/system-overlay-invalid/system-overlay-invalid.apk b/cmds/idmap2/tests/data/system-overlay-invalid/system-overlay-invalid.apk
index bd990983693c..a63daf86caf5 100644
--- a/cmds/idmap2/tests/data/system-overlay-invalid/system-overlay-invalid.apk
+++ b/cmds/idmap2/tests/data/system-overlay-invalid/system-overlay-invalid.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/system-overlay/system-overlay.apk b/cmds/idmap2/tests/data/system-overlay/system-overlay.apk
index a0fba4378b57..90d2803a1eca 100644
--- a/cmds/idmap2/tests/data/system-overlay/system-overlay.apk
+++ b/cmds/idmap2/tests/data/system-overlay/system-overlay.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/target/res/values/overlayable.xml b/cmds/idmap2/tests/data/target/res/values/overlayable.xml
index ad4cd4882632..57e6c439c23c 100644
--- a/cmds/idmap2/tests/data/target/res/values/overlayable.xml
+++ b/cmds/idmap2/tests/data/target/res/values/overlayable.xml
@@ -45,6 +45,10 @@
<item type="string" name="policy_actor" />
</policy>
+ <policy type="config_signature">
+ <item type="string" name="policy_config_signature"/>
+ </policy>
+
<!-- Resources publicly overlayable -->
<policy type="public">
<item type="string" name="policy_public" />
diff --git a/cmds/idmap2/tests/data/target/res/values/values.xml b/cmds/idmap2/tests/data/target/res/values/values.xml
index 5230e25e626b..00909a9e481c 100644
--- a/cmds/idmap2/tests/data/target/res/values/values.xml
+++ b/cmds/idmap2/tests/data/target/res/values/values.xml
@@ -37,6 +37,7 @@
<string name="policy_system">policy_system</string>
<string name="policy_system_vendor">policy_system_vendor</string>
<string name="policy_actor">policy_actor</string>
+ <string name="policy_config_signature">policy_config_signature</string>
<string name="other">other</string>
</resources>
diff --git a/cmds/idmap2/tests/data/target/target-no-overlayable.apk b/cmds/idmap2/tests/data/target/target-no-overlayable.apk
index 58504a74a83a..cc3491de894d 100644
--- a/cmds/idmap2/tests/data/target/target-no-overlayable.apk
+++ b/cmds/idmap2/tests/data/target/target-no-overlayable.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/target/target.apk b/cmds/idmap2/tests/data/target/target.apk
index c80e5eb65ff2..4a58c5e28f49 100644
--- a/cmds/idmap2/tests/data/target/target.apk
+++ b/cmds/idmap2/tests/data/target/target.apk
Binary files differ
diff --git a/cmds/idmap2/valgrind.sh b/cmds/idmap2/valgrind.sh
index b4ebab0c7ffe..84daeecdb21e 100755
--- a/cmds/idmap2/valgrind.sh
+++ b/cmds/idmap2/valgrind.sh
@@ -53,7 +53,5 @@ valgrind="valgrind --error-exitcode=1 -q --track-origins=yes --leak-check=full"
_eval "idmap2 create" "$valgrind idmap2 create --policy public --target-apk-path $target_path --overlay-apk-path $overlay_path --idmap-path $idmap_path"
_eval "idmap2 dump" "$valgrind idmap2 dump --idmap-path $idmap_path"
_eval "idmap2 lookup" "$valgrind idmap2 lookup --idmap-path $idmap_path --config '' --resid test.target:string/str1"
-_eval "idmap2 scan" "$valgrind idmap2 scan --input-directory ${prefix}/tests/data/overlay --recursive --target-package-name test.target --target-apk-path $target_path --output-directory /tmp --override-policy public"
-_eval "idmap2 verify" "$valgrind idmap2 verify --idmap-path $idmap_path"
_eval "idmap2_tests" "$valgrind $ANDROID_HOST_OUT/nativetest64/idmap2_tests/idmap2_tests"
exit $errors
diff --git a/cmds/incidentd/src/IncidentService.cpp b/cmds/incidentd/src/IncidentService.cpp
index dc1612575f38..13bf197aa9dc 100644
--- a/cmds/incidentd/src/IncidentService.cpp
+++ b/cmds/incidentd/src/IncidentService.cpp
@@ -554,6 +554,10 @@ status_t IncidentService::command(FILE* in, FILE* out, FILE* err, Vector<String8
return NO_ERROR;
}
if (!args[0].compare(String8("section"))) {
+ if (argCount == 1) {
+ fprintf(out, "Not enough arguments for section\n");
+ return NO_ERROR;
+ }
int id = atoi(args[1]);
int idx = 0;
while (SECTION_LIST[idx] != NULL) {
diff --git a/cmds/incidentd/tests/section_list.cpp b/cmds/incidentd/tests/section_list.cpp
index 3a45af028518..60f7fb788837 100644
--- a/cmds/incidentd/tests/section_list.cpp
+++ b/cmds/incidentd/tests/section_list.cpp
@@ -1,4 +1,4 @@
-// This file is a dummy section_list.cpp used for test only.
+// This file is a stub section_list.cpp used for test only.
#include "section_list.h"
#include "frameworks/base/cmds/incidentd/tests/test_proto.pb.h"
diff --git a/cmds/input/Android.bp b/cmds/input/Android.bp
index a0ebde63eb6e..1ee9dd355290 100644
--- a/cmds/input/Android.bp
+++ b/cmds/input/Android.bp
@@ -1,8 +1,7 @@
// Copyright 2008 The Android Open Source Project
//
-java_binary {
+sh_binary {
name: "input",
- wrapper: "input",
- srcs: ["**/*.java"],
+ src: "input",
}
diff --git a/cmds/input/input b/cmds/input/input
index 2625eba17153..d7d041431b49 100755
--- a/cmds/input/input
+++ b/cmds/input/input
@@ -1,3 +1,2 @@
#!/system/bin/sh
-export CLASSPATH=/system/framework/input.jar
-exec app_process /system/bin com.android.commands.input.Input "$@"
+cmd input "$@"
diff --git a/cmds/input/src/com/android/commands/input/Input.java b/cmds/input/src/com/android/commands/input/Input.java
deleted file mode 100644
index 08216d9b3f1d..000000000000
--- a/cmds/input/src/com/android/commands/input/Input.java
+++ /dev/null
@@ -1,435 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.commands.input;
-
-import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.Display.INVALID_DISPLAY;
-
-import android.hardware.input.InputManager;
-import android.os.SystemClock;
-import android.view.InputDevice;
-import android.view.KeyCharacterMap;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.ViewConfiguration;
-
-import com.android.internal.os.BaseCommand;
-
-import java.io.PrintStream;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Command that sends key events to the device, either by their keycode, or by
- * desired character output.
- */
-
-public class Input extends BaseCommand {
- private static final String TAG = "Input";
- private static final String INVALID_ARGUMENTS = "Error: Invalid arguments for command: ";
- private static final String INVALID_DISPLAY_ARGUMENTS =
- "Error: Invalid arguments for display ID.";
-
- private static final float DEFAULT_PRESSURE = 1.0f;
- private static final float NO_PRESSURE = 0.0f;
-
- private static final Map<String, Integer> SOURCES = new HashMap<String, Integer>() {{
- put("keyboard", InputDevice.SOURCE_KEYBOARD);
- put("dpad", InputDevice.SOURCE_DPAD);
- put("gamepad", InputDevice.SOURCE_GAMEPAD);
- put("touchscreen", InputDevice.SOURCE_TOUCHSCREEN);
- put("mouse", InputDevice.SOURCE_MOUSE);
- put("stylus", InputDevice.SOURCE_STYLUS);
- put("trackball", InputDevice.SOURCE_TRACKBALL);
- put("touchpad", InputDevice.SOURCE_TOUCHPAD);
- put("touchnavigation", InputDevice.SOURCE_TOUCH_NAVIGATION);
- put("joystick", InputDevice.SOURCE_JOYSTICK);
- }};
-
- private static final Map<String, InputCmd> COMMANDS = new HashMap<String, InputCmd>();
-
- /**
- * Command-line entry point.
- *
- * @param args The command-line arguments
- */
- public static void main(String[] args) {
- (new Input()).run(args);
- }
-
- Input() {
- COMMANDS.put("text", new InputText());
- COMMANDS.put("keyevent", new InputKeyEvent());
- COMMANDS.put("tap", new InputTap());
- COMMANDS.put("swipe", new InputSwipe());
- COMMANDS.put("draganddrop", new InputDragAndDrop());
- COMMANDS.put("press", new InputPress());
- COMMANDS.put("roll", new InputRoll());
- COMMANDS.put("motionevent", new InputMotionEvent());
- }
-
- @Override
- public void onRun() throws Exception {
- String arg = nextArgRequired();
- int inputSource = InputDevice.SOURCE_UNKNOWN;
-
- // Get source (optional).
- if (SOURCES.containsKey(arg)) {
- inputSource = SOURCES.get(arg);
- arg = nextArgRequired();
- }
-
- // Get displayId (optional).
- int displayId = INVALID_DISPLAY;
- if ("-d".equals(arg)) {
- displayId = getDisplayId();
- arg = nextArgRequired();
- }
-
- // Get command and run.
- InputCmd cmd = COMMANDS.get(arg);
- if (cmd != null) {
- try {
- cmd.run(inputSource, displayId);
- return;
- } catch (NumberFormatException ex) {
- throw new IllegalArgumentException(INVALID_ARGUMENTS + arg);
- }
- }
-
- throw new IllegalArgumentException("Error: Unknown command: " + arg);
- }
-
- private int getDisplayId() {
- String displayArg = nextArgRequired();
- if ("INVALID_DISPLAY".equalsIgnoreCase(displayArg)) {
- return INVALID_DISPLAY;
- } else if ("DEFAULT_DISPLAY".equalsIgnoreCase(displayArg)) {
- return DEFAULT_DISPLAY;
- } else {
- try {
- final int displayId = Integer.parseInt(displayArg);
- if (displayId == INVALID_DISPLAY) {
- return INVALID_DISPLAY;
- }
- return Math.max(displayId, 0);
- } catch (NumberFormatException e) {
- throw new IllegalArgumentException(INVALID_DISPLAY_ARGUMENTS);
- }
- }
- }
-
- class InputText implements InputCmd {
- @Override
- public void run(int inputSource, int displayId) {
- inputSource = getSource(inputSource, InputDevice.SOURCE_KEYBOARD);
- sendText(inputSource, nextArgRequired(), displayId);
- }
-
- /**
- * Convert the characters of string text into key event's and send to
- * device.
- *
- * @param text is a string of characters you want to input to the device.
- */
- private void sendText(int source, final String text, int displayId) {
- final StringBuffer buff = new StringBuffer(text);
- boolean escapeFlag = false;
- for (int i = 0; i < buff.length(); i++) {
- if (escapeFlag) {
- escapeFlag = false;
- if (buff.charAt(i) == 's') {
- buff.setCharAt(i, ' ');
- buff.deleteCharAt(--i);
- }
- }
- if (buff.charAt(i) == '%') {
- escapeFlag = true;
- }
- }
-
- final char[] chars = buff.toString().toCharArray();
- final KeyCharacterMap kcm = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
- final KeyEvent[] events = kcm.getEvents(chars);
- for (int i = 0; i < events.length; i++) {
- KeyEvent e = events[i];
- if (source != e.getSource()) {
- e.setSource(source);
- }
- e.setDisplayId(displayId);
- injectKeyEvent(e);
- }
- }
- }
-
- class InputKeyEvent implements InputCmd {
- @Override
- public void run(int inputSource, int displayId) {
- String arg = nextArgRequired();
- final boolean longpress = "--longpress".equals(arg);
- if (longpress) {
- arg = nextArgRequired();
- }
-
- do {
- final int keycode = KeyEvent.keyCodeFromString(arg);
- sendKeyEvent(inputSource, keycode, longpress, displayId);
- } while ((arg = nextArg()) != null);
- }
-
- private void sendKeyEvent(int inputSource, int keyCode, boolean longpress, int displayId) {
- final long now = SystemClock.uptimeMillis();
- int repeatCount = 0;
-
- KeyEvent event = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, repeatCount,
- 0 /*metaState*/, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /*scancode*/, 0 /*flags*/,
- inputSource);
- event.setDisplayId(displayId);
-
- injectKeyEvent(event);
- if (longpress) {
- repeatCount++;
- injectKeyEvent(KeyEvent.changeTimeRepeat(event, now, repeatCount,
- KeyEvent.FLAG_LONG_PRESS));
- }
- injectKeyEvent(KeyEvent.changeAction(event, KeyEvent.ACTION_UP));
- }
- }
-
- class InputTap implements InputCmd {
- @Override
- public void run(int inputSource, int displayId) {
- inputSource = getSource(inputSource, InputDevice.SOURCE_TOUCHSCREEN);
- sendTap(inputSource, Float.parseFloat(nextArgRequired()),
- Float.parseFloat(nextArgRequired()), displayId);
- }
-
- void sendTap(int inputSource, float x, float y, int displayId) {
- final long now = SystemClock.uptimeMillis();
- injectMotionEvent(inputSource, MotionEvent.ACTION_DOWN, now, now, x, y, 1.0f,
- displayId);
- injectMotionEvent(inputSource, MotionEvent.ACTION_UP, now, now, x, y, 0.0f, displayId);
- }
- }
-
- class InputPress extends InputTap {
- @Override
- public void run(int inputSource, int displayId) {
- inputSource = getSource(inputSource, InputDevice.SOURCE_TRACKBALL);
- sendTap(inputSource, 0.0f, 0.0f, displayId);
- }
- }
-
- class InputSwipe implements InputCmd {
- @Override
- public void run(int inputSource, int displayId) {
- inputSource = getSource(inputSource, InputDevice.SOURCE_TOUCHSCREEN);
- sendSwipe(inputSource, displayId, false);
- }
-
- void sendSwipe(int inputSource, int displayId, boolean isDragDrop) {
- // Parse two points and duration.
- final float x1 = Float.parseFloat(nextArgRequired());
- final float y1 = Float.parseFloat(nextArgRequired());
- final float x2 = Float.parseFloat(nextArgRequired());
- final float y2 = Float.parseFloat(nextArgRequired());
- String durationArg = nextArg();
- int duration = durationArg != null ? Integer.parseInt(durationArg) : -1;
- if (duration < 0) {
- duration = 300;
- }
-
- final long down = SystemClock.uptimeMillis();
- injectMotionEvent(inputSource, MotionEvent.ACTION_DOWN, down, down, x1, y1, 1.0f,
- displayId);
- if (isDragDrop) {
- // long press until drag start.
- try {
- Thread.sleep(ViewConfiguration.getLongPressTimeout());
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
- long now = SystemClock.uptimeMillis();
- final long endTime = down + duration;
- while (now < endTime) {
- final long elapsedTime = now - down;
- final float alpha = (float) elapsedTime / duration;
- injectMotionEvent(inputSource, MotionEvent.ACTION_MOVE, down, now,
- lerp(x1, x2, alpha), lerp(y1, y2, alpha), 1.0f, displayId);
- now = SystemClock.uptimeMillis();
- }
- injectMotionEvent(inputSource, MotionEvent.ACTION_UP, down, now, x2, y2, 0.0f,
- displayId);
- }
- }
-
- class InputDragAndDrop extends InputSwipe {
- @Override
- public void run(int inputSource, int displayId) {
- inputSource = getSource(inputSource, InputDevice.SOURCE_TOUCHSCREEN);
- sendSwipe(inputSource, displayId, true);
- }
- }
-
- class InputRoll implements InputCmd {
- @Override
- public void run(int inputSource, int displayId) {
- inputSource = getSource(inputSource, InputDevice.SOURCE_TRACKBALL);
- sendMove(inputSource, Float.parseFloat(nextArgRequired()),
- Float.parseFloat(nextArgRequired()), displayId);
- }
-
- /**
- * Sends a simple zero-pressure move event.
- *
- * @param inputSource the InputDevice.SOURCE_* sending the input event
- * @param dx change in x coordinate due to move
- * @param dy change in y coordinate due to move
- */
- private void sendMove(int inputSource, float dx, float dy, int displayId) {
- final long now = SystemClock.uptimeMillis();
- injectMotionEvent(inputSource, MotionEvent.ACTION_MOVE, now, now, dx, dy, 0.0f,
- displayId);
- }
- }
-
- class InputMotionEvent implements InputCmd {
- @Override
- public void run(int inputSource, int displayId) {
- inputSource = getSource(inputSource, InputDevice.SOURCE_TOUCHSCREEN);
- sendMotionEvent(inputSource, nextArgRequired(), Float.parseFloat(nextArgRequired()),
- Float.parseFloat(nextArgRequired()), displayId);
- }
-
- private void sendMotionEvent(int inputSource, String motionEventType, float x, float y,
- int displayId) {
- final int action;
- final float pressure;
-
- switch (motionEventType.toUpperCase()) {
- case "DOWN":
- action = MotionEvent.ACTION_DOWN;
- pressure = DEFAULT_PRESSURE;
- break;
- case "UP":
- action = MotionEvent.ACTION_UP;
- pressure = NO_PRESSURE;
- break;
- case "MOVE":
- action = MotionEvent.ACTION_MOVE;
- pressure = DEFAULT_PRESSURE;
- break;
- default:
- throw new IllegalArgumentException("Unknown motionevent " + motionEventType);
- }
-
- final long now = SystemClock.uptimeMillis();
- injectMotionEvent(inputSource, action, now, now, x, y, pressure, displayId);
- }
- }
-
- /**
- * Abstract class for command
- * use nextArgRequired or nextArg to check next argument if necessary.
- */
- private interface InputCmd {
- void run(int inputSource, int displayId);
- }
-
- private static void injectKeyEvent(KeyEvent event) {
- InputManager.getInstance().injectInputEvent(event,
- InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
- }
-
- private static int getInputDeviceId(int inputSource) {
- final int DEFAULT_DEVICE_ID = 0;
- int[] devIds = InputDevice.getDeviceIds();
- for (int devId : devIds) {
- InputDevice inputDev = InputDevice.getDevice(devId);
- if (inputDev.supportsSource(inputSource)) {
- return devId;
- }
- }
- return DEFAULT_DEVICE_ID;
- }
-
- /**
- * Builds a MotionEvent and injects it into the event stream.
- *
- * @param inputSource the InputDevice.SOURCE_* sending the input event
- * @param action the MotionEvent.ACTION_* for the event
- * @param downTime the value of the ACTION_DOWN event happened
- * @param when the value of SystemClock.uptimeMillis() at which the event happened
- * @param x x coordinate of event
- * @param y y coordinate of event
- * @param pressure pressure of event
- */
- private static void injectMotionEvent(int inputSource, int action, long downTime, long when,
- float x, float y, float pressure, int displayId) {
- final float DEFAULT_SIZE = 1.0f;
- final int DEFAULT_META_STATE = 0;
- final float DEFAULT_PRECISION_X = 1.0f;
- final float DEFAULT_PRECISION_Y = 1.0f;
- final int DEFAULT_EDGE_FLAGS = 0;
- MotionEvent event = MotionEvent.obtain(downTime, when, action, x, y, pressure, DEFAULT_SIZE,
- DEFAULT_META_STATE, DEFAULT_PRECISION_X, DEFAULT_PRECISION_Y,
- getInputDeviceId(inputSource), DEFAULT_EDGE_FLAGS);
- event.setSource(inputSource);
- if (displayId == INVALID_DISPLAY && (inputSource & InputDevice.SOURCE_CLASS_POINTER) != 0) {
- displayId = DEFAULT_DISPLAY;
- }
- event.setDisplayId(displayId);
- InputManager.getInstance().injectInputEvent(event,
- InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
- }
-
- private static final float lerp(float a, float b, float alpha) {
- return (b - a) * alpha + a;
- }
-
- private static final int getSource(int inputSource, int defaultSource) {
- return inputSource == InputDevice.SOURCE_UNKNOWN ? defaultSource : inputSource;
- }
-
- @Override
- public void onShowUsage(PrintStream out) {
- out.println("Usage: input [<source>] [-d DISPLAY_ID] <command> [<arg>...]");
- out.println();
- out.println("The sources are: ");
- for (String src : SOURCES.keySet()) {
- out.println(" " + src);
- }
- out.println();
- out.printf("-d: specify the display ID.\n"
- + " (Default: %d for key event, %d for motion event if not specified.)",
- INVALID_DISPLAY, DEFAULT_DISPLAY);
- out.println();
- out.println("The commands and default sources are:");
- out.println(" text <string> (Default: touchscreen)");
- out.println(" keyevent [--longpress] <key code number or name> ..."
- + " (Default: keyboard)");
- out.println(" tap <x> <y> (Default: touchscreen)");
- out.println(" swipe <x1> <y1> <x2> <y2> [duration(ms)]"
- + " (Default: touchscreen)");
- out.println(" draganddrop <x1> <y1> <x2> <y2> [duration(ms)]"
- + " (Default: touchscreen)");
- out.println(" press (Default: trackball)");
- out.println(" roll <dx> <dy> (Default: trackball)");
- out.println(" motionevent <DOWN|UP|MOVE> <x> <y> (Default: touchscreen)");
- }
-}
diff --git a/cmds/locksettings/TEST_MAPPING b/cmds/locksettings/TEST_MAPPING
index 56f5cc034f05..c1cba5f7f22d 100644
--- a/cmds/locksettings/TEST_MAPPING
+++ b/cmds/locksettings/TEST_MAPPING
@@ -1,5 +1,5 @@
{
- "presubmit-devicepolicy": [
+ "presubmit": [
{
"name": "CtsDevicePolicyManagerTestCases",
"options": [
diff --git a/cmds/screencap/Android.bp b/cmds/screencap/Android.bp
index 248c67589696..fc628a696afa 100644
--- a/cmds/screencap/Android.bp
+++ b/cmds/screencap/Android.bp
@@ -7,7 +7,7 @@ cc_binary {
"libcutils",
"libutils",
"libbinder",
- "libhwui",
+ "libjnigraphics",
"libui",
"libgui",
],
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index bb32dd2fa7ad..5c08704a6623 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -26,10 +26,13 @@
#include <sys/mman.h>
#include <sys/wait.h>
+#include <android/bitmap.h>
+
#include <binder/ProcessState.h>
-#include <gui/SurfaceComposerClient.h>
#include <gui/ISurfaceComposer.h>
+#include <gui/SurfaceComposerClient.h>
+#include <gui/SyncScreenCaptureListener.h>
#include <ui/DisplayInfo.h>
#include <ui/GraphicTypes.h>
@@ -37,14 +40,6 @@
#include <system/graphics.h>
-// TODO: Fix Skia.
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-parameter"
-#include <SkImageEncoder.h>
-#include <SkData.h>
-#include <SkColorSpace.h>
-#pragma GCC diagnostic pop
-
using namespace android;
#define COLORSPACE_UNKNOWN 0
@@ -57,33 +52,20 @@ static void usage(const char* pname, PhysicalDisplayId displayId)
"usage: %s [-hp] [-d display-id] [FILENAME]\n"
" -h: this message\n"
" -p: save the file as a png.\n"
- " -d: specify the physical display ID to capture (default: %"
- ANDROID_PHYSICAL_DISPLAY_ID_FORMAT ")\n"
+ " -d: specify the physical display ID to capture (default: %s)\n"
" see \"dumpsys SurfaceFlinger --display-id\" for valid display IDs.\n"
"If FILENAME ends with .png it will be saved as a png.\n"
"If FILENAME is not given, the results will be printed to stdout.\n",
- pname, displayId);
+ pname, to_string(displayId).c_str());
}
-static SkColorType flinger2skia(PixelFormat f)
+static int32_t flinger2bitmapFormat(PixelFormat f)
{
switch (f) {
case PIXEL_FORMAT_RGB_565:
- return kRGB_565_SkColorType;
- default:
- return kN32_SkColorType;
- }
-}
-
-static sk_sp<SkColorSpace> dataSpaceToColorSpace(ui::Dataspace d)
-{
- switch (d) {
- case ui::Dataspace::V0_SRGB:
- return SkColorSpace::MakeSRGB();
- case ui::Dataspace::DISPLAY_P3:
- return SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kDCIP3);
+ return ANDROID_BITMAP_FORMAT_RGB_565;
default:
- return nullptr;
+ return ANDROID_BITMAP_FORMAT_RGBA_8888;
}
}
@@ -155,7 +137,7 @@ int main(int argc, char** argv)
png = true;
break;
case 'd':
- displayId = atoll(optarg);
+ displayId = PhysicalDisplayId(atoll(optarg));
break;
case '?':
case 'h':
@@ -192,8 +174,6 @@ int main(int argc, char** argv)
ssize_t mapsize = -1;
void* base = NULL;
- uint32_t w, s, h, f;
- size_t size = 0;
// setThreadPoolMaxThreadCount(0) actually tells the kernel it's
// not allowed to spawn any additional threads, but we still spawn
@@ -202,16 +182,22 @@ int main(int argc, char** argv)
ProcessState::self()->setThreadPoolMaxThreadCount(0);
ProcessState::self()->startThreadPool();
- ui::Dataspace outDataspace;
- sp<GraphicBuffer> outBuffer;
-
- status_t result = ScreenshotClient::capture(*displayId, &outDataspace, &outBuffer);
+ sp<SyncScreenCaptureListener> captureListener = new SyncScreenCaptureListener();
+ status_t result = ScreenshotClient::captureDisplay(displayId->value, captureListener);
if (result != NO_ERROR) {
close(fd);
return 1;
}
- result = outBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &base);
+ ScreenCaptureResults captureResults = captureListener->waitForResults();
+ if (captureResults.result != NO_ERROR) {
+ close(fd);
+ return 1;
+ }
+ ui::Dataspace dataspace = captureResults.capturedDataspace;
+ sp<GraphicBuffer> buffer = captureResults.buffer;
+
+ result = buffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &base);
if (base == nullptr || result != NO_ERROR) {
String8 reason;
@@ -225,33 +211,36 @@ int main(int argc, char** argv)
return 1;
}
- w = outBuffer->getWidth();
- h = outBuffer->getHeight();
- s = outBuffer->getStride();
- f = outBuffer->getPixelFormat();
- size = s * h * bytesPerPixel(f);
-
if (png) {
- const SkImageInfo info =
- SkImageInfo::Make(w, h, flinger2skia(f), kPremul_SkAlphaType,
- dataSpaceToColorSpace(outDataspace));
- SkPixmap pixmap(info, base, s * bytesPerPixel(f));
- struct FDWStream final : public SkWStream {
- size_t fBytesWritten = 0;
- int fFd;
- FDWStream(int f) : fFd(f) {}
- size_t bytesWritten() const override { return fBytesWritten; }
- bool write(const void* buffer, size_t size) override {
- fBytesWritten += size;
- return size == 0 || ::write(fFd, buffer, size) > 0;
- }
- } fdStream(fd);
- (void)SkEncodeImage(&fdStream, pixmap, SkEncodedImageFormat::kPNG, 100);
+ AndroidBitmapInfo info;
+ info.format = flinger2bitmapFormat(buffer->getPixelFormat());
+ info.flags = ANDROID_BITMAP_FLAGS_ALPHA_PREMUL;
+ info.width = buffer->getWidth();
+ info.height = buffer->getHeight();
+ info.stride = buffer->getStride() * bytesPerPixel(buffer->getPixelFormat());
+
+ int result = AndroidBitmap_compress(&info, static_cast<int32_t>(dataspace), base,
+ ANDROID_BITMAP_COMPRESS_FORMAT_PNG, 100, &fd,
+ [](void* fdPtr, const void* data, size_t size) -> bool {
+ int bytesWritten = write(*static_cast<int*>(fdPtr),
+ data, size);
+ return bytesWritten == size;
+ });
+
+ if (result != ANDROID_BITMAP_RESULT_SUCCESS) {
+ fprintf(stderr, "Failed to compress PNG (error code: %d)\n", result);
+ }
+
if (fn != NULL) {
notifyMediaScanner(fn);
}
} else {
- uint32_t c = dataSpaceToInt(outDataspace);
+ uint32_t w = buffer->getWidth();
+ uint32_t h = buffer->getHeight();
+ uint32_t s = buffer->getStride();
+ uint32_t f = buffer->getPixelFormat();
+ uint32_t c = dataSpaceToInt(dataspace);
+
write(fd, &w, 4);
write(fd, &h, 4);
write(fd, &f, 4);
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index 0617eb6c0e66..88db1d84df8e 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -73,10 +73,10 @@ cc_defaults {
"src/HashableDimensionKey.cpp",
"src/logd/LogEvent.cpp",
"src/logd/LogEventQueue.cpp",
- "src/matchers/CombinationLogMatchingTracker.cpp",
+ "src/matchers/CombinationAtomMatchingTracker.cpp",
"src/matchers/EventMatcherWizard.cpp",
"src/matchers/matcher_util.cpp",
- "src/matchers/SimpleLogMatchingTracker.cpp",
+ "src/matchers/SimpleAtomMatchingTracker.cpp",
"src/metadata_util.cpp",
"src/metrics/CountMetricProducer.cpp",
"src/metrics/duration_helper/MaxDurationTracker.cpp",
@@ -85,8 +85,9 @@ cc_defaults {
"src/metrics/EventMetricProducer.cpp",
"src/metrics/GaugeMetricProducer.cpp",
"src/metrics/MetricProducer.cpp",
- "src/metrics/metrics_manager_util.cpp",
"src/metrics/MetricsManager.cpp",
+ "src/metrics/parsing_utils/config_update_utils.cpp",
+ "src/metrics/parsing_utils/metrics_manager_util.cpp",
"src/metrics/ValueMetricProducer.cpp",
"src/packages/UidMap.cpp",
"src/shell/shell_config.proto",
@@ -171,7 +172,8 @@ cc_library_static {
export_generated_headers: ["statslog_statsdtest.h"],
shared_libs: [
"libstatssocket",
- ]
+ "libstatspull",
+ ],
}
cc_library_static {
@@ -185,7 +187,11 @@ cc_library_static {
],
shared_libs: [
"libstatssocket",
- ]
+ "libstatspull",
+ ],
+ export_shared_lib_headers: [
+ "libstatspull",
+ ],
}
// =========
@@ -216,10 +222,6 @@ cc_binary {
// address: true,
//},
},
- debuggable: {
- // Add a flag to enable stats log printing from statsd on debug builds.
- cflags: ["-DVERY_VERBOSE_PRINTING"],
- },
},
proto: {
@@ -321,6 +323,8 @@ cc_test {
"tests/metrics/metrics_test_helper.cpp",
"tests/metrics/OringDurationTracker_test.cpp",
"tests/metrics/ValueMetricProducer_test.cpp",
+ "tests/metrics/parsing_utils/config_update_utils_test.cpp",
+ "tests/metrics/parsing_utils/metrics_manager_util_test.cpp",
"tests/MetricsManager_test.cpp",
"tests/shell/ShellSubscriber_test.cpp",
"tests/state/StateTracker_test.cpp",
diff --git a/cmds/statsd/TEST_MAPPING b/cmds/statsd/TEST_MAPPING
index 8dee073aca22..a7a4cf14182e 100644
--- a/cmds/statsd/TEST_MAPPING
+++ b/cmds/statsd/TEST_MAPPING
@@ -3,5 +3,15 @@
{
"name" : "statsd_test"
}
+ ],
+
+ "postsubmit" : [
+ {
+ "name" : "CtsStatsdHostTestCases"
+ },
+ {
+ "name" : "GtsStatsdHostTestCases"
+ }
]
-} \ No newline at end of file
+
+}
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index e7b32c56551a..7bee4e2d1a36 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -120,10 +120,9 @@ static void flushProtoToBuffer(ProtoOutputStream& proto, vector<uint8_t>* outDat
}
}
-void StatsLogProcessor::onAnomalyAlarmFired(
+void StatsLogProcessor::processFiredAnomalyAlarmsLocked(
const int64_t& timestampNs,
unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet) {
- std::lock_guard<std::mutex> lock(mMetricsMutex);
for (const auto& itr : mMetricsManagers) {
itr.second->onAnomalyAlarmFired(timestampNs, alarmSet);
}
@@ -409,11 +408,9 @@ void StatsLogProcessor::OnLogEvent(LogEvent* event, int64_t elapsedRealtimeNs) {
onWatchdogRollbackOccurredLocked(event);
}
-#ifdef VERY_VERBOSE_PRINTING
if (mPrintAllLogs) {
ALOGI("%s", event->ToString().c_str());
}
-#endif
resetIfConfigTtlExpiredLocked(eventElapsedTimeNs);
// Hard-coded logic to update the isolated uid's in the uid-map.
@@ -431,6 +428,20 @@ void StatsLogProcessor::OnLogEvent(LogEvent* event, int64_t elapsedRealtimeNs) {
return;
}
+ bool fireAlarm = false;
+ {
+ std::lock_guard<std::mutex> anomalyLock(mAnomalyAlarmMutex);
+ if (mNextAnomalyAlarmTime != 0 &&
+ MillisToNano(mNextAnomalyAlarmTime) <= elapsedRealtimeNs) {
+ mNextAnomalyAlarmTime = 0;
+ VLOG("informing anomaly alarm at time %lld", (long long)elapsedRealtimeNs);
+ fireAlarm = true;
+ }
+ }
+ if (fireAlarm) {
+ informAnomalyAlarmFiredLocked(NanoToMillis(elapsedRealtimeNs));
+ }
+
int64_t curTimeSec = getElapsedRealtimeSec();
if (curTimeSec - mLastPullerCacheClearTimeSec > StatsdStats::kPullerCacheClearIntervalSec) {
mPullerManager->ClearPullerCacheIfNecessary(curTimeSec * NS_PER_SEC);
@@ -515,19 +526,35 @@ void StatsLogProcessor::OnConfigUpdated(const int64_t timestampNs, const ConfigK
OnConfigUpdatedLocked(timestampNs, key, config);
}
-void StatsLogProcessor::OnConfigUpdatedLocked(
- const int64_t timestampNs, const ConfigKey& key, const StatsdConfig& config) {
+void StatsLogProcessor::OnConfigUpdatedLocked(const int64_t timestampNs, const ConfigKey& key,
+ const StatsdConfig& config, bool modularUpdate) {
VLOG("Updated configuration for key %s", key.ToString().c_str());
- sp<MetricsManager> newMetricsManager =
- new MetricsManager(key, config, mTimeBaseNs, timestampNs, mUidMap, mPullerManager,
- mAnomalyAlarmMonitor, mPeriodicAlarmMonitor);
- if (newMetricsManager->isConfigValid()) {
- newMetricsManager->init();
- mUidMap->OnConfigUpdated(key);
- newMetricsManager->refreshTtl(timestampNs);
- mMetricsManagers[key] = newMetricsManager;
- VLOG("StatsdConfig valid");
+ // Create new config if this is not a modular update or if this is a new config.
+ const auto& it = mMetricsManagers.find(key);
+ bool configValid = false;
+ if (!modularUpdate || it == mMetricsManagers.end()) {
+ sp<MetricsManager> newMetricsManager =
+ new MetricsManager(key, config, mTimeBaseNs, timestampNs, mUidMap, mPullerManager,
+ mAnomalyAlarmMonitor, mPeriodicAlarmMonitor);
+ configValid = newMetricsManager->isConfigValid();
+ if (configValid) {
+ newMetricsManager->init();
+ mUidMap->OnConfigUpdated(key);
+ newMetricsManager->refreshTtl(timestampNs);
+ mMetricsManagers[key] = newMetricsManager;
+ VLOG("StatsdConfig valid");
+ }
} else {
+ // Preserve the existing MetricsManager, update necessary components and metadata in place.
+ configValid = it->second->updateConfig(config, mTimeBaseNs, timestampNs,
+ mAnomalyAlarmMonitor, mPeriodicAlarmMonitor);
+ if (configValid) {
+ // TODO(b/162323476): refresh TTL, ensure init() is handled properly.
+ mUidMap->OnConfigUpdated(key);
+
+ }
+ }
+ if (!configValid) {
// If there is any error in the config, don't use it.
// Remove any existing config with the same key.
ALOGE("StatsdConfig NOT valid");
@@ -1092,6 +1119,28 @@ void StatsLogProcessor::noteOnDiskData(const ConfigKey& key) {
mOnDiskDataConfigs.insert(key);
}
+void StatsLogProcessor::setAnomalyAlarm(const int64_t elapsedTimeMillis) {
+ std::lock_guard<std::mutex> lock(mAnomalyAlarmMutex);
+ mNextAnomalyAlarmTime = elapsedTimeMillis;
+}
+
+void StatsLogProcessor::cancelAnomalyAlarm() {
+ std::lock_guard<std::mutex> lock(mAnomalyAlarmMutex);
+ mNextAnomalyAlarmTime = 0;
+}
+
+void StatsLogProcessor::informAnomalyAlarmFiredLocked(const int64_t elapsedTimeMillis) {
+ VLOG("StatsService::informAlarmForSubscriberTriggeringFired was called");
+ std::unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet =
+ mAnomalyAlarmMonitor->popSoonerThan(static_cast<uint32_t>(elapsedTimeMillis / 1000));
+ if (alarmSet.size() > 0) {
+ VLOG("Found periodic alarm fired.");
+ processFiredAnomalyAlarmsLocked(MillisToNano(elapsedTimeMillis), alarmSet);
+ } else {
+ ALOGW("Cannot find an periodic alarm that fired. Perhaps it was recently cancelled.");
+ }
+}
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index 23f2584655b0..383dbd9db2c1 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -66,11 +66,6 @@ public:
const DumpLatency dumpLatency,
ProtoOutputStream* proto);
- /* Tells MetricsManager that the alarms in alarmSet have fired. Modifies anomaly alarmSet. */
- void onAnomalyAlarmFired(
- const int64_t& timestampNs,
- unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet);
-
/* Tells MetricsManager that the alarms in alarmSet have fired. Modifies periodic alarmSet. */
void onPeriodicAlarmFired(
const int64_t& timestampNs,
@@ -139,15 +134,17 @@ public:
int64_t getLastReportTimeNs(const ConfigKey& key);
inline void setPrintLogs(bool enabled) {
-#ifdef VERY_VERBOSE_PRINTING
std::lock_guard<std::mutex> lock(mMetricsMutex);
mPrintAllLogs = enabled;
-#endif
}
// Add a specific config key to the possible configs to dump ASAP.
void noteOnDiskData(const ConfigKey& key);
+ void setAnomalyAlarm(const int64_t timeMillis);
+
+ void cancelAnomalyAlarm();
+
private:
// For testing only.
inline sp<AlarmMonitor> getAnomalyAlarmMonitor() const {
@@ -160,6 +157,11 @@ private:
mutable mutex mMetricsMutex;
+ // Guards mNextAnomalyAlarmTime. A separate mutex is needed because alarms are set/cancelled
+ // in the onLogEvent code path, which is locked by mMetricsMutex.
+ // DO NOT acquire mMetricsMutex while holding mAnomalyAlarmMutex. This can lead to a deadlock.
+ mutable mutex mAnomalyAlarmMutex;
+
std::unordered_map<ConfigKey, sp<MetricsManager>> mMetricsManagers;
std::unordered_map<ConfigKey, int64_t> mLastBroadcastTimes;
@@ -185,8 +187,8 @@ private:
void resetIfConfigTtlExpiredLocked(const int64_t timestampNs);
- void OnConfigUpdatedLocked(
- const int64_t currentTimestampNs, const ConfigKey& key, const StatsdConfig& config);
+ void OnConfigUpdatedLocked(const int64_t currentTimestampNs, const ConfigKey& key,
+ const StatsdConfig& config, bool modularUpdate = false);
void GetActiveConfigsLocked(const int uid, vector<int64_t>& outActiveConfigs);
@@ -250,6 +252,15 @@ private:
// Reset the specified configs.
void resetConfigsLocked(const int64_t timestampNs, const std::vector<ConfigKey>& configs);
+ // An anomaly alarm should have fired.
+ // Check with anomaly alarm manager to find the alarms and process the result.
+ void informAnomalyAlarmFiredLocked(const int64_t elapsedTimeMillis);
+
+ /* Tells MetricsManager that the alarms in alarmSet have fired. Modifies anomaly alarmSet. */
+ void processFiredAnomalyAlarmsLocked(
+ const int64_t& timestampNs,
+ unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet);
+
// Function used to send a broadcast so that receiver for the config key can call getData
// to retrieve the stored data.
std::function<bool(const ConfigKey& key)> mSendBroadcast;
@@ -276,9 +287,10 @@ private:
//Last time we wrote metadata to disk.
int64_t mLastMetadataWriteNs = 0;
-#ifdef VERY_VERBOSE_PRINTING
+ // The time for the next anomaly alarm for alerts.
+ int64_t mNextAnomalyAlarmTime = 0;
+
bool mPrintAllLogs = false;
-#endif
FRIEND_TEST(StatsLogProcessorTest, TestOutOfOrderLogs);
FRIEND_TEST(StatsLogProcessorTest, TestRateLimitByteSize);
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 322648229d0e..68c2dd56ef13 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -91,17 +91,13 @@ Status checkUid(uid_t expectedUid) {
StatsService::StatsService(const sp<Looper>& handlerLooper, shared_ptr<LogEventQueue> queue)
: mAnomalyAlarmMonitor(new AlarmMonitor(
MIN_DIFF_TO_UPDATE_REGISTERED_ALARM_SECS,
- [](const shared_ptr<IStatsCompanionService>& sc, int64_t timeMillis) {
- if (sc != nullptr) {
- sc->setAnomalyAlarm(timeMillis);
- StatsdStats::getInstance().noteRegisteredAnomalyAlarmChanged();
- }
+ [this](const shared_ptr<IStatsCompanionService>& /*sc*/, int64_t timeMillis) {
+ mProcessor->setAnomalyAlarm(timeMillis);
+ StatsdStats::getInstance().noteRegisteredAnomalyAlarmChanged();
},
- [](const shared_ptr<IStatsCompanionService>& sc) {
- if (sc != nullptr) {
- sc->cancelAnomalyAlarm();
- StatsdStats::getInstance().noteRegisteredAnomalyAlarmChanged();
- }
+ [this](const shared_ptr<IStatsCompanionService>& /*sc*/) {
+ mProcessor->cancelAnomalyAlarm();
+ StatsdStats::getInstance().noteRegisteredAnomalyAlarmChanged();
})),
mPeriodicAlarmMonitor(new AlarmMonitor(
MIN_DIFF_TO_UPDATE_REGISTERED_ALARM_SECS,
@@ -484,7 +480,8 @@ void StatsService::print_cmd_help(int out) {
dprintf(out, " Clear cached puller data.\n");
dprintf(out, "\n");
dprintf(out, "usage: adb shell cmd stats print-logs\n");
- dprintf(out, " Only works on eng build\n");
+ dprintf(out, " Requires root privileges.\n");
+ dprintf(out, " Can be disabled by calling adb shell cmd stats print-logs 0\n");
}
status_t StatsService::cmd_trigger_broadcast(int out, Vector<String8>& args) {
@@ -865,18 +862,19 @@ status_t StatsService::cmd_clear_puller_cache(int out) {
}
status_t StatsService::cmd_print_logs(int out, const Vector<String8>& args) {
- VLOG("StatsService::cmd_print_logs with Pid %i, Uid %i", AIBinder_getCallingPid(),
- AIBinder_getCallingUid());
- if (checkPermission(kPermissionDump)) {
- bool enabled = true;
- if (args.size() >= 2) {
- enabled = atoi(args[1].c_str()) != 0;
- }
- mProcessor->setPrintLogs(enabled);
- return NO_ERROR;
- } else {
+ Status status = checkUid(AID_ROOT);
+ if (!status.isOk()) {
return PERMISSION_DENIED;
}
+
+ VLOG("StatsService::cmd_print_logs with pid %i, uid %i", AIBinder_getCallingPid(),
+ AIBinder_getCallingUid());
+ bool enabled = true;
+ if (args.size() >= 2) {
+ enabled = atoi(args[1].c_str()) != 0;
+ }
+ mProcessor->setPrintLogs(enabled);
+ return NO_ERROR;
}
bool StatsService::getUidFromArgs(const Vector<String8>& args, size_t uidArgIndex, int32_t& uid) {
@@ -975,22 +973,6 @@ Status StatsService::informOnePackageRemoved(const string& app, int32_t uid) {
return Status::ok();
}
-Status StatsService::informAnomalyAlarmFired() {
- ENFORCE_UID(AID_SYSTEM);
-
- VLOG("StatsService::informAnomalyAlarmFired was called");
- int64_t currentTimeSec = getElapsedRealtimeSec();
- std::unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet =
- mAnomalyAlarmMonitor->popSoonerThan(static_cast<uint32_t>(currentTimeSec));
- if (alarmSet.size() > 0) {
- VLOG("Found an anomaly alarm that fired.");
- mProcessor->onAnomalyAlarmFired(currentTimeSec * NS_PER_SEC, alarmSet);
- } else {
- VLOG("Cannot find an anomaly alarm that fired. Perhaps it was recently cancelled.");
- }
- return Status::ok();
-}
-
Status StatsService::informAlarmForSubscriberTriggeringFired() {
ENFORCE_UID(AID_SYSTEM);
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index 324ffbd65e51..479f4e87ec96 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -66,7 +66,6 @@ public:
virtual Status systemRunning();
virtual Status statsCompanionReady();
virtual Status bootCompleted();
- virtual Status informAnomalyAlarmFired();
virtual Status informPollAlarmFired();
virtual Status informAlarmForSubscriberTriggeringFired();
@@ -404,6 +403,10 @@ private:
FRIEND_TEST(PartialBucketE2eTest, TestGaugeMetricOnBootWithoutMinPartialBucket);
FRIEND_TEST(PartialBucketE2eTest, TestGaugeMetricWithoutMinPartialBucket);
FRIEND_TEST(PartialBucketE2eTest, TestGaugeMetricWithMinPartialBucket);
+
+ FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket);
+ FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets);
+ FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period);
};
} // namespace statsd
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index d0d3d285ada2..e6e22bac05d4 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -485,6 +485,9 @@ message Atom {
NetworkTetheringReported network_tethering_reported =
303 [(module) = "network_tethering"];
ImeTouchReported ime_touch_reported = 304 [(module) = "sysui"];
+ UIInteractionFrameInfoReported ui_interaction_frame_info_reported =
+ 305 [(module) = "framework"];
+ UIActionLatencyReported ui_action_latency_reported = 306 [(module) = "framework"];
// StatsdStats tracks platform atoms with ids upto 500.
// Update StatsdStats::kMaxPushedAtomId when atom ids here approach that value.
@@ -583,9 +586,10 @@ message Atom {
SupportedRadioAccessFamily supported_radio_access_family = 10079 [(module) = "telephony"];
SettingSnapshot setting_snapshot = 10080 [(module) = "framework"];
BlobInfo blob_info = 10081 [(module) = "framework"];
- DataUsageBytesTransfer data_usage_bytes_transfer = 10082 [(module) = "framework"];
+ DataUsageBytesTransfer data_usage_bytes_transfer =
+ 10082 [(module) = "framework", (truncate_timestamp) = true];
BytesTransferByTagAndMetered bytes_transfer_by_tag_and_metered =
- 10083 [(module) = "framework"];
+ 10083 [(module) = "framework", (truncate_timestamp) = true];
DNDModeProto dnd_mode_rule = 10084 [(module) = "framework"];
GeneralExternalStorageAccessStats general_external_storage_access_stats =
10085 [(module) = "mediaprovider"];
@@ -4003,7 +4007,7 @@ message Notification {
optional bool is_group_summary = 5;
// The section of the shade that the notification is in.
- // See NotificationSectionsManager.PriorityBucket.
+ // See SystemUI Notifications.proto.
enum NotificationSection {
SECTION_UNKNOWN = 0;
SECTION_HEADS_UP = 1;
@@ -4011,6 +4015,7 @@ message Notification {
SECTION_PEOPLE = 3;
SECTION_ALERTING = 4;
SECTION_SILENT = 5;
+ SECTION_FOREGROUND_SERVICE = 6;
}
optional NotificationSection section = 6;
}
@@ -4244,6 +4249,19 @@ message BinaryPushStateChanged {
INSTALL_FAILURE_STATE_MISMATCH = 24;
INSTALL_FAILURE_COMMIT = 25;
REBOOT_TRIGGERED = 26;
+ // Logged after INSTALL_REQUESTED for devices installing a train that
+ // contains no module requiring reboot.
+ REBOOT_NOT_REQUIRED = 27;
+ // Logged after INSTALL_REQUESTED for devices that are installing a train
+ // which requires reboot and eligible for soft restart.
+ SOFT_RESTART_ELIGIBLE = 28;
+ // Logged after INSTALL_REQUESTED for devices that are installing a train
+ // which requires reboot and eligible for notification restart.
+ NOTIFICATION_RESTART_ELIGIBLE = 29;
+ // Logged after INSTALL_REQUESTED for devices that are installing a train
+ // which requires reboot and not eligible for any reboot promotion strategy
+ // (e.g. soft restart, notification restart).
+ NO_REBOOT_PROMOTION_STRATEGY_ELIGIBLE = 30;
}
optional State state = 6;
// Possible experiment ids for monitoring this push.
@@ -4574,7 +4592,7 @@ message GeneralExternalStorageAccessStats {
// Includes file path and ContentResolver accesses
optional uint32 secondary_storage_accesses = 4;
// Comma-separated list of mime types that were accessed.
- optional MimeTypes mime_types_accessed = 5;
+ optional MimeTypes mime_types_accessed = 5 [(log_mode) = MODE_BYTES];
}
/**
@@ -5040,6 +5058,54 @@ message BlobOpened{
optional Result result = 4;
}
+/**
+ * Event to track Jank for various system interactions.
+ *
+ * Logged from:
+ * frameworks/base/core/java/android/os/aot/FrameTracker.java
+ */
+message UIInteractionFrameInfoReported {
+ enum InteractionType {
+ UNKNOWN = 0;
+ NOTIFICATION_SHADE_SWIPE = 1;
+ }
+
+ optional InteractionType interaction_type = 1;
+
+ // Number of frames rendered during the interaction.
+ optional int64 total_frames = 2;
+
+ // Number of frames that were skipped in rendering during the interaction.
+ optional int64 missed_frames = 3;
+
+ // Maximum time it took to render a single frame during the interaction.
+ optional int64 max_frame_time_nanos = 4;
+}
+
+/**
+ * Event to track various latencies in SystemUI.
+ *
+ * Logged from:
+ * frameworks/base/core/java/com/android/internal/util/LatencyTracker.java
+ */
+message UIActionLatencyReported {
+ enum ActionType {
+ UNKNOWN = 0;
+ ACTION_EXPAND_PANEL = 1;
+ ACTION_TOGGLE_RECENTS = 2;
+ ACTION_FINGERPRINT_WAKE_AND_UNLOCK = 3;
+ ACTION_CHECK_CREDENTIAL = 4;
+ ACTION_CHECK_CREDENTIAL_UNLOCKED = 5;
+ ACTION_TURN_ON_SCREEN = 6;
+ ACTION_ROTATE_SCREEN = 7;
+ ACTION_FACE_WAKE_AND_UNLOCK = 8;
+ }
+
+ optional ActionType action = 1;
+
+ optional int64 latency_millis = 2;
+}
+
//////////////////////////////////////////////////////////////////////
// Pulled atoms below this line //
//////////////////////////////////////////////////////////////////////
@@ -6164,7 +6230,7 @@ message ProcessStatsAvailablePagesProto {
* Pulled from ProcessStatsService.java
*/
message ProcStats {
- optional ProcessStatsSectionProto proc_stats_section = 1;
+ optional ProcessStatsSectionProto proc_stats_section = 1 [(log_mode) = MODE_BYTES];
// Data pulled from device into this is sometimes sharded across multiple atoms to work around
// a size limit. When this happens, this shard ID will contain an increasing 1-indexed integer
// with the number of this shard.
@@ -6175,7 +6241,7 @@ message ProcStats {
* Pulled from ProcessStatsService.java
*/
message ProcStatsPkgProc {
- optional ProcessStatsSectionProto proc_stats_section = 1;
+ optional ProcessStatsSectionProto proc_stats_section = 1 [(log_mode) = MODE_BYTES];
}
// Next Tag: 2
@@ -6193,7 +6259,7 @@ message NotificationRemoteViewsProto {
* Pulled from NotificationManagerService.java
*/
message NotificationRemoteViews {
- optional NotificationRemoteViewsProto notification_remote_views = 1;
+ optional NotificationRemoteViewsProto notification_remote_views = 1 [(log_mode) = MODE_BYTES];
}
/**
@@ -6261,7 +6327,7 @@ message DNDModeProto {
// May also be "MANUAL_RULE" to indicate app-activation of the manual rule.
optional string id = 5;
optional int32 uid = 6 [(is_uid) = true]; // currently only SYSTEM_UID or 0 for other
- optional DNDPolicyProto policy = 7;
+ optional DNDPolicyProto policy = 7 [(log_mode) = MODE_BYTES];
}
/**
@@ -6426,7 +6492,7 @@ message PowerProfileProto {
* Pulled from PowerProfile.java
*/
message PowerProfile {
- optional PowerProfileProto power_profile = 1;
+ optional PowerProfileProto power_profile = 1 [(log_mode) = MODE_BYTES];
}
/**
@@ -8121,7 +8187,7 @@ message DeviceIdentifierAccessDenied {
message TrainInfo {
optional int64 train_version_code = 1;
- optional TrainExperimentIds train_experiment_id = 2;
+ optional TrainExperimentIds train_experiment_id = 2 [(log_mode) = MODE_BYTES];
optional string train_name = 3;
@@ -11169,8 +11235,8 @@ message BlobInfo {
optional int64 expiry_timestamp_millis = 3;
// List of committers of this Blob
- optional BlobCommitterListProto committers = 4;
+ optional BlobCommitterListProto committers = 4 [(log_mode) = MODE_BYTES];
// List of leasees of this Blob
- optional BlobLeaseeListProto leasees = 5;
+ optional BlobLeaseeListProto leasees = 5 [(log_mode) = MODE_BYTES];
}
diff --git a/cmds/statsd/src/condition/CombinationConditionTracker.cpp b/cmds/statsd/src/condition/CombinationConditionTracker.cpp
index e9875baf58c7..4574b2e34547 100644
--- a/cmds/statsd/src/condition/CombinationConditionTracker.cpp
+++ b/cmds/statsd/src/condition/CombinationConditionTracker.cpp
@@ -25,8 +25,9 @@ namespace statsd {
using std::unordered_map;
using std::vector;
-CombinationConditionTracker::CombinationConditionTracker(const int64_t& id, const int index)
- : ConditionTracker(id, index) {
+CombinationConditionTracker::CombinationConditionTracker(const int64_t& id, const int index,
+ const uint64_t protoHash)
+ : ConditionTracker(id, index, protoHash) {
VLOG("creating CombinationConditionTracker %lld", (long long)mConditionId);
}
@@ -38,9 +39,23 @@ bool CombinationConditionTracker::init(const vector<Predicate>& allConditionConf
const vector<sp<ConditionTracker>>& allConditionTrackers,
const unordered_map<int64_t, int>& conditionIdIndexMap,
vector<bool>& stack,
- vector<ConditionState>& initialConditionCache) {
+ vector<ConditionState>& conditionCache) {
VLOG("Combination predicate init() %lld", (long long)mConditionId);
if (mInitialized) {
+ // All the children are guaranteed to be initialized, but the recursion is needed to
+ // fill the conditionCache properly, since another combination condition or metric
+ // might rely on this. The recursion is needed to compute the current condition.
+
+ // Init is called instead of isConditionMet so that the ConditionKey can be filled with the
+ // default key for sliced conditions, since we do not know all indirect descendants here.
+ for (const int childIndex : mChildren) {
+ if (conditionCache[childIndex] == ConditionState::kNotEvaluated) {
+ allConditionTrackers[childIndex]->init(allConditionConfig, allConditionTrackers,
+ conditionIdIndexMap, stack, conditionCache);
+ }
+ }
+ conditionCache[mIndex] =
+ evaluateCombinationCondition(mChildren, mLogicalOperation, conditionCache);
return true;
}
@@ -74,9 +89,8 @@ bool CombinationConditionTracker::init(const vector<Predicate>& allConditionConf
return false;
}
- bool initChildSucceeded =
- childTracker->init(allConditionConfig, allConditionTrackers, conditionIdIndexMap,
- stack, initialConditionCache);
+ bool initChildSucceeded = childTracker->init(allConditionConfig, allConditionTrackers,
+ conditionIdIndexMap, stack, conditionCache);
if (!initChildSucceeded) {
ALOGW("Child initialization failed %lld ", (long long)child);
@@ -92,14 +106,14 @@ bool CombinationConditionTracker::init(const vector<Predicate>& allConditionConf
mUnSlicedChildren.push_back(childIndex);
}
mChildren.push_back(childIndex);
- mTrackerIndex.insert(childTracker->getLogTrackerIndex().begin(),
- childTracker->getLogTrackerIndex().end());
+ mTrackerIndex.insert(childTracker->getAtomMatchingTrackerIndex().begin(),
+ childTracker->getAtomMatchingTrackerIndex().end());
}
- mUnSlicedPartCondition = evaluateCombinationCondition(mUnSlicedChildren, mLogicalOperation,
- initialConditionCache);
- initialConditionCache[mIndex] =
- evaluateCombinationCondition(mChildren, mLogicalOperation, initialConditionCache);
+ mUnSlicedPartCondition =
+ evaluateCombinationCondition(mUnSlicedChildren, mLogicalOperation, conditionCache);
+ conditionCache[mIndex] =
+ evaluateCombinationCondition(mChildren, mLogicalOperation, conditionCache);
// unmark this node in the recursion stack.
stack[mIndex] = false;
@@ -109,6 +123,49 @@ bool CombinationConditionTracker::init(const vector<Predicate>& allConditionConf
return true;
}
+bool CombinationConditionTracker::onConfigUpdated(
+ const vector<Predicate>& allConditionProtos, const int index,
+ const vector<sp<ConditionTracker>>& allConditionTrackers,
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ const unordered_map<int64_t, int>& conditionTrackerMap) {
+ ConditionTracker::onConfigUpdated(allConditionProtos, index, allConditionTrackers,
+ atomMatchingTrackerMap, conditionTrackerMap);
+ mTrackerIndex.clear();
+ mChildren.clear();
+ mUnSlicedChildren.clear();
+ mSlicedChildren.clear();
+ Predicate_Combination combinationCondition = allConditionProtos[mIndex].combination();
+
+ for (const int64_t child : combinationCondition.predicate()) {
+ const auto& it = conditionTrackerMap.find(child);
+
+ if (it == conditionTrackerMap.end()) {
+ ALOGW("Predicate %lld not found in the config", (long long)child);
+ return false;
+ }
+
+ int childIndex = it->second;
+ const sp<ConditionTracker>& childTracker = allConditionTrackers[childIndex];
+
+ // Ensures that the child's tracker indices are updated.
+ if (!childTracker->onConfigUpdated(allConditionProtos, childIndex, allConditionTrackers,
+ atomMatchingTrackerMap, conditionTrackerMap)) {
+ ALOGW("Child update failed %lld ", (long long)child);
+ return false;
+ }
+
+ if (allConditionTrackers[childIndex]->isSliced()) {
+ mSlicedChildren.push_back(childIndex);
+ } else {
+ mUnSlicedChildren.push_back(childIndex);
+ }
+ mChildren.push_back(childIndex);
+ mTrackerIndex.insert(childTracker->getAtomMatchingTrackerIndex().begin(),
+ childTracker->getAtomMatchingTrackerIndex().end());
+ }
+ return true;
+}
+
void CombinationConditionTracker::isConditionMet(
const ConditionKey& conditionParameters, const vector<sp<ConditionTracker>>& allConditions,
const bool isPartialLink,
diff --git a/cmds/statsd/src/condition/CombinationConditionTracker.h b/cmds/statsd/src/condition/CombinationConditionTracker.h
index 39ff0ab03266..672d61c82268 100644
--- a/cmds/statsd/src/condition/CombinationConditionTracker.h
+++ b/cmds/statsd/src/condition/CombinationConditionTracker.h
@@ -24,16 +24,21 @@ namespace android {
namespace os {
namespace statsd {
-class CombinationConditionTracker : public virtual ConditionTracker {
+class CombinationConditionTracker : public ConditionTracker {
public:
- CombinationConditionTracker(const int64_t& id, const int index);
+ CombinationConditionTracker(const int64_t& id, const int index, const uint64_t protoHash);
~CombinationConditionTracker();
bool init(const std::vector<Predicate>& allConditionConfig,
const std::vector<sp<ConditionTracker>>& allConditionTrackers,
const std::unordered_map<int64_t, int>& conditionIdIndexMap, std::vector<bool>& stack,
- std::vector<ConditionState>& initialConditionCache) override;
+ std::vector<ConditionState>& conditionCache) override;
+
+ bool onConfigUpdated(const std::vector<Predicate>& allConditionProtos, const int index,
+ const std::vector<sp<ConditionTracker>>& allConditionTrackers,
+ const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ const std::unordered_map<int64_t, int>& conditionTrackerMap) override;
void evaluateCondition(const LogEvent& event,
const std::vector<MatchingState>& eventMatcherValues,
@@ -102,6 +107,7 @@ private:
std::vector<int> mSlicedChildren;
std::vector<int> mUnSlicedChildren;
+ FRIEND_TEST(ConfigUpdateTest, TestUpdateConditions);
};
} // namespace statsd
diff --git a/cmds/statsd/src/condition/ConditionTracker.h b/cmds/statsd/src/condition/ConditionTracker.h
index 62736c8160bb..3bf4e636be89 100644
--- a/cmds/statsd/src/condition/ConditionTracker.h
+++ b/cmds/statsd/src/condition/ConditionTracker.h
@@ -18,7 +18,7 @@
#include "condition/condition_util.h"
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
-#include "matchers/LogMatchingTracker.h"
+#include "matchers/AtomMatchingTracker.h"
#include "matchers/matcher_util.h"
#include <utils/RefBase.h>
@@ -31,38 +31,59 @@ namespace statsd {
class ConditionTracker : public virtual RefBase {
public:
- ConditionTracker(const int64_t& id, const int index)
+ ConditionTracker(const int64_t& id, const int index, const uint64_t protoHash)
: mConditionId(id),
mIndex(index),
mInitialized(false),
mTrackerIndex(),
mUnSlicedPartCondition(ConditionState::kUnknown),
- mSliced(false){};
+ mSliced(false),
+ mProtoHash(protoHash){};
virtual ~ConditionTracker(){};
- inline const int64_t& getId() { return mConditionId; }
-
// Initialize this ConditionTracker. This initialization is done recursively (DFS). It can also
// be done in the constructor, but we do it separately because (1) easy to return a bool to
// indicate whether the initialization is successful. (2) makes unit test easier.
+ // This function can also be called on config updates, in which case it does nothing other than
+ // fill the condition cache with the current condition.
// allConditionConfig: the list of all Predicate config from statsd_config.
// allConditionTrackers: the list of all ConditionTrackers (this is needed because we may also
- // need to call init() on children conditions)
+ // need to call init() on child conditions)
// conditionIdIndexMap: the mapping from condition id to its index.
// stack: a bit map to keep track which nodes have been visited on the stack in the recursion.
- // initialConditionCache: tracks initial conditions of all ConditionTrackers.
+ // conditionCache: tracks initial conditions of all ConditionTrackers. returns the
+ // current condition if called on a config update.
virtual bool init(const std::vector<Predicate>& allConditionConfig,
const std::vector<sp<ConditionTracker>>& allConditionTrackers,
const std::unordered_map<int64_t, int>& conditionIdIndexMap,
- std::vector<bool>& stack,
- std::vector<ConditionState>& initialConditionCache) = 0;
+ std::vector<bool>& stack, std::vector<ConditionState>& conditionCache) = 0;
+
+ // Update appropriate state on config updates. Primarily, all indices need to be updated.
+ // This predicate and all of its children are guaranteed to be preserved across the update.
+ // This function is recursive and will call onConfigUpdated on child conditions. It does not
+ // manage cycle detection since all preserved conditions should not have any cycles.
+ //
+ // allConditionProtos: the new predicates.
+ // index: the new index of this tracker in allConditionProtos and allConditionTrackers.
+ // allConditionTrackers: the list of all ConditionTrackers (this is needed because we may also
+ // need to call onConfigUpdated() on child conditions)
+ // [atomMatchingTrackerMap]: map of atom matcher id to index after the config update
+ // [conditionTrackerMap]: map of condition tracker id to index after the config update.
+ // returns whether or not the update is successful
+ virtual bool onConfigUpdated(const std::vector<Predicate>& allConditionProtos, const int index,
+ const std::vector<sp<ConditionTracker>>& allConditionTrackers,
+ const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ const std::unordered_map<int64_t, int>& conditionTrackerMap) {
+ mIndex = index;
+ return true;
+ }
// evaluate current condition given the new event.
// event: the new log event
- // eventMatcherValues: the results of the LogMatcherTrackers. LogMatcherTrackers always process
- // event before ConditionTrackers, because ConditionTracker depends on
- // LogMatchingTrackers.
+ // eventMatcherValues: the results of the AtomMatchingTrackers. AtomMatchingTrackers always
+ // process event before ConditionTrackers, because ConditionTracker depends
+ // on AtomMatchingTrackers.
// mAllConditions: the list of all ConditionTracker
// conditionCache: the cached non-sliced condition of the ConditionTrackers for this new event.
// conditionChanged: the bit map to record whether the condition has changed.
@@ -88,8 +109,8 @@ public:
const bool isPartialLink,
std::vector<ConditionState>& conditionCache) const = 0;
- // return the list of LogMatchingTracker index that this ConditionTracker uses.
- virtual const std::set<int>& getLogTrackerIndex() const {
+ // return the list of AtomMatchingTracker index that this ConditionTracker uses.
+ virtual const std::set<int>& getAtomMatchingTrackerIndex() const {
return mTrackerIndex;
}
@@ -110,6 +131,10 @@ public:
return mConditionId;
}
+ inline uint64_t getProtoHash() const {
+ return mProtoHash;
+ }
+
virtual void getTrueSlicedDimensions(
const std::vector<sp<ConditionTracker>>& allConditions,
std::set<HashableDimensionKey>* dimensions) const = 0;
@@ -131,12 +156,12 @@ protected:
const int64_t mConditionId;
// the index of this condition in the manager's condition list.
- const int mIndex;
+ int mIndex;
// if it's properly initialized.
bool mInitialized;
- // the list of LogMatchingTracker index that this ConditionTracker uses.
+ // the list of AtomMatchingTracker index that this ConditionTracker uses.
std::set<int> mTrackerIndex;
// This variable is only used for CombinationConditionTrackers.
@@ -149,6 +174,12 @@ protected:
ConditionState mUnSlicedPartCondition;
bool mSliced;
+
+ // Hash of the Predicate's proto bytes from StatsdConfig.
+ // Used to determine if the definition of this condition has changed across a config update.
+ const uint64_t mProtoHash;
+
+ FRIEND_TEST(ConfigUpdateTest, TestUpdateConditions);
};
} // namespace statsd
diff --git a/cmds/statsd/src/condition/SimpleConditionTracker.cpp b/cmds/statsd/src/condition/SimpleConditionTracker.cpp
index efb4d4989425..1dcc8f96131a 100644
--- a/cmds/statsd/src/condition/SimpleConditionTracker.cpp
+++ b/cmds/statsd/src/condition/SimpleConditionTracker.cpp
@@ -27,54 +27,21 @@ namespace statsd {
using std::unordered_map;
SimpleConditionTracker::SimpleConditionTracker(
- const ConfigKey& key, const int64_t& id, const int index,
+ const ConfigKey& key, const int64_t& id, const uint64_t protoHash, const int index,
const SimplePredicate& simplePredicate,
- const unordered_map<int64_t, int>& trackerNameIndexMap)
- : ConditionTracker(id, index), mConfigKey(key), mContainANYPositionInInternalDimensions(false) {
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap)
+ : ConditionTracker(id, index, protoHash),
+ mConfigKey(key),
+ mContainANYPositionInInternalDimensions(false) {
VLOG("creating SimpleConditionTracker %lld", (long long)mConditionId);
mCountNesting = simplePredicate.count_nesting();
- if (simplePredicate.has_start()) {
- auto pair = trackerNameIndexMap.find(simplePredicate.start());
- if (pair == trackerNameIndexMap.end()) {
- ALOGW("Start matcher %lld not found in the config", (long long)simplePredicate.start());
- return;
- }
- mStartLogMatcherIndex = pair->second;
- mTrackerIndex.insert(mStartLogMatcherIndex);
- } else {
- mStartLogMatcherIndex = -1;
- }
-
- if (simplePredicate.has_stop()) {
- auto pair = trackerNameIndexMap.find(simplePredicate.stop());
- if (pair == trackerNameIndexMap.end()) {
- ALOGW("Stop matcher %lld not found in the config", (long long)simplePredicate.stop());
- return;
- }
- mStopLogMatcherIndex = pair->second;
- mTrackerIndex.insert(mStopLogMatcherIndex);
- } else {
- mStopLogMatcherIndex = -1;
- }
-
- if (simplePredicate.has_stop_all()) {
- auto pair = trackerNameIndexMap.find(simplePredicate.stop_all());
- if (pair == trackerNameIndexMap.end()) {
- ALOGW("Stop all matcher %lld found in the config", (long long)simplePredicate.stop_all());
- return;
- }
- mStopAllLogMatcherIndex = pair->second;
- mTrackerIndex.insert(mStopAllLogMatcherIndex);
- } else {
- mStopAllLogMatcherIndex = -1;
- }
+ setMatcherIndices(simplePredicate, atomMatchingTrackerMap);
if (simplePredicate.has_dimensions()) {
translateFieldMatcher(simplePredicate.dimensions(), &mOutputDimensions);
if (mOutputDimensions.size() > 0) {
mSliced = true;
- mDimensionTag = mOutputDimensions[0].mMatcher.getTag();
}
mContainANYPositionInInternalDimensions = HasPositionANY(simplePredicate.dimensions());
}
@@ -95,14 +62,70 @@ SimpleConditionTracker::~SimpleConditionTracker() {
bool SimpleConditionTracker::init(const vector<Predicate>& allConditionConfig,
const vector<sp<ConditionTracker>>& allConditionTrackers,
const unordered_map<int64_t, int>& conditionIdIndexMap,
- vector<bool>& stack,
- vector<ConditionState>& initialConditionCache) {
+ vector<bool>& stack, vector<ConditionState>& conditionCache) {
// SimpleConditionTracker does not have dependency on other conditions, thus we just return
// if the initialization was successful.
- initialConditionCache[mIndex] = mInitialValue;
+ ConditionKey conditionKey;
+ if (mSliced) {
+ conditionKey[mConditionId] = DEFAULT_DIMENSION_KEY;
+ }
+ isConditionMet(conditionKey, allConditionTrackers, mSliced, conditionCache);
return mInitialized;
}
+bool SimpleConditionTracker::onConfigUpdated(
+ const vector<Predicate>& allConditionProtos, const int index,
+ const vector<sp<ConditionTracker>>& allConditionTrackers,
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ const unordered_map<int64_t, int>& conditionTrackerMap) {
+ ConditionTracker::onConfigUpdated(allConditionProtos, index, allConditionTrackers,
+ atomMatchingTrackerMap, conditionTrackerMap);
+ setMatcherIndices(allConditionProtos[index].simple_predicate(), atomMatchingTrackerMap);
+ return true;
+}
+
+void SimpleConditionTracker::setMatcherIndices(
+ const SimplePredicate& simplePredicate,
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap) {
+ mTrackerIndex.clear();
+ if (simplePredicate.has_start()) {
+ auto pair = atomMatchingTrackerMap.find(simplePredicate.start());
+ if (pair == atomMatchingTrackerMap.end()) {
+ ALOGW("Start matcher %lld not found in the config", (long long)simplePredicate.start());
+ return;
+ }
+ mStartLogMatcherIndex = pair->second;
+ mTrackerIndex.insert(mStartLogMatcherIndex);
+ } else {
+ mStartLogMatcherIndex = -1;
+ }
+
+ if (simplePredicate.has_stop()) {
+ auto pair = atomMatchingTrackerMap.find(simplePredicate.stop());
+ if (pair == atomMatchingTrackerMap.end()) {
+ ALOGW("Stop matcher %lld not found in the config", (long long)simplePredicate.stop());
+ return;
+ }
+ mStopLogMatcherIndex = pair->second;
+ mTrackerIndex.insert(mStopLogMatcherIndex);
+ } else {
+ mStopLogMatcherIndex = -1;
+ }
+
+ if (simplePredicate.has_stop_all()) {
+ auto pair = atomMatchingTrackerMap.find(simplePredicate.stop_all());
+ if (pair == atomMatchingTrackerMap.end()) {
+ ALOGW("Stop all matcher %lld found in the config",
+ (long long)simplePredicate.stop_all());
+ return;
+ }
+ mStopAllLogMatcherIndex = pair->second;
+ mTrackerIndex.insert(mStopAllLogMatcherIndex);
+ } else {
+ mStopAllLogMatcherIndex = -1;
+ }
+}
+
void SimpleConditionTracker::dumpState() {
VLOG("%lld DUMP:", (long long)mConditionId);
for (const auto& pair : mSlicedConditionState) {
diff --git a/cmds/statsd/src/condition/SimpleConditionTracker.h b/cmds/statsd/src/condition/SimpleConditionTracker.h
index ea7f87bde2b8..7a8b40108448 100644
--- a/cmds/statsd/src/condition/SimpleConditionTracker.h
+++ b/cmds/statsd/src/condition/SimpleConditionTracker.h
@@ -27,18 +27,23 @@ namespace android {
namespace os {
namespace statsd {
-class SimpleConditionTracker : public virtual ConditionTracker {
+class SimpleConditionTracker : public ConditionTracker {
public:
- SimpleConditionTracker(const ConfigKey& key, const int64_t& id, const int index,
- const SimplePredicate& simplePredicate,
- const std::unordered_map<int64_t, int>& trackerNameIndexMap);
+ SimpleConditionTracker(const ConfigKey& key, const int64_t& id, const uint64_t protoHash,
+ const int index, const SimplePredicate& simplePredicate,
+ const std::unordered_map<int64_t, int>& atomMatchingTrackerMap);
~SimpleConditionTracker();
bool init(const std::vector<Predicate>& allConditionConfig,
const std::vector<sp<ConditionTracker>>& allConditionTrackers,
const std::unordered_map<int64_t, int>& conditionIdIndexMap, std::vector<bool>& stack,
- std::vector<ConditionState>& initialConditionCache) override;
+ std::vector<ConditionState>& conditionCache) override;
+
+ bool onConfigUpdated(const std::vector<Predicate>& allConditionProtos, const int index,
+ const std::vector<sp<ConditionTracker>>& allConditionTrackers,
+ const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ const std::unordered_map<int64_t, int>& conditionTrackerMap) override;
void evaluateCondition(const LogEvent& event,
const std::vector<MatchingState>& eventMatcherValues,
@@ -112,10 +117,11 @@ private:
std::set<HashableDimensionKey> mLastChangedToTrueDimensions;
std::set<HashableDimensionKey> mLastChangedToFalseDimensions;
- int mDimensionTag;
-
std::map<HashableDimensionKey, int> mSlicedConditionState;
+ void setMatcherIndices(const SimplePredicate& predicate,
+ const std::unordered_map<int64_t, int>& logTrackerMap);
+
void handleStopAll(std::vector<ConditionState>& conditionCache,
std::vector<bool>& changedCache);
@@ -129,6 +135,7 @@ private:
FRIEND_TEST(SimpleConditionTrackerTest, TestSlicedCondition);
FRIEND_TEST(SimpleConditionTrackerTest, TestSlicedWithNoOutputDim);
FRIEND_TEST(SimpleConditionTrackerTest, TestStopAll);
+ FRIEND_TEST(ConfigUpdateTest, TestUpdateConditions);
};
} // namespace statsd
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index 8a9ec7456e55..46c377037542 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -92,63 +92,43 @@ StatsPullerManager::StatsPullerManager()
}
bool StatsPullerManager::Pull(int tagId, const ConfigKey& configKey, const int64_t eventTimeNs,
- vector<shared_ptr<LogEvent>>* data, bool useUids) {
+ vector<shared_ptr<LogEvent>>* data) {
std::lock_guard<std::mutex> _l(mLock);
- return PullLocked(tagId, configKey, eventTimeNs, data, useUids);
+ return PullLocked(tagId, configKey, eventTimeNs, data);
}
bool StatsPullerManager::Pull(int tagId, const vector<int32_t>& uids, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool useUids) {
+ vector<std::shared_ptr<LogEvent>>* data) {
std::lock_guard<std::mutex> _l(mLock);
- return PullLocked(tagId, uids, eventTimeNs, data, useUids);
+ return PullLocked(tagId, uids, eventTimeNs, data);
}
bool StatsPullerManager::PullLocked(int tagId, const ConfigKey& configKey,
- const int64_t eventTimeNs, vector<shared_ptr<LogEvent>>* data,
- bool useUids) {
+ const int64_t eventTimeNs, vector<shared_ptr<LogEvent>>* data) {
vector<int32_t> uids;
- if (useUids) {
- auto uidProviderIt = mPullUidProviders.find(configKey);
- if (uidProviderIt == mPullUidProviders.end()) {
- ALOGE("Error pulling tag %d. No pull uid provider for config key %s", tagId,
- configKey.ToString().c_str());
- StatsdStats::getInstance().notePullUidProviderNotFound(tagId);
- return false;
- }
- sp<PullUidProvider> pullUidProvider = uidProviderIt->second.promote();
- if (pullUidProvider == nullptr) {
- ALOGE("Error pulling tag %d, pull uid provider for config %s is gone.", tagId,
- configKey.ToString().c_str());
- StatsdStats::getInstance().notePullUidProviderNotFound(tagId);
- return false;
- }
- uids = pullUidProvider->getPullAtomUids(tagId);
+ const auto& uidProviderIt = mPullUidProviders.find(configKey);
+ if (uidProviderIt == mPullUidProviders.end()) {
+ ALOGE("Error pulling tag %d. No pull uid provider for config key %s", tagId,
+ configKey.ToString().c_str());
+ StatsdStats::getInstance().notePullUidProviderNotFound(tagId);
+ return false;
}
- return PullLocked(tagId, uids, eventTimeNs, data, useUids);
+ sp<PullUidProvider> pullUidProvider = uidProviderIt->second.promote();
+ if (pullUidProvider == nullptr) {
+ ALOGE("Error pulling tag %d, pull uid provider for config %s is gone.", tagId,
+ configKey.ToString().c_str());
+ StatsdStats::getInstance().notePullUidProviderNotFound(tagId);
+ return false;
+ }
+ uids = pullUidProvider->getPullAtomUids(tagId);
+ return PullLocked(tagId, uids, eventTimeNs, data);
}
bool StatsPullerManager::PullLocked(int tagId, const vector<int32_t>& uids,
- const int64_t eventTimeNs, vector<shared_ptr<LogEvent>>* data,
- bool useUids) {
+ const int64_t eventTimeNs, vector<shared_ptr<LogEvent>>* data) {
VLOG("Initiating pulling %d", tagId);
- if (useUids) {
- for (int32_t uid : uids) {
- PullerKey key = {.atomTag = tagId, .uid = uid};
- auto pullerIt = kAllPullAtomInfo.find(key);
- if (pullerIt != kAllPullAtomInfo.end()) {
- bool ret = pullerIt->second->Pull(eventTimeNs, data);
- VLOG("pulled %zu items", data->size());
- if (!ret) {
- StatsdStats::getInstance().notePullFailed(tagId);
- }
- return ret;
- }
- }
- StatsdStats::getInstance().notePullerNotFound(tagId);
- ALOGW("StatsPullerManager: Unknown tagId %d", tagId);
- return false; // Return early since we don't know what to pull.
- } else {
- PullerKey key = {.atomTag = tagId, .uid = -1};
+ for (int32_t uid : uids) {
+ PullerKey key = {.atomTag = tagId, .uid = uid};
auto pullerIt = kAllPullAtomInfo.find(key);
if (pullerIt != kAllPullAtomInfo.end()) {
bool ret = pullerIt->second->Pull(eventTimeNs, data);
@@ -158,9 +138,10 @@ bool StatsPullerManager::PullLocked(int tagId, const vector<int32_t>& uids,
}
return ret;
}
- ALOGW("StatsPullerManager: Unknown tagId %d", tagId);
- return false; // Return early since we don't know what to pull.
}
+ StatsdStats::getInstance().notePullerNotFound(tagId);
+ ALOGW("StatsPullerManager: Unknown tagId %d", tagId);
+ return false; // Return early since we don't know what to pull.
}
bool StatsPullerManager::PullerForMatcherExists(int tagId) const {
@@ -352,8 +333,7 @@ int StatsPullerManager::ClearPullerCacheIfNecessary(int64_t timestampNs) {
void StatsPullerManager::RegisterPullAtomCallback(const int uid, const int32_t atomTag,
const int64_t coolDownNs, const int64_t timeoutNs,
const vector<int32_t>& additiveFields,
- const shared_ptr<IPullAtomCallback>& callback,
- bool useUid) {
+ const shared_ptr<IPullAtomCallback>& callback) {
std::lock_guard<std::mutex> _l(mLock);
VLOG("RegisterPullerCallback: adding puller for tag %d", atomTag);
@@ -368,16 +348,15 @@ void StatsPullerManager::RegisterPullAtomCallback(const int uid, const int32_t a
sp<StatsCallbackPuller> puller = new StatsCallbackPuller(atomTag, callback, actualCoolDownNs,
actualTimeoutNs, additiveFields);
- PullerKey key = {.atomTag = atomTag, .uid = useUid ? uid : -1};
+ PullerKey key = {.atomTag = atomTag, .uid = uid};
AIBinder_linkToDeath(callback->asBinder().get(), mPullAtomCallbackDeathRecipient.get(),
new PullAtomCallbackDeathCookie(this, key, puller));
kAllPullAtomInfo[key] = puller;
}
-void StatsPullerManager::UnregisterPullAtomCallback(const int uid, const int32_t atomTag,
- bool useUids) {
+void StatsPullerManager::UnregisterPullAtomCallback(const int uid, const int32_t atomTag) {
std::lock_guard<std::mutex> _l(mLock);
- PullerKey key = {.atomTag = atomTag, .uid = useUids ? uid : -1};
+ PullerKey key = {.atomTag = atomTag, .uid = uid};
if (kAllPullAtomInfo.find(key) != kAllPullAtomInfo.end()) {
StatsdStats::getInstance().notePullerCallbackRegistrationChanged(atomTag,
/*registered=*/false);
diff --git a/cmds/statsd/src/external/StatsPullerManager.h b/cmds/statsd/src/external/StatsPullerManager.h
index 194a0f5edba8..489cbdbe5400 100644
--- a/cmds/statsd/src/external/StatsPullerManager.h
+++ b/cmds/statsd/src/external/StatsPullerManager.h
@@ -102,11 +102,11 @@ public:
// If the metric wants to make any change to the data, like timestamps, they
// should make a copy as this data may be shared with multiple metrics.
virtual bool Pull(int tagId, const ConfigKey& configKey, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool useUids = true);
+ vector<std::shared_ptr<LogEvent>>* data);
// Same as above, but directly specify the allowed uids to pull from.
virtual bool Pull(int tagId, const vector<int32_t>& uids, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool useUids = true);
+ vector<std::shared_ptr<LogEvent>>* data);
// Clear pull data cache immediately.
int ForceClearPullerCache();
@@ -118,10 +118,9 @@ public:
void RegisterPullAtomCallback(const int uid, const int32_t atomTag, const int64_t coolDownNs,
const int64_t timeoutNs, const vector<int32_t>& additiveFields,
- const shared_ptr<IPullAtomCallback>& callback,
- bool useUid = true);
+ const shared_ptr<IPullAtomCallback>& callback);
- void UnregisterPullAtomCallback(const int uid, const int32_t atomTag, bool useUids = true);
+ void UnregisterPullAtomCallback(const int uid, const int32_t atomTag);
std::map<const PullerKey, sp<StatsPuller>> kAllPullAtomInfo;
@@ -153,10 +152,10 @@ private:
std::map<ConfigKey, wp<PullUidProvider>> mPullUidProviders;
bool PullLocked(int tagId, const ConfigKey& configKey, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool useUids = true);
+ vector<std::shared_ptr<LogEvent>>* data);
bool PullLocked(int tagId, const vector<int32_t>& uids, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool useUids);
+ vector<std::shared_ptr<LogEvent>>* data);
// locks for data receiver and StatsCompanionService changes
std::mutex mLock;
diff --git a/cmds/statsd/src/hash.h b/cmds/statsd/src/hash.h
index cfe869f60202..bd6b0cd47eaf 100644
--- a/cmds/statsd/src/hash.h
+++ b/cmds/statsd/src/hash.h
@@ -22,6 +22,7 @@ namespace android {
namespace os {
namespace statsd {
+// Uses murmur2 hashing algorithm.
extern uint32_t Hash32(const char *data, size_t n, uint32_t seed);
extern uint64_t Hash64(const char* data, size_t n, uint64_t seed);
diff --git a/cmds/statsd/src/matchers/AtomMatchingTracker.h b/cmds/statsd/src/matchers/AtomMatchingTracker.h
new file mode 100644
index 000000000000..c1384972464c
--- /dev/null
+++ b/cmds/statsd/src/matchers/AtomMatchingTracker.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ATOM_MATCHING_TRACKER_H
+#define ATOM_MATCHING_TRACKER_H
+
+#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
+#include "logd/LogEvent.h"
+#include "matchers/matcher_util.h"
+
+#include <utils/RefBase.h>
+
+#include <set>
+#include <unordered_map>
+#include <vector>
+
+namespace android {
+namespace os {
+namespace statsd {
+
+class AtomMatchingTracker : public virtual RefBase {
+public:
+ AtomMatchingTracker(const int64_t& id, const int index, const uint64_t protoHash)
+ : mId(id), mIndex(index), mInitialized(false), mProtoHash(protoHash){};
+
+ virtual ~AtomMatchingTracker(){};
+
+ // Initialize this AtomMatchingTracker.
+ // allAtomMatchers: the list of the AtomMatcher proto config. This is needed because we don't
+ // store the proto object in memory. We only need it during initilization.
+ // allAtomMatchingTrackers: the list of the AtomMatchingTracker objects. It's a one-to-one
+ // mapping with allAtomMatchers. This is needed because the
+ // initialization is done recursively for
+ // CombinationAtomMatchingTrackers using DFS.
+ // stack: a bit map to record which matcher has been visited on the stack. This is for detecting
+ // circle dependency.
+ virtual bool init(const std::vector<AtomMatcher>& allAtomMatchers,
+ const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ const std::unordered_map<int64_t, int>& matcherMap,
+ std::vector<bool>& stack) = 0;
+
+ // Update appropriate state on config updates. Primarily, all indices need to be updated.
+ // This matcher and all of its children are guaranteed to be preserved across the update.
+ // matcher: the AtomMatcher proto from the config.
+ // index: the index of this matcher in mAllAtomMatchingTrackers.
+ // atomMatchingTrackerMap: map from matcher id to index in mAllAtomMatchingTrackers
+ virtual bool onConfigUpdated(
+ const AtomMatcher& matcher, const int index,
+ const std::unordered_map<int64_t, int>& atomMatchingTrackerMap) = 0;
+
+ // Called when a log event comes.
+ // event: the log event.
+ // allAtomMatchingTrackers: the list of all AtomMatchingTrackers. This is needed because the log
+ // processing is done recursively.
+ // matcherResults: The cached results for all matchers for this event. Parent matchers can
+ // directly access the children's matching results if they have been evaluated.
+ // Otherwise, call children matchers' onLogEvent.
+ virtual void onLogEvent(const LogEvent& event,
+ const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ std::vector<MatchingState>& matcherResults) = 0;
+
+ // Get the tagIds that this matcher cares about. The combined collection is stored
+ // in MetricMananger, so that we can pass any LogEvents that are not interest of us. It uses
+ // some memory but hopefully it can save us much CPU time when there is flood of events.
+ virtual const std::set<int>& getAtomIds() const {
+ return mAtomIds;
+ }
+
+ int64_t getId() const {
+ return mId;
+ }
+
+ uint64_t getProtoHash() const {
+ return mProtoHash;
+ }
+
+protected:
+ // Name of this matching. We don't really need the name, but it makes log message easy to debug.
+ const int64_t mId;
+
+ // Index of this AtomMatchingTracker in MetricsManager's container.
+ int mIndex;
+
+ // Whether this AtomMatchingTracker has been properly initialized.
+ bool mInitialized;
+
+ // The collection of the event tag ids that this AtomMatchingTracker cares. So we can quickly
+ // return kNotMatched when we receive an event with an id not in the list. This is especially
+ // useful when we have a complex CombinationAtomMatchingTracker.
+ std::set<int> mAtomIds;
+
+ // Hash of the AtomMatcher's proto bytes from StatsdConfig.
+ // Used to determine if the definition of this matcher has changed across a config update.
+ const uint64_t mProtoHash;
+
+ FRIEND_TEST(MetricsManagerTest, TestCreateAtomMatchingTrackerSimple);
+ FRIEND_TEST(MetricsManagerTest, TestCreateAtomMatchingTrackerCombination);
+ FRIEND_TEST(ConfigUpdateTest, TestUpdateMatchers);
+};
+
+} // namespace statsd
+} // namespace os
+} // namespace android
+
+#endif // ATOM_MATCHING_TRACKER_H
diff --git a/cmds/statsd/src/matchers/CombinationLogMatchingTracker.cpp b/cmds/statsd/src/matchers/CombinationAtomMatchingTracker.cpp
index b94a9572113e..45685ce5bfee 100644
--- a/cmds/statsd/src/matchers/CombinationLogMatchingTracker.cpp
+++ b/cmds/statsd/src/matchers/CombinationAtomMatchingTracker.cpp
@@ -16,7 +16,8 @@
#include "Log.h"
-#include "CombinationLogMatchingTracker.h"
+#include "CombinationAtomMatchingTracker.h"
+
#include "matchers/matcher_util.h"
namespace android {
@@ -27,17 +28,18 @@ using std::set;
using std::unordered_map;
using std::vector;
-CombinationLogMatchingTracker::CombinationLogMatchingTracker(const int64_t& id, const int index)
- : LogMatchingTracker(id, index) {
+CombinationAtomMatchingTracker::CombinationAtomMatchingTracker(const int64_t& id, const int index,
+ const uint64_t protoHash)
+ : AtomMatchingTracker(id, index, protoHash) {
}
-CombinationLogMatchingTracker::~CombinationLogMatchingTracker() {
+CombinationAtomMatchingTracker::~CombinationAtomMatchingTracker() {
}
-bool CombinationLogMatchingTracker::init(const vector<AtomMatcher>& allLogMatchers,
- const vector<sp<LogMatchingTracker>>& allTrackers,
- const unordered_map<int64_t, int>& matcherMap,
- vector<bool>& stack) {
+bool CombinationAtomMatchingTracker::init(
+ const vector<AtomMatcher>& allAtomMatchers,
+ const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ const unordered_map<int64_t, int>& matcherMap, vector<bool>& stack) {
if (mInitialized) {
return true;
}
@@ -45,7 +47,7 @@ bool CombinationLogMatchingTracker::init(const vector<AtomMatcher>& allLogMatche
// mark this node as visited in the recursion stack.
stack[mIndex] = true;
- AtomMatcher_Combination matcher = allLogMatchers[mIndex].combination();
+ AtomMatcher_Combination matcher = allAtomMatchers[mIndex].combination();
// LogicalOperation is missing in the config
if (!matcher.has_operation()) {
@@ -73,14 +75,15 @@ bool CombinationLogMatchingTracker::init(const vector<AtomMatcher>& allLogMatche
return false;
}
- if (!allTrackers[childIndex]->init(allLogMatchers, allTrackers, matcherMap, stack)) {
+ if (!allAtomMatchingTrackers[childIndex]->init(allAtomMatchers, allAtomMatchingTrackers,
+ matcherMap, stack)) {
ALOGW("child matcher init failed %lld", (long long)child);
return false;
}
mChildren.push_back(childIndex);
- const set<int>& childTagIds = allTrackers[childIndex]->getAtomIds();
+ const set<int>& childTagIds = allAtomMatchingTrackers[childIndex]->getAtomIds();
mAtomIds.insert(childTagIds.begin(), childTagIds.end());
}
@@ -90,9 +93,26 @@ bool CombinationLogMatchingTracker::init(const vector<AtomMatcher>& allLogMatche
return true;
}
-void CombinationLogMatchingTracker::onLogEvent(const LogEvent& event,
- const vector<sp<LogMatchingTracker>>& allTrackers,
- vector<MatchingState>& matcherResults) {
+bool CombinationAtomMatchingTracker::onConfigUpdated(
+ const AtomMatcher& matcher, const int index,
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap) {
+ mIndex = index;
+ mChildren.clear();
+ AtomMatcher_Combination combinationMatcher = matcher.combination();
+ for (const int64_t child : combinationMatcher.matcher()) {
+ const auto& pair = atomMatchingTrackerMap.find(child);
+ if (pair == atomMatchingTrackerMap.end()) {
+ ALOGW("Matcher %lld not found in the config", (long long)child);
+ return false;
+ }
+ mChildren.push_back(pair->second);
+ }
+ return true;
+}
+
+void CombinationAtomMatchingTracker::onLogEvent(
+ const LogEvent& event, const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ vector<MatchingState>& matcherResults) {
// this event has been processed.
if (matcherResults[mIndex] != MatchingState::kNotComputed) {
return;
@@ -106,8 +126,8 @@ void CombinationLogMatchingTracker::onLogEvent(const LogEvent& event,
// evaluate children matchers if they haven't been evaluated.
for (const int childIndex : mChildren) {
if (matcherResults[childIndex] == MatchingState::kNotComputed) {
- const sp<LogMatchingTracker>& child = allTrackers[childIndex];
- child->onLogEvent(event, allTrackers, matcherResults);
+ const sp<AtomMatchingTracker>& child = allAtomMatchingTrackers[childIndex];
+ child->onLogEvent(event, allAtomMatchingTrackers, matcherResults);
}
}
diff --git a/cmds/statsd/src/matchers/CombinationLogMatchingTracker.h b/cmds/statsd/src/matchers/CombinationAtomMatchingTracker.h
index 55bc46059fc1..3160448b6c76 100644
--- a/cmds/statsd/src/matchers/CombinationLogMatchingTracker.h
+++ b/cmds/statsd/src/matchers/CombinationAtomMatchingTracker.h
@@ -13,12 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#ifndef COMBINATION_LOG_MATCHING_TRACKER_H
-#define COMBINATION_LOG_MATCHING_TRACKER_H
+#ifndef COMBINATION_ATOM_MATCHING_TRACKER_H
+#define COMBINATION_ATOM_MATCHING_TRACKER_H
#include <unordered_map>
#include <vector>
-#include "LogMatchingTracker.h"
+
+#include "AtomMatchingTracker.h"
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
namespace android {
@@ -26,28 +27,32 @@ namespace os {
namespace statsd {
// Represents a AtomMatcher_Combination in the StatsdConfig.
-class CombinationLogMatchingTracker : public virtual LogMatchingTracker {
+class CombinationAtomMatchingTracker : public AtomMatchingTracker {
public:
- CombinationLogMatchingTracker(const int64_t& id, const int index);
+ CombinationAtomMatchingTracker(const int64_t& id, const int index, const uint64_t protoHash);
+
+ bool init(const std::vector<AtomMatcher>& allAtomMatchers,
+ const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ const std::unordered_map<int64_t, int>& matcherMap, std::vector<bool>& stack);
- bool init(const std::vector<AtomMatcher>& allLogMatchers,
- const std::vector<sp<LogMatchingTracker>>& allTrackers,
- const std::unordered_map<int64_t, int>& matcherMap,
- std::vector<bool>& stack);
+ bool onConfigUpdated(const AtomMatcher& matcher, const int index,
+ const std::unordered_map<int64_t, int>& atomMatchingTrackerMap) override;
- ~CombinationLogMatchingTracker();
+ ~CombinationAtomMatchingTracker();
void onLogEvent(const LogEvent& event,
- const std::vector<sp<LogMatchingTracker>>& allTrackers,
+ const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
std::vector<MatchingState>& matcherResults) override;
private:
LogicalOperation mLogicalOperation;
std::vector<int> mChildren;
+
+ FRIEND_TEST(ConfigUpdateTest, TestUpdateMatchers);
};
} // namespace statsd
} // namespace os
} // namespace android
-#endif // COMBINATION_LOG_MATCHING_TRACKER_H
+#endif // COMBINATION_ATOM_MATCHING_TRACKER_H
diff --git a/cmds/statsd/src/matchers/EventMatcherWizard.h b/cmds/statsd/src/matchers/EventMatcherWizard.h
index 57ec2b35ba32..5d780f2423d8 100644
--- a/cmds/statsd/src/matchers/EventMatcherWizard.h
+++ b/cmds/statsd/src/matchers/EventMatcherWizard.h
@@ -16,7 +16,7 @@
#pragma once
-#include "LogMatchingTracker.h"
+#include "AtomMatchingTracker.h"
namespace android {
namespace os {
@@ -25,7 +25,7 @@ namespace statsd {
class EventMatcherWizard : public virtual android::RefBase {
public:
EventMatcherWizard(){}; // for testing
- EventMatcherWizard(const std::vector<sp<LogMatchingTracker>>& eventTrackers)
+ EventMatcherWizard(const std::vector<sp<AtomMatchingTracker>>& eventTrackers)
: mAllEventMatchers(eventTrackers){};
virtual ~EventMatcherWizard(){};
@@ -33,7 +33,7 @@ public:
MatchingState matchLogEvent(const LogEvent& event, int matcher_index);
private:
- std::vector<sp<LogMatchingTracker>> mAllEventMatchers;
+ std::vector<sp<AtomMatchingTracker>> mAllEventMatchers;
};
} // namespace statsd
diff --git a/cmds/statsd/src/matchers/LogMatchingTracker.h b/cmds/statsd/src/matchers/LogMatchingTracker.h
deleted file mode 100644
index 88ab4e6f683a..000000000000
--- a/cmds/statsd/src/matchers/LogMatchingTracker.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LOG_MATCHING_TRACKER_H
-#define LOG_MATCHING_TRACKER_H
-
-#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
-#include "logd/LogEvent.h"
-#include "matchers/matcher_util.h"
-
-#include <utils/RefBase.h>
-
-#include <set>
-#include <unordered_map>
-#include <vector>
-
-namespace android {
-namespace os {
-namespace statsd {
-
-class LogMatchingTracker : public virtual RefBase {
-public:
- LogMatchingTracker(const int64_t& id, const int index)
- : mId(id), mIndex(index), mInitialized(false){};
-
- virtual ~LogMatchingTracker(){};
-
- // Initialize this LogMatchingTracker.
- // allLogMatchers: the list of the AtomMatcher proto config. This is needed because we don't
- // store the proto object in memory. We only need it during initilization.
- // allTrackers: the list of the LogMatchingTracker objects. It's a one-to-one mapping with
- // allLogMatchers. This is needed because the initialization is done recursively
- // for CombinationLogMatchingTrackers using DFS.
- // stack: a bit map to record which matcher has been visited on the stack. This is for detecting
- // circle dependency.
- virtual bool init(const std::vector<AtomMatcher>& allLogMatchers,
- const std::vector<sp<LogMatchingTracker>>& allTrackers,
- const std::unordered_map<int64_t, int>& matcherMap,
- std::vector<bool>& stack) = 0;
-
- // Called when a log event comes.
- // event: the log event.
- // allTrackers: the list of all LogMatchingTrackers. This is needed because the log processing
- // is done recursively.
- // matcherResults: The cached results for all matchers for this event. Parent matchers can
- // directly access the children's matching results if they have been evaluated.
- // Otherwise, call children matchers' onLogEvent.
- virtual void onLogEvent(const LogEvent& event,
- const std::vector<sp<LogMatchingTracker>>& allTrackers,
- std::vector<MatchingState>& matcherResults) = 0;
-
- // Get the tagIds that this matcher cares about. The combined collection is stored
- // in MetricMananger, so that we can pass any LogEvents that are not interest of us. It uses
- // some memory but hopefully it can save us much CPU time when there is flood of events.
- virtual const std::set<int>& getAtomIds() const {
- return mAtomIds;
- }
-
- const int64_t& getId() const {
- return mId;
- }
-
-protected:
- // Name of this matching. We don't really need the name, but it makes log message easy to debug.
- const int64_t mId;
-
- // Index of this LogMatchingTracker in MetricsManager's container.
- const int mIndex;
-
- // Whether this LogMatchingTracker has been properly initialized.
- bool mInitialized;
-
- // The collection of the event tag ids that this LogMatchingTracker cares. So we can quickly
- // return kNotMatched when we receive an event with an id not in the list. This is especially
- // useful when we have a complex CombinationLogMatcherTracker.
- std::set<int> mAtomIds;
-};
-
-} // namespace statsd
-} // namespace os
-} // namespace android
-
-#endif // LOG_MATCHING_TRACKER_H
diff --git a/cmds/statsd/src/matchers/SimpleLogMatchingTracker.cpp b/cmds/statsd/src/matchers/SimpleAtomMatchingTracker.cpp
index 082daf5a1916..423da5bd3cf8 100644
--- a/cmds/statsd/src/matchers/SimpleLogMatchingTracker.cpp
+++ b/cmds/statsd/src/matchers/SimpleAtomMatchingTracker.cpp
@@ -17,7 +17,7 @@
#define DEBUG false // STOPSHIP if true
#include "Log.h"
-#include "SimpleLogMatchingTracker.h"
+#include "SimpleAtomMatchingTracker.h"
namespace android {
namespace os {
@@ -26,11 +26,11 @@ namespace statsd {
using std::unordered_map;
using std::vector;
-
-SimpleLogMatchingTracker::SimpleLogMatchingTracker(const int64_t& id, const int index,
- const SimpleAtomMatcher& matcher,
- const UidMap& uidMap)
- : LogMatchingTracker(id, index), mMatcher(matcher), mUidMap(uidMap) {
+SimpleAtomMatchingTracker::SimpleAtomMatchingTracker(const int64_t& id, const int index,
+ const uint64_t protoHash,
+ const SimpleAtomMatcher& matcher,
+ const sp<UidMap>& uidMap)
+ : AtomMatchingTracker(id, index, protoHash), mMatcher(matcher), mUidMap(uidMap) {
if (!matcher.has_atom_id()) {
mInitialized = false;
} else {
@@ -39,20 +39,28 @@ SimpleLogMatchingTracker::SimpleLogMatchingTracker(const int64_t& id, const int
}
}
-SimpleLogMatchingTracker::~SimpleLogMatchingTracker() {
+SimpleAtomMatchingTracker::~SimpleAtomMatchingTracker() {
}
-bool SimpleLogMatchingTracker::init(const vector<AtomMatcher>& allLogMatchers,
- const vector<sp<LogMatchingTracker>>& allTrackers,
- const unordered_map<int64_t, int>& matcherMap,
- vector<bool>& stack) {
+bool SimpleAtomMatchingTracker::init(const vector<AtomMatcher>& allAtomMatchers,
+ const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ const unordered_map<int64_t, int>& matcherMap,
+ vector<bool>& stack) {
// no need to do anything.
return mInitialized;
}
-void SimpleLogMatchingTracker::onLogEvent(const LogEvent& event,
- const vector<sp<LogMatchingTracker>>& allTrackers,
- vector<MatchingState>& matcherResults) {
+bool SimpleAtomMatchingTracker::onConfigUpdated(
+ const AtomMatcher& matcher, const int index,
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap) {
+ mIndex = index;
+ // Do not need to update mMatcher since the matcher must be identical across the update.
+ return mInitialized;
+}
+
+void SimpleAtomMatchingTracker::onLogEvent(
+ const LogEvent& event, const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ vector<MatchingState>& matcherResults) {
if (matcherResults[mIndex] != MatchingState::kNotComputed) {
VLOG("Matcher %lld already evaluated ", (long long)mId);
return;
@@ -65,7 +73,7 @@ void SimpleLogMatchingTracker::onLogEvent(const LogEvent& event,
bool matched = matchesSimple(mUidMap, mMatcher, event);
matcherResults[mIndex] = matched ? MatchingState::kMatched : MatchingState::kNotMatched;
- VLOG("Stats SimpleLogMatcher %lld matched? %d", (long long)mId, matched);
+ VLOG("Stats SimpleAtomMatcher %lld matched? %d", (long long)mId, matched);
}
} // namespace statsd
diff --git a/cmds/statsd/src/matchers/SimpleLogMatchingTracker.h b/cmds/statsd/src/matchers/SimpleAtomMatchingTracker.h
index a0f6a888bd44..b67e6c20e8f1 100644
--- a/cmds/statsd/src/matchers/SimpleLogMatchingTracker.h
+++ b/cmds/statsd/src/matchers/SimpleAtomMatchingTracker.h
@@ -14,12 +14,13 @@
* limitations under the License.
*/
-#ifndef SIMPLE_LOG_MATCHING_TRACKER_H
-#define SIMPLE_LOG_MATCHING_TRACKER_H
+#ifndef SIMPLE_ATOM_MATCHING_TRACKER_H
+#define SIMPLE_ATOM_MATCHING_TRACKER_H
#include <unordered_map>
#include <vector>
-#include "LogMatchingTracker.h"
+
+#include "AtomMatchingTracker.h"
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
#include "packages/UidMap.h"
@@ -27,29 +28,31 @@ namespace android {
namespace os {
namespace statsd {
-class SimpleLogMatchingTracker : public virtual LogMatchingTracker {
+class SimpleAtomMatchingTracker : public AtomMatchingTracker {
public:
- SimpleLogMatchingTracker(const int64_t& id, const int index,
- const SimpleAtomMatcher& matcher,
- const UidMap& uidMap);
+ SimpleAtomMatchingTracker(const int64_t& id, const int index, const uint64_t protoHash,
+ const SimpleAtomMatcher& matcher, const sp<UidMap>& uidMap);
- ~SimpleLogMatchingTracker();
+ ~SimpleAtomMatchingTracker();
- bool init(const std::vector<AtomMatcher>& allLogMatchers,
- const std::vector<sp<LogMatchingTracker>>& allTrackers,
+ bool init(const std::vector<AtomMatcher>& allAtomMatchers,
+ const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
const std::unordered_map<int64_t, int>& matcherMap,
std::vector<bool>& stack) override;
+ bool onConfigUpdated(const AtomMatcher& matcher, const int index,
+ const std::unordered_map<int64_t, int>& atomMatchingTrackerMap) override;
+
void onLogEvent(const LogEvent& event,
- const std::vector<sp<LogMatchingTracker>>& allTrackers,
+ const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
std::vector<MatchingState>& matcherResults) override;
private:
const SimpleAtomMatcher mMatcher;
- const UidMap& mUidMap;
+ const sp<UidMap> mUidMap;
};
} // namespace statsd
} // namespace os
} // namespace android
-#endif // SIMPLE_LOG_MATCHING_TRACKER_H
+#endif // SIMPLE_ATOM_MATCHING_TRACKER_H
diff --git a/cmds/statsd/src/matchers/matcher_util.cpp b/cmds/statsd/src/matchers/matcher_util.cpp
index 2b4c6a3cbf1e..a7454c5d923b 100644
--- a/cmds/statsd/src/matchers/matcher_util.cpp
+++ b/cmds/statsd/src/matchers/matcher_util.cpp
@@ -17,7 +17,7 @@
#include "Log.h"
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
-#include "matchers/LogMatchingTracker.h"
+#include "matchers/AtomMatchingTracker.h"
#include "matchers/matcher_util.h"
#include "stats_util.h"
@@ -81,14 +81,15 @@ bool combinationMatch(const vector<int>& children, const LogicalOperation& opera
return matched;
}
-bool tryMatchString(const UidMap& uidMap, const FieldValue& fieldValue, const string& str_match) {
+bool tryMatchString(const sp<UidMap>& uidMap, const FieldValue& fieldValue,
+ const string& str_match) {
if (isAttributionUidField(fieldValue) || isUidField(fieldValue)) {
int uid = fieldValue.mValue.int_value;
auto aidIt = UidMap::sAidToUidMapping.find(str_match);
if (aidIt != UidMap::sAidToUidMapping.end()) {
return ((int)aidIt->second) == uid;
}
- std::set<string> packageNames = uidMap.getAppNamesFromUid(uid, true /* normalize*/);
+ std::set<string> packageNames = uidMap->getAppNamesFromUid(uid, true /* normalize*/);
return packageNames.find(str_match) != packageNames.end();
} else if (fieldValue.mValue.getType() == STRING) {
return fieldValue.mValue.str_value == str_match;
@@ -96,7 +97,7 @@ bool tryMatchString(const UidMap& uidMap, const FieldValue& fieldValue, const st
return false;
}
-bool matchesSimple(const UidMap& uidMap, const FieldValueMatcher& matcher,
+bool matchesSimple(const sp<UidMap>& uidMap, const FieldValueMatcher& matcher,
const vector<FieldValue>& values, int start, int end, int depth) {
if (depth > 2) {
ALOGE("Depth > 3 not supported");
@@ -353,7 +354,7 @@ bool matchesSimple(const UidMap& uidMap, const FieldValueMatcher& matcher,
}
}
-bool matchesSimple(const UidMap& uidMap, const SimpleAtomMatcher& simpleMatcher,
+bool matchesSimple(const sp<UidMap>& uidMap, const SimpleAtomMatcher& simpleMatcher,
const LogEvent& event) {
if (event.GetTagId() != simpleMatcher.atom_id()) {
return false;
diff --git a/cmds/statsd/src/matchers/matcher_util.h b/cmds/statsd/src/matchers/matcher_util.h
index 1ab3e87b5fed..130b6068bd19 100644
--- a/cmds/statsd/src/matchers/matcher_util.h
+++ b/cmds/statsd/src/matchers/matcher_util.h
@@ -36,8 +36,8 @@ enum MatchingState {
bool combinationMatch(const std::vector<int>& children, const LogicalOperation& operation,
const std::vector<MatchingState>& matcherResults);
-bool matchesSimple(const UidMap& uidMap,
- const SimpleAtomMatcher& simpleMatcher, const LogEvent& wrapper);
+bool matchesSimple(const sp<UidMap>& uidMap, const SimpleAtomMatcher& simpleMatcher,
+ const LogEvent& wrapper);
} // namespace statsd
} // namespace os
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp
index 573961276e5b..3dbb6ed47ff8 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp
@@ -69,13 +69,14 @@ const int FIELD_ID_END_BUCKET_ELAPSED_MILLIS = 6;
CountMetricProducer::CountMetricProducer(
const ConfigKey& key, const CountMetric& metric, const int conditionIndex,
const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard,
- const int64_t timeBaseNs, const int64_t startTimeNs,
+ const uint64_t protoHash, const int64_t timeBaseNs, const int64_t startTimeNs,
const unordered_map<int, shared_ptr<Activation>>& eventActivationMap,
const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap,
const vector<int>& slicedStateAtoms,
const unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap)
: MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, initialConditionCache, wizard,
- eventActivationMap, eventDeactivationMap, slicedStateAtoms, stateGroupMap) {
+ protoHash, eventActivationMap, eventDeactivationMap, slicedStateAtoms,
+ stateGroupMap) {
if (metric.has_bucket()) {
mBucketSizeNs =
TimeUnitToBucketSizeInMillisGuardrailed(key.GetUid(), metric.bucket()) * 1000000;
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.h b/cmds/statsd/src/metrics/CountMetricProducer.h
index f05fb061ccc1..6b2f2ca61ecc 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.h
+++ b/cmds/statsd/src/metrics/CountMetricProducer.h
@@ -44,7 +44,7 @@ public:
CountMetricProducer(
const ConfigKey& key, const CountMetric& countMetric, const int conditionIndex,
const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard,
- const int64_t timeBaseNs, const int64_t startTimeNs,
+ const uint64_t protoHash, const int64_t timeBaseNs, const int64_t startTimeNs,
const std::unordered_map<int, std::shared_ptr<Activation>>& eventActivationMap = {},
const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>&
eventDeactivationMap = {},
@@ -57,6 +57,10 @@ public:
const HashableDimensionKey& primaryKey, const FieldValue& oldState,
const FieldValue& newState) override;
+ MetricType getMetricType() const override {
+ return METRIC_TYPE_COUNT;
+ }
+
protected:
void onMatchedLogEventInternalLocked(
const size_t matcherIndex, const MetricDimensionKey& eventKey,
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index e9b043876d3d..3acafaa3560e 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -66,14 +66,15 @@ DurationMetricProducer::DurationMetricProducer(
const ConfigKey& key, const DurationMetric& metric, const int conditionIndex,
const vector<ConditionState>& initialConditionCache, const size_t startIndex,
const size_t stopIndex, const size_t stopAllIndex, const bool nesting,
- const sp<ConditionWizard>& wizard, const FieldMatcher& internalDimensions,
- const int64_t timeBaseNs, const int64_t startTimeNs,
+ const sp<ConditionWizard>& wizard, const uint64_t protoHash,
+ const FieldMatcher& internalDimensions, const int64_t timeBaseNs, const int64_t startTimeNs,
const unordered_map<int, shared_ptr<Activation>>& eventActivationMap,
const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap,
const vector<int>& slicedStateAtoms,
const unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap)
: MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, initialConditionCache, wizard,
- eventActivationMap, eventDeactivationMap, slicedStateAtoms, stateGroupMap),
+ protoHash, eventActivationMap, eventDeactivationMap, slicedStateAtoms,
+ stateGroupMap),
mAggregationType(metric.aggregation_type()),
mStartIndex(startIndex),
mStopIndex(stopIndex),
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h
index bfe1010c89de..3a94d9c775aa 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.h
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.h
@@ -42,8 +42,9 @@ public:
const ConfigKey& key, const DurationMetric& durationMetric, const int conditionIndex,
const vector<ConditionState>& initialConditionCache, const size_t startIndex,
const size_t stopIndex, const size_t stopAllIndex, const bool nesting,
- const sp<ConditionWizard>& wizard, const FieldMatcher& internalDimensions,
- const int64_t timeBaseNs, const int64_t startTimeNs,
+ const sp<ConditionWizard>& wizard, const uint64_t protoHash,
+ const FieldMatcher& internalDimensions, const int64_t timeBaseNs,
+ const int64_t startTimeNs,
const unordered_map<int, shared_ptr<Activation>>& eventActivationMap = {},
const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap = {},
const vector<int>& slicedStateAtoms = {},
@@ -58,6 +59,10 @@ public:
const HashableDimensionKey& primaryKey, const FieldValue& oldState,
const FieldValue& newState) override;
+ MetricType getMetricType() const override {
+ return METRIC_TYPE_DURATION;
+ }
+
protected:
void onMatchedLogEventLocked(const size_t matcherIndex, const LogEvent& event) override;
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.cpp b/cmds/statsd/src/metrics/EventMetricProducer.cpp
index dc0036a687f3..dfe4559b05fb 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/EventMetricProducer.cpp
@@ -55,13 +55,14 @@ const int FIELD_ID_ATOMS = 2;
EventMetricProducer::EventMetricProducer(
const ConfigKey& key, const EventMetric& metric, const int conditionIndex,
const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard,
- const int64_t startTimeNs,
+ const uint64_t protoHash, const int64_t startTimeNs,
const unordered_map<int, shared_ptr<Activation>>& eventActivationMap,
const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap,
const vector<int>& slicedStateAtoms,
const unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap)
: MetricProducer(metric.id(), key, startTimeNs, conditionIndex, initialConditionCache, wizard,
- eventActivationMap, eventDeactivationMap, slicedStateAtoms, stateGroupMap) {
+ protoHash, eventActivationMap, eventDeactivationMap, slicedStateAtoms,
+ stateGroupMap) {
if (metric.links().size() > 0) {
for (const auto& link : metric.links()) {
Metric2Condition mc;
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.h b/cmds/statsd/src/metrics/EventMetricProducer.h
index bfb2de36fad4..e828dddcbb18 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.h
+++ b/cmds/statsd/src/metrics/EventMetricProducer.h
@@ -36,7 +36,7 @@ public:
EventMetricProducer(
const ConfigKey& key, const EventMetric& eventMetric, const int conditionIndex,
const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard,
- const int64_t startTimeNs,
+ const uint64_t protoHash, const int64_t startTimeNs,
const std::unordered_map<int, std::shared_ptr<Activation>>& eventActivationMap = {},
const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>&
eventDeactivationMap = {},
@@ -45,6 +45,10 @@ public:
virtual ~EventMetricProducer();
+ MetricType getMetricType() const override {
+ return METRIC_TYPE_EVENT;
+ }
+
private:
void onMatchedLogEventInternalLocked(
const size_t matcherIndex, const MetricDimensionKey& eventKey,
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 020f4b638f4d..9dda248a6d1f 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -71,13 +71,14 @@ const int FIELD_ID_END_BUCKET_ELAPSED_MILLIS = 8;
GaugeMetricProducer::GaugeMetricProducer(
const ConfigKey& key, const GaugeMetric& metric, const int conditionIndex,
const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard,
- const int whatMatcherIndex, const sp<EventMatcherWizard>& matcherWizard,
- const int pullTagId, const int triggerAtomId, const int atomId, const int64_t timeBaseNs,
- const int64_t startTimeNs, const sp<StatsPullerManager>& pullerManager,
+ const uint64_t protoHash, const int whatMatcherIndex,
+ const sp<EventMatcherWizard>& matcherWizard, const int pullTagId, const int triggerAtomId,
+ const int atomId, const int64_t timeBaseNs, const int64_t startTimeNs,
+ const sp<StatsPullerManager>& pullerManager,
const unordered_map<int, shared_ptr<Activation>>& eventActivationMap,
const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap)
: MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, initialConditionCache, wizard,
- eventActivationMap, eventDeactivationMap, /*slicedStateAtoms=*/{},
+ protoHash, eventActivationMap, eventDeactivationMap, /*slicedStateAtoms=*/{},
/*stateGroupMap=*/{}),
mWhatMatcherIndex(whatMatcherIndex),
mEventMatcherWizard(matcherWizard),
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index 2fc772b6b641..e933d4b19716 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -59,10 +59,11 @@ public:
GaugeMetricProducer(
const ConfigKey& key, const GaugeMetric& gaugeMetric, const int conditionIndex,
const vector<ConditionState>& initialConditionCache,
- const sp<ConditionWizard>& conditionWizard, const int whatMatcherIndex,
- const sp<EventMatcherWizard>& matcherWizard, const int pullTagId,
- const int triggerAtomId, const int atomId, const int64_t timeBaseNs,
- const int64_t startTimeNs, const sp<StatsPullerManager>& pullerManager,
+ const sp<ConditionWizard>& conditionWizard, const uint64_t protoHash,
+ const int whatMatcherIndex, const sp<EventMatcherWizard>& matcherWizard,
+ const int pullTagId, const int triggerAtomId, const int atomId,
+ const int64_t timeBaseNs, const int64_t startTimeNs,
+ const sp<StatsPullerManager>& pullerManager,
const std::unordered_map<int, std::shared_ptr<Activation>>& eventActivationMap = {},
const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>&
eventDeactivationMap = {});
@@ -96,6 +97,10 @@ public:
}
};
+ MetricType getMetricType() const override {
+ return METRIC_TYPE_GAUGE;
+ }
+
protected:
void onMatchedLogEventInternalLocked(
const size_t matcherIndex, const MetricDimensionKey& eventKey,
@@ -170,14 +175,14 @@ private:
// for each slice with the latest value.
void updateCurrentSlicedBucketForAnomaly();
- // Whitelist of fields to report. Empty means all are reported.
+ // Allowlist of fields to report. Empty means all are reported.
std::vector<Matcher> mFieldMatchers;
GaugeMetric::SamplingType mSamplingType;
const int64_t mMaxPullDelayNs;
- // apply a whitelist on the original input
+ // apply an allowlist on the original input
std::shared_ptr<vector<FieldValue>> getGaugeFields(const LogEvent& event);
// Util function to check whether the specified dimension hits the guardrail.
diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp
index fe143e496373..c1c1d20f00e2 100644
--- a/cmds/statsd/src/metrics/MetricProducer.cpp
+++ b/cmds/statsd/src/metrics/MetricProducer.cpp
@@ -46,13 +46,14 @@ const int FIELD_ID_ACTIVE_EVENT_ACTIVATION_STATE = 3;
MetricProducer::MetricProducer(
const int64_t& metricId, const ConfigKey& key, const int64_t timeBaseNs,
const int conditionIndex, const vector<ConditionState>& initialConditionCache,
- const sp<ConditionWizard>& wizard,
+ const sp<ConditionWizard>& wizard, const uint64_t protoHash,
const std::unordered_map<int, std::shared_ptr<Activation>>& eventActivationMap,
const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>&
eventDeactivationMap,
const vector<int>& slicedStateAtoms,
const unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap)
: mMetricId(metricId),
+ mProtoHash(protoHash),
mConfigKey(key),
mTimeBaseNs(timeBaseNs),
mCurrentBucketStartTimeNs(timeBaseNs),
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index be4cd6724bb1..bb590aac54d6 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -87,6 +87,13 @@ enum BucketDropReason {
NO_DATA = 9
};
+enum MetricType {
+ METRIC_TYPE_EVENT = 1,
+ METRIC_TYPE_COUNT = 2,
+ METRIC_TYPE_DURATION = 3,
+ METRIC_TYPE_GAUGE = 4,
+ METRIC_TYPE_VALUE = 5,
+};
struct Activation {
Activation(const ActivationType& activationType, const int64_t ttlNs)
: ttl_ns(ttlNs),
@@ -130,7 +137,7 @@ class MetricProducer : public virtual android::RefBase, public virtual StateList
public:
MetricProducer(const int64_t& metricId, const ConfigKey& key, const int64_t timeBaseNs,
const int conditionIndex, const vector<ConditionState>& initialConditionCache,
- const sp<ConditionWizard>& wizard,
+ const sp<ConditionWizard>& wizard, const uint64_t protoHash,
const std::unordered_map<int, std::shared_ptr<Activation>>& eventActivationMap,
const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>&
eventDeactivationMap,
@@ -259,10 +266,16 @@ public:
int64_t currentTimeNs, const DumpReportReason reason, ProtoOutputStream* proto);
// Start: getters/setters
- inline const int64_t& getMetricId() const {
+ inline int64_t getMetricId() const {
return mMetricId;
}
+ inline uint64_t getProtoHash() const {
+ return mProtoHash;
+ }
+
+ virtual MetricType getMetricType() const = 0;
+
// For test only.
inline int64_t getCurrentBucketNum() const {
return mCurrentBucketNum;
@@ -400,6 +413,10 @@ protected:
const int64_t mMetricId;
+ // Hash of the Metric's proto bytes from StatsdConfig, including any activations.
+ // Used to determine if the definition of this metric has changed across a config update.
+ const uint64_t mProtoHash;
+
const ConfigKey mConfigKey;
// The time when this metric producer was first created. The end time for the current bucket
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index 60de1a24cce5..39806890c42d 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -24,9 +24,10 @@
#include "condition/CombinationConditionTracker.h"
#include "condition/SimpleConditionTracker.h"
#include "guardrail/StatsdStats.h"
-#include "matchers/CombinationLogMatchingTracker.h"
-#include "matchers/SimpleLogMatchingTracker.h"
-#include "metrics_manager_util.h"
+#include "matchers/CombinationAtomMatchingTracker.h"
+#include "matchers/SimpleAtomMatchingTracker.h"
+#include "parsing_utils/config_update_utils.h"
+#include "parsing_utils/metrics_manager_util.h"
#include "state/StateManager.h"
#include "stats_log_util.h"
#include "stats_util.h"
@@ -77,12 +78,13 @@ MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config,
refreshTtl(timeBaseNs);
mConfigValid = initStatsdConfig(
- key, config, *uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
- timeBaseNs, currentTimeNs, mTagIds, mAllAtomMatchers, mAllConditionTrackers,
- mAllMetricProducers, mAllAnomalyTrackers, mAllPeriodicAlarmTrackers,
- mConditionToMetricMap, mTrackerToMetricMap, mTrackerToConditionMap,
- mActivationAtomTrackerToMetricMap, mDeactivationAtomTrackerToMetricMap,
- mAlertTrackerMap, mMetricIndexesWithActivation, mNoReportMetricIds);
+ key, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
+ timeBaseNs, currentTimeNs, mTagIds, mAllAtomMatchingTrackers, mAtomMatchingTrackerMap,
+ mAllConditionTrackers, mConditionTrackerMap, mAllMetricProducers, mMetricProducerMap,
+ mAllAnomalyTrackers, mAllPeriodicAlarmTrackers, mConditionToMetricMap,
+ mTrackerToMetricMap, mTrackerToConditionMap, mActivationAtomTrackerToMetricMap,
+ mDeactivationAtomTrackerToMetricMap, mAlertTrackerMap, mMetricIndexesWithActivation,
+ mStateProtoHashes, mNoReportMetricIds);
mHashStringsInReport = config.hash_strings_in_metric_report();
mVersionStringsInReport = config.version_strings_in_metric_report();
@@ -91,7 +93,7 @@ MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config,
// Init allowed pushed atom uids.
if (config.allowed_log_source_size() == 0) {
mConfigValid = false;
- ALOGE("Log source whitelist is empty! This config won't get any data. Suggest adding at "
+ ALOGE("Log source allowlist is empty! This config won't get any data. Suggest adding at "
"least AID_SYSTEM and AID_STATSD to the allowed_log_source field.");
} else {
for (const auto& source : config.allowed_log_source()) {
@@ -153,7 +155,7 @@ MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config,
// Guardrail. Reject the config if it's too big.
if (mAllMetricProducers.size() > StatsdStats::kMaxMetricCountPerConfig ||
mAllConditionTrackers.size() > StatsdStats::kMaxConditionCountPerConfig ||
- mAllAtomMatchers.size() > StatsdStats::kMaxMatcherCountPerConfig) {
+ mAllAtomMatchingTrackers.size() > StatsdStats::kMaxMatcherCountPerConfig) {
ALOGE("This config is too big! Reject!");
mConfigValid = false;
}
@@ -173,8 +175,9 @@ MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config,
// no matter whether this config is valid, log it in the stats.
StatsdStats::getInstance().noteConfigReceived(
- key, mAllMetricProducers.size(), mAllConditionTrackers.size(), mAllAtomMatchers.size(),
- mAllAnomalyTrackers.size(), mAnnotations, mConfigValid);
+ key, mAllMetricProducers.size(), mAllConditionTrackers.size(),
+ mAllAtomMatchingTrackers.size(), mAllAnomalyTrackers.size(), mAnnotations,
+ mConfigValid);
// Check active
for (const auto& metric : mAllMetricProducers) {
if (metric->isActive()) {
@@ -195,6 +198,29 @@ MetricsManager::~MetricsManager() {
VLOG("~MetricsManager()");
}
+bool MetricsManager::updateConfig(const StatsdConfig& config, const int64_t timeBaseNs,
+ const int64_t currentTimeNs,
+ const sp<AlarmMonitor>& anomalyAlarmMonitor,
+ const sp<AlarmMonitor>& periodicAlarmMonitor) {
+ vector<sp<AtomMatchingTracker>> newAtomMatchingTrackers;
+ unordered_map<int64_t, int> newAtomMatchingTrackerMap;
+ vector<sp<ConditionTracker>> newConditionTrackers;
+ unordered_map<int64_t, int> newConditionTrackerMap;
+ mTagIds.clear();
+ mTrackerToConditionMap.clear();
+ mConfigValid = updateStatsdConfig(
+ mConfigKey, config, mUidMap, mPullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
+ timeBaseNs, currentTimeNs, mAllAtomMatchingTrackers, mAtomMatchingTrackerMap,
+ mAllConditionTrackers, mConditionTrackerMap, mTagIds, newAtomMatchingTrackers,
+ newAtomMatchingTrackerMap, newConditionTrackers, newConditionTrackerMap,
+ mTrackerToConditionMap);
+ mAllAtomMatchingTrackers = newAtomMatchingTrackers;
+ mAtomMatchingTrackerMap = newAtomMatchingTrackerMap;
+ mAllConditionTrackers = newConditionTrackers;
+ mConditionTrackerMap = newConditionTrackerMap;
+ return mConfigValid;
+}
+
void MetricsManager::initLogSourceWhiteList() {
std::lock_guard<std::mutex> lock(mAllowedLogSourcesMutex);
mAllowedLogSources.clear();
@@ -484,11 +510,12 @@ void MetricsManager::onLogEvent(const LogEvent& event) {
return;
}
- vector<MatchingState> matcherCache(mAllAtomMatchers.size(), MatchingState::kNotComputed);
+ vector<MatchingState> matcherCache(mAllAtomMatchingTrackers.size(),
+ MatchingState::kNotComputed);
// Evaluate all atom matchers.
- for (auto& matcher : mAllAtomMatchers) {
- matcher->onLogEvent(event, mAllAtomMatchers, matcherCache);
+ for (auto& matcher : mAllAtomMatchingTrackers) {
+ matcher->onLogEvent(event, mAllAtomMatchingTrackers, matcherCache);
}
// Set of metrics that received an activation cancellation.
@@ -578,10 +605,10 @@ void MetricsManager::onLogEvent(const LogEvent& event) {
}
// For matched AtomMatchers, tell relevant metrics that a matched event has come.
- for (size_t i = 0; i < mAllAtomMatchers.size(); i++) {
+ for (size_t i = 0; i < mAllAtomMatchingTrackers.size(); i++) {
if (matcherCache[i] == MatchingState::kMatched) {
StatsdStats::getInstance().noteMatcherMatched(mConfigKey,
- mAllAtomMatchers[i]->getId());
+ mAllAtomMatchingTrackers[i]->getId());
auto pair = mTrackerToMetricMap.find(i);
if (pair != mTrackerToMetricMap.end()) {
auto& metricList = pair->second;
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index ad30a88c5d19..27f3d51b07ce 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -25,7 +25,7 @@
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
#include "frameworks/base/cmds/statsd/src/statsd_metadata.pb.h"
#include "logd/LogEvent.h"
-#include "matchers/LogMatchingTracker.h"
+#include "matchers/AtomMatchingTracker.h"
#include "metrics/MetricProducer.h"
#include "packages/UidMap.h"
@@ -46,6 +46,10 @@ public:
virtual ~MetricsManager();
+ bool updateConfig(const StatsdConfig& config, const int64_t timeBaseNs,
+ const int64_t currentTimeNs, const sp<AlarmMonitor>& anomalyAlarmMonitor,
+ const sp<AlarmMonitor>& periodicAlarmMonitor);
+
// Return whether the configuration is valid.
bool isConfigValid() const;
@@ -213,7 +217,7 @@ private:
// All event tags that are interesting to my metrics.
std::set<int> mTagIds;
- // We only store the sp of LogMatchingTracker, MetricProducer, and ConditionTracker in
+ // We only store the sp of AtomMatchingTracker, MetricProducer, and ConditionTracker in
// MetricsManager. There are relationships between them, and the relationships are denoted by
// index instead of pointers. The reasons for this are: (1) the relationship between them are
// complicated, so storing index instead of pointers reduces the risk that A holds B's sp, and B
@@ -221,7 +225,7 @@ private:
// the related results from a cache using the index.
// Hold all the atom matchers from the config.
- std::vector<sp<LogMatchingTracker>> mAllAtomMatchers;
+ std::vector<sp<AtomMatchingTracker>> mAllAtomMatchingTrackers;
// Hold all the conditions from the config.
std::vector<sp<ConditionTracker>> mAllConditionTrackers;
@@ -235,23 +239,35 @@ private:
// Hold all periodic alarm trackers.
std::vector<sp<AlarmTracker>> mAllPeriodicAlarmTrackers;
+ // To make updating configs faster, we map the id of a AtomMatchingTracker, MetricProducer, and
+ // ConditionTracker to its index in the corresponding vector.
+
+ // Maps the id of an atom matching tracker to its index in mAllAtomMatchingTrackers.
+ std::unordered_map<int64_t, int> mAtomMatchingTrackerMap;
+
+ // Maps the id of a condition tracker to its index in mAllConditionTrackers.
+ std::unordered_map<int64_t, int> mConditionTrackerMap;
+
+ // Maps the id of a metric producer to its index in mAllMetricProducers.
+ std::unordered_map<int64_t, int> mMetricProducerMap;
+
// To make the log processing more efficient, we want to do as much filtering as possible
// before we go into individual trackers and conditions to match.
// 1st filter: check if the event tag id is in mTagIds.
// 2nd filter: if it is, we parse the event because there is at least one member is interested.
- // then pass to all LogMatchingTrackers (itself also filter events by ids).
- // 3nd filter: for LogMatchingTrackers that matched this event, we pass this event to the
+ // then pass to all AtomMatchingTrackers (itself also filter events by ids).
+ // 3nd filter: for AtomMatchingTrackers that matched this event, we pass this event to the
// ConditionTrackers and MetricProducers that use this matcher.
// 4th filter: for ConditionTrackers that changed value due to this event, we pass
// new conditions to metrics that use this condition.
// The following map is initialized from the statsd_config.
- // Maps from the index of the LogMatchingTracker to index of MetricProducer.
+ // Maps from the index of the AtomMatchingTracker to index of MetricProducer.
std::unordered_map<int, std::vector<int>> mTrackerToMetricMap;
- // Maps from LogMatchingTracker to ConditionTracker
+ // Maps from AtomMatchingTracker to ConditionTracker
std::unordered_map<int, std::vector<int>> mTrackerToConditionMap;
// Maps from ConditionTracker to MetricProducer
@@ -282,6 +298,9 @@ private:
// The config is always active if any metric in the config does not have an activation signal.
bool mIsAlwaysActive;
+ // Hashes of the States used in this config, keyed by the state id, used in config updates.
+ std::map<int64_t, uint64_t> mStateProtoHashes;
+
FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensions);
FRIEND_TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks);
FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSliceByFirstUid);
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index 5987a723a421..39ae9a47f2bf 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -79,16 +79,17 @@ const Value ZERO_DOUBLE((int64_t)0);
ValueMetricProducer::ValueMetricProducer(
const ConfigKey& key, const ValueMetric& metric, const int conditionIndex,
const vector<ConditionState>& initialConditionCache,
- const sp<ConditionWizard>& conditionWizard, const int whatMatcherIndex,
- const sp<EventMatcherWizard>& matcherWizard, const int pullTagId, const int64_t timeBaseNs,
- const int64_t startTimeNs, const sp<StatsPullerManager>& pullerManager,
+ const sp<ConditionWizard>& conditionWizard, const uint64_t protoHash,
+ const int whatMatcherIndex, const sp<EventMatcherWizard>& matcherWizard,
+ const int pullTagId, const int64_t timeBaseNs, const int64_t startTimeNs,
+ const sp<StatsPullerManager>& pullerManager,
const unordered_map<int, shared_ptr<Activation>>& eventActivationMap,
const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap,
const vector<int>& slicedStateAtoms,
const unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap)
: MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, initialConditionCache,
- conditionWizard, eventActivationMap, eventDeactivationMap, slicedStateAtoms,
- stateGroupMap),
+ conditionWizard, protoHash, eventActivationMap, eventDeactivationMap,
+ slicedStateAtoms, stateGroupMap),
mWhatMatcherIndex(whatMatcherIndex),
mEventMatcherWizard(matcherWizard),
mPullerManager(pullerManager),
@@ -411,7 +412,7 @@ void ValueMetricProducer::skipCurrentBucket(const int64_t dropTimeNs,
void ValueMetricProducer::resetBase() {
for (auto& slice : mCurrentBaseInfo) {
- for (auto& baseInfo : slice.second) {
+ for (auto& baseInfo : slice.second.baseInfos) {
baseInfo.hasBase = false;
}
}
@@ -623,7 +624,7 @@ void ValueMetricProducer::accumulateEvents(const std::vector<std::shared_ptr<Log
mMatchedMetricDimensionKeys.find(whatKey) != mMatchedMetricDimensionKeys.end();
if (!presentInPulledData && whatKey.contains(mStateChangePrimaryKey.second)) {
auto it = mCurrentBaseInfo.find(whatKey);
- for (auto& baseInfo : it->second) {
+ for (auto& baseInfo : it->second.baseInfos) {
baseInfo.hasBase = false;
}
}
@@ -652,7 +653,7 @@ void ValueMetricProducer::dumpStatesLocked(FILE* out, bool verbose) const {
(unsigned long)mCurrentSlicedBucket.size());
if (verbose) {
for (const auto& it : mCurrentSlicedBucket) {
- for (const auto& interval : it.second) {
+ for (const auto& interval : it.second.intervals) {
fprintf(out, "\t(what)%s\t(states)%s (value)%s\n",
it.first.getDimensionKeyInWhat().toString().c_str(),
it.first.getStateValuesKey().toString().c_str(),
@@ -733,6 +734,11 @@ bool getDoubleOrLong(const LogEvent& event, const Matcher& matcher, Value& ret)
return false;
}
+bool ValueMetricProducer::multipleBucketsSkipped(const int64_t numBucketsForward) {
+ // Skip buckets if this is a pulled metric or a pushed metric that is diffed.
+ return numBucketsForward > 1 && (mIsPulled || mUseDiff);
+}
+
void ValueMetricProducer::onMatchedLogEventInternalLocked(
const size_t matcherIndex, const MetricDimensionKey& eventKey,
const ConditionKey& conditionKey, bool condition, const LogEvent& event,
@@ -783,23 +789,23 @@ void ValueMetricProducer::onMatchedLogEventInternalLocked(
return;
}
- vector<BaseInfo>& baseInfos = mCurrentBaseInfo[whatKey];
+ DimensionsInWhatInfo& dimensionsInWhatInfo = mCurrentBaseInfo[whatKey];
+ vector<BaseInfo>& baseInfos = dimensionsInWhatInfo.baseInfos;
if (baseInfos.size() < mFieldMatchers.size()) {
VLOG("Resizing number of intervals to %d", (int)mFieldMatchers.size());
baseInfos.resize(mFieldMatchers.size());
}
- for (BaseInfo& baseInfo : baseInfos) {
- if (!baseInfo.hasCurrentState) {
- baseInfo.currentState = getUnknownStateKey();
- baseInfo.hasCurrentState = true;
- }
+ if (!dimensionsInWhatInfo.hasCurrentState) {
+ dimensionsInWhatInfo.currentState = getUnknownStateKey();
+ dimensionsInWhatInfo.hasCurrentState = true;
}
// We need to get the intervals stored with the previous state key so we can
// close these value intervals.
- const auto oldStateKey = baseInfos[0].currentState;
- vector<Interval>& intervals = mCurrentSlicedBucket[MetricDimensionKey(whatKey, oldStateKey)];
+ const auto oldStateKey = dimensionsInWhatInfo.currentState;
+ vector<Interval>& intervals =
+ mCurrentSlicedBucket[MetricDimensionKey(whatKey, oldStateKey)].intervals;
if (intervals.size() < mFieldMatchers.size()) {
VLOG("Resizing number of intervals to %d", (int)mFieldMatchers.size());
intervals.resize(mFieldMatchers.size());
@@ -813,14 +819,14 @@ void ValueMetricProducer::onMatchedLogEventInternalLocked(
// Discussion here: http://ag/6124370.
bool useAnomalyDetection = true;
+ dimensionsInWhatInfo.hasCurrentState = true;
+ dimensionsInWhatInfo.currentState = stateKey;
for (int i = 0; i < (int)mFieldMatchers.size(); i++) {
const Matcher& matcher = mFieldMatchers[i];
BaseInfo& baseInfo = baseInfos[i];
Interval& interval = intervals[i];
interval.valueIndex = i;
Value value;
- baseInfo.hasCurrentState = true;
- baseInfo.currentState = stateKey;
if (!getDoubleOrLong(event, matcher, value)) {
VLOG("Failed to get value %d from event %s", i, event.ToString().c_str());
StatsdStats::getInstance().noteBadValueType(mMetricId);
@@ -910,8 +916,9 @@ void ValueMetricProducer::onMatchedLogEventInternalLocked(
interval.sampleSize += 1;
}
- // Only trigger the tracker if all intervals are correct
- if (useAnomalyDetection) {
+ // Only trigger the tracker if all intervals are correct and we have not skipped the bucket due
+ // to MULTIPLE_BUCKETS_SKIPPED.
+ if (useAnomalyDetection && !multipleBucketsSkipped(calcBucketsForwardCount(eventTimeNs))) {
// TODO: propgate proper values down stream when anomaly support doubles
long wholeBucketVal = intervals[0].value.long_value;
auto prev = mCurrentFullBucket.find(eventKey);
@@ -961,9 +968,7 @@ void ValueMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs,
int64_t bucketEndTime = fullBucketEndTimeNs;
int64_t numBucketsForward = calcBucketsForwardCount(eventTimeNs);
- // Skip buckets if this is a pulled metric or a pushed metric that is diffed.
- if (numBucketsForward > 1 && (mIsPulled || mUseDiff)) {
-
+ if (multipleBucketsSkipped(numBucketsForward)) {
VLOG("Skipping forward %lld buckets", (long long)numBucketsForward);
StatsdStats::getInstance().noteSkippedForwardBuckets(mMetricId);
// Something went wrong. Maybe the device was sleeping for a long time. It is better
@@ -986,7 +991,7 @@ void ValueMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs,
bool bucketHasData = false;
// The current bucket is large enough to keep.
for (const auto& slice : mCurrentSlicedBucket) {
- ValueBucket bucket = buildPartialBucket(bucketEndTime, slice.second);
+ PastValueBucket bucket = buildPartialBucket(bucketEndTime, slice.second.intervals);
bucket.mConditionTrueNs = conditionTrueDuration;
// it will auto create new vector of ValuebucketInfo if the key is not found.
if (bucket.valueIndex.size() > 0) {
@@ -1026,9 +1031,9 @@ void ValueMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs,
mCurrentBucketNum += numBucketsForward;
}
-ValueBucket ValueMetricProducer::buildPartialBucket(int64_t bucketEndTime,
- const std::vector<Interval>& intervals) {
- ValueBucket bucket;
+PastValueBucket ValueMetricProducer::buildPartialBucket(int64_t bucketEndTime,
+ const std::vector<Interval>& intervals) {
+ PastValueBucket bucket;
bucket.mBucketStartNs = mCurrentBucketStartTimeNs;
bucket.mBucketEndNs = bucketEndTime;
for (const auto& interval : intervals) {
@@ -1055,7 +1060,7 @@ void ValueMetricProducer::initCurrentSlicedBucket(int64_t nextBucketStartTimeNs)
// Cleanup data structure to aggregate values.
for (auto it = mCurrentSlicedBucket.begin(); it != mCurrentSlicedBucket.end();) {
bool obsolete = true;
- for (auto& interval : it->second) {
+ for (auto& interval : it->second.intervals) {
interval.hasValue = false;
interval.sampleSize = 0;
if (interval.seenNewData) {
@@ -1103,7 +1108,7 @@ void ValueMetricProducer::appendToFullBucket(const bool isFullBucketReached) {
continue;
}
// TODO: fix this when anomaly can accept double values
- auto& interval = slice.second[0];
+ auto& interval = slice.second.intervals[0];
if (interval.hasValue) {
mCurrentFullBucket[slice.first] += interval.value.long_value;
}
@@ -1122,7 +1127,7 @@ void ValueMetricProducer::appendToFullBucket(const bool isFullBucketReached) {
for (auto& tracker : mAnomalyTrackers) {
if (tracker != nullptr) {
// TODO: fix this when anomaly can accept double values
- auto& interval = slice.second[0];
+ auto& interval = slice.second.intervals[0];
if (interval.hasValue) {
tracker->addPastBucket(slice.first, interval.value.long_value,
mCurrentBucketNum);
@@ -1135,7 +1140,7 @@ void ValueMetricProducer::appendToFullBucket(const bool isFullBucketReached) {
// Accumulate partial bucket.
for (const auto& slice : mCurrentSlicedBucket) {
// TODO: fix this when anomaly can accept double values
- auto& interval = slice.second[0];
+ auto& interval = slice.second.intervals[0];
if (interval.hasValue) {
mCurrentFullBucket[slice.first] += interval.value.long_value;
}
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index b359af745c91..4b2599bdb517 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -31,7 +31,7 @@ namespace android {
namespace os {
namespace statsd {
-struct ValueBucket {
+struct PastValueBucket {
int64_t mBucketStartNs;
int64_t mBucketEndNs;
std::vector<int> valueIndex;
@@ -41,7 +41,6 @@ struct ValueBucket {
int64_t mConditionTrueNs;
};
-
// Aggregates values within buckets.
//
// There are different events that might complete a bucket
@@ -53,9 +52,9 @@ public:
ValueMetricProducer(
const ConfigKey& key, const ValueMetric& valueMetric, const int conditionIndex,
const vector<ConditionState>& initialConditionCache,
- const sp<ConditionWizard>& conditionWizard, const int whatMatcherIndex,
- const sp<EventMatcherWizard>& matcherWizard, const int pullTagId,
- const int64_t timeBaseNs, const int64_t startTimeNs,
+ const sp<ConditionWizard>& conditionWizard, const uint64_t protoHash,
+ const int whatMatcherIndex, const sp<EventMatcherWizard>& matcherWizard,
+ const int pullTagId, const int64_t timeBaseNs, const int64_t startTimeNs,
const sp<StatsPullerManager>& pullerManager,
const std::unordered_map<int, std::shared_ptr<Activation>>& eventActivationMap = {},
const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>&
@@ -93,6 +92,10 @@ public:
void onStateChanged(int64_t eventTimeNs, int32_t atomId, const HashableDimensionKey& primaryKey,
const FieldValue& oldState, const FieldValue& newState) override;
+ MetricType getMetricType() const override {
+ return METRIC_TYPE_VALUE;
+ }
+
protected:
void onMatchedLogEventInternalLocked(
const size_t matcherIndex, const MetricDimensionKey& eventKey,
@@ -173,7 +176,7 @@ private:
// if this is pulled metric
const bool mIsPulled;
- // internal state of an ongoing aggregation bucket.
+ // Tracks the value information of one value field.
typedef struct {
// Index in multi value aggregation.
int valueIndex;
@@ -188,25 +191,40 @@ private:
bool seenNewData = false;
} Interval;
+ // Internal state of an ongoing aggregation bucket.
+ typedef struct CurrentValueBucket {
+ // Value information for each value field of the metric.
+ std::vector<Interval> intervals;
+ } CurrentValueBucket;
+
+ // Holds base information for diffing values from one value field.
typedef struct {
// Holds current base value of the dimension. Take diff and update if necessary.
Value base;
// Whether there is a base to diff to.
bool hasBase;
+ } BaseInfo;
+
+ // State key and base information for a specific DimensionsInWhat key.
+ typedef struct {
+ std::vector<BaseInfo> baseInfos;
// Last seen state value(s).
HashableDimensionKey currentState;
// Whether this dimensions in what key has a current state key.
bool hasCurrentState;
- } BaseInfo;
+ } DimensionsInWhatInfo;
- std::unordered_map<MetricDimensionKey, std::vector<Interval>> mCurrentSlicedBucket;
+ // Tracks the internal state in the ongoing aggregation bucket for each DimensionsInWhat
+ // key and StateValuesKey pair.
+ std::unordered_map<MetricDimensionKey, CurrentValueBucket> mCurrentSlicedBucket;
- std::unordered_map<HashableDimensionKey, std::vector<BaseInfo>> mCurrentBaseInfo;
+ // Tracks current state key and base information for each DimensionsInWhat key.
+ std::unordered_map<HashableDimensionKey, DimensionsInWhatInfo> mCurrentBaseInfo;
std::unordered_map<MetricDimensionKey, int64_t> mCurrentFullBucket;
// Save the past buckets and we can clear when the StatsLogReport is dumped.
- std::unordered_map<MetricDimensionKey, std::vector<ValueBucket>> mPastBuckets;
+ std::unordered_map<MetricDimensionKey, std::vector<PastValueBucket>> mPastBuckets;
const int64_t mMinBucketSizeNs;
@@ -219,11 +237,13 @@ private:
void pullAndMatchEventsLocked(const int64_t timestampNs);
+ bool multipleBucketsSkipped(const int64_t numBucketsForward);
+
void accumulateEvents(const std::vector<std::shared_ptr<LogEvent>>& allData,
int64_t originalPullTimeNs, int64_t eventElapsedTimeNs);
- ValueBucket buildPartialBucket(int64_t bucketEndTime,
- const std::vector<Interval>& intervals);
+ PastValueBucket buildPartialBucket(int64_t bucketEndTime,
+ const std::vector<Interval>& intervals);
void initCurrentSlicedBucket(int64_t nextBucketStartTimeNs);
@@ -232,7 +252,7 @@ private:
// Reset diff base and mHasGlobalBase
void resetBase();
- static const size_t kBucketSize = sizeof(ValueBucket{});
+ static const size_t kBucketSize = sizeof(PastValueBucket{});
const size_t mDimensionSoftLimit;
diff --git a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp
new file mode 100644
index 000000000000..bd60b6bfcb8e
--- /dev/null
+++ b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp
@@ -0,0 +1,438 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define DEBUG false // STOPSHIP if true
+#include "Log.h"
+
+#include "config_update_utils.h"
+
+#include "external/StatsPullerManager.h"
+#include "hash.h"
+#include "metrics_manager_util.h"
+
+namespace android {
+namespace os {
+namespace statsd {
+
+// Recursive function to determine if a matcher needs to be updated. Populates matcherToUpdate.
+// Returns whether the function was successful or not.
+bool determineMatcherUpdateStatus(const StatsdConfig& config, const int matcherIdx,
+ const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers,
+ const unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ vector<UpdateStatus>& matchersToUpdate,
+ vector<bool>& cycleTracker) {
+ // Have already examined this matcher.
+ if (matchersToUpdate[matcherIdx] != UPDATE_UNKNOWN) {
+ return true;
+ }
+
+ const AtomMatcher& matcher = config.atom_matcher(matcherIdx);
+ int64_t id = matcher.id();
+ // Check if new matcher.
+ const auto& oldAtomMatchingTrackerIt = oldAtomMatchingTrackerMap.find(id);
+ if (oldAtomMatchingTrackerIt == oldAtomMatchingTrackerMap.end()) {
+ matchersToUpdate[matcherIdx] = UPDATE_NEW;
+ return true;
+ }
+
+ // This is an existing matcher. Check if it has changed.
+ string serializedMatcher;
+ if (!matcher.SerializeToString(&serializedMatcher)) {
+ ALOGE("Unable to serialize matcher %lld", (long long)id);
+ return false;
+ }
+ uint64_t newProtoHash = Hash64(serializedMatcher);
+ if (newProtoHash != oldAtomMatchingTrackers[oldAtomMatchingTrackerIt->second]->getProtoHash()) {
+ matchersToUpdate[matcherIdx] = UPDATE_REPLACE;
+ return true;
+ }
+
+ switch (matcher.contents_case()) {
+ case AtomMatcher::ContentsCase::kSimpleAtomMatcher: {
+ matchersToUpdate[matcherIdx] = UPDATE_PRESERVE;
+ return true;
+ }
+ case AtomMatcher::ContentsCase::kCombination: {
+ // Recurse to check if children have changed.
+ cycleTracker[matcherIdx] = true;
+ UpdateStatus status = UPDATE_PRESERVE;
+ for (const int64_t childMatcherId : matcher.combination().matcher()) {
+ const auto& childIt = newAtomMatchingTrackerMap.find(childMatcherId);
+ if (childIt == newAtomMatchingTrackerMap.end()) {
+ ALOGW("Matcher %lld not found in the config", (long long)childMatcherId);
+ return false;
+ }
+ const int childIdx = childIt->second;
+ if (cycleTracker[childIdx]) {
+ ALOGE("Cycle detected in matcher config");
+ return false;
+ }
+ if (!determineMatcherUpdateStatus(
+ config, childIdx, oldAtomMatchingTrackerMap, oldAtomMatchingTrackers,
+ newAtomMatchingTrackerMap, matchersToUpdate, cycleTracker)) {
+ return false;
+ }
+
+ if (matchersToUpdate[childIdx] == UPDATE_REPLACE) {
+ status = UPDATE_REPLACE;
+ break;
+ }
+ }
+ matchersToUpdate[matcherIdx] = status;
+ cycleTracker[matcherIdx] = false;
+ return true;
+ }
+ default: {
+ ALOGE("Matcher \"%lld\" malformed", (long long)id);
+ return false;
+ }
+ }
+ return true;
+}
+
+bool updateAtomMatchingTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap,
+ const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers,
+ set<int>& allTagIds,
+ unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers,
+ set<int64_t>& replacedMatchers) {
+ const int atomMatcherCount = config.atom_matcher_size();
+
+ vector<AtomMatcher> matcherProtos;
+ matcherProtos.reserve(atomMatcherCount);
+ newAtomMatchingTrackers.reserve(atomMatcherCount);
+
+ // Maps matcher id to their position in the config. For fast lookup of dependencies.
+ for (int i = 0; i < atomMatcherCount; i++) {
+ const AtomMatcher& matcher = config.atom_matcher(i);
+ if (newAtomMatchingTrackerMap.find(matcher.id()) != newAtomMatchingTrackerMap.end()) {
+ ALOGE("Duplicate atom matcher found for id %lld", (long long)matcher.id());
+ return false;
+ }
+ newAtomMatchingTrackerMap[matcher.id()] = i;
+ matcherProtos.push_back(matcher);
+ }
+
+ // For combination matchers, we need to determine if any children need to be updated.
+ vector<UpdateStatus> matchersToUpdate(atomMatcherCount, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(atomMatcherCount, false);
+ for (int i = 0; i < atomMatcherCount; i++) {
+ if (!determineMatcherUpdateStatus(config, i, oldAtomMatchingTrackerMap,
+ oldAtomMatchingTrackers, newAtomMatchingTrackerMap,
+ matchersToUpdate, cycleTracker)) {
+ return false;
+ }
+ }
+
+ for (int i = 0; i < atomMatcherCount; i++) {
+ const AtomMatcher& matcher = config.atom_matcher(i);
+ const int64_t id = matcher.id();
+ switch (matchersToUpdate[i]) {
+ case UPDATE_PRESERVE: {
+ const auto& oldAtomMatchingTrackerIt = oldAtomMatchingTrackerMap.find(id);
+ if (oldAtomMatchingTrackerIt == oldAtomMatchingTrackerMap.end()) {
+ ALOGE("Could not find AtomMatcher %lld in the previous config, but expected it "
+ "to be there",
+ (long long)id);
+ return false;
+ }
+ const sp<AtomMatchingTracker>& tracker =
+ oldAtomMatchingTrackers[oldAtomMatchingTrackerIt->second];
+ if (!tracker->onConfigUpdated(matcherProtos[i], i, newAtomMatchingTrackerMap)) {
+ ALOGW("Config update failed for matcher %lld", (long long)id);
+ return false;
+ }
+ newAtomMatchingTrackers.push_back(tracker);
+ break;
+ }
+ case UPDATE_REPLACE:
+ replacedMatchers.insert(id);
+ [[fallthrough]]; // Intentionally fallthrough to create the new matcher.
+ case UPDATE_NEW: {
+ sp<AtomMatchingTracker> tracker = createAtomMatchingTracker(matcher, i, uidMap);
+ if (tracker == nullptr) {
+ return false;
+ }
+ newAtomMatchingTrackers.push_back(tracker);
+ break;
+ }
+ default: {
+ ALOGE("Matcher \"%lld\" update state is unknown. This should never happen",
+ (long long)id);
+ return false;
+ }
+ }
+ }
+
+ std::fill(cycleTracker.begin(), cycleTracker.end(), false);
+ for (auto& matcher : newAtomMatchingTrackers) {
+ if (!matcher->init(matcherProtos, newAtomMatchingTrackers, newAtomMatchingTrackerMap,
+ cycleTracker)) {
+ return false;
+ }
+ // Collect all the tag ids that are interesting. TagIds exist in leaf nodes only.
+ const set<int>& tagIds = matcher->getAtomIds();
+ allTagIds.insert(tagIds.begin(), tagIds.end());
+ }
+
+ return true;
+}
+
+// Recursive function to determine if a condition needs to be updated. Populates conditionsToUpdate.
+// Returns whether the function was successful or not.
+bool determineConditionUpdateStatus(const StatsdConfig& config, const int conditionIdx,
+ const unordered_map<int64_t, int>& oldConditionTrackerMap,
+ const vector<sp<ConditionTracker>>& oldConditionTrackers,
+ const unordered_map<int64_t, int>& newConditionTrackerMap,
+ const set<int64_t>& replacedMatchers,
+ vector<UpdateStatus>& conditionsToUpdate,
+ vector<bool>& cycleTracker) {
+ // Have already examined this condition.
+ if (conditionsToUpdate[conditionIdx] != UPDATE_UNKNOWN) {
+ return true;
+ }
+
+ const Predicate& predicate = config.predicate(conditionIdx);
+ int64_t id = predicate.id();
+ // Check if new condition.
+ const auto& oldConditionTrackerIt = oldConditionTrackerMap.find(id);
+ if (oldConditionTrackerIt == oldConditionTrackerMap.end()) {
+ conditionsToUpdate[conditionIdx] = UPDATE_NEW;
+ return true;
+ }
+
+ // This is an existing condition. Check if it has changed.
+ string serializedCondition;
+ if (!predicate.SerializeToString(&serializedCondition)) {
+ ALOGE("Unable to serialize matcher %lld", (long long)id);
+ return false;
+ }
+ uint64_t newProtoHash = Hash64(serializedCondition);
+ if (newProtoHash != oldConditionTrackers[oldConditionTrackerIt->second]->getProtoHash()) {
+ conditionsToUpdate[conditionIdx] = UPDATE_REPLACE;
+ return true;
+ }
+
+ switch (predicate.contents_case()) {
+ case Predicate::ContentsCase::kSimplePredicate: {
+ // Need to check if any of the underlying matchers changed.
+ const SimplePredicate& simplePredicate = predicate.simple_predicate();
+ if (simplePredicate.has_start()) {
+ if (replacedMatchers.find(simplePredicate.start()) != replacedMatchers.end()) {
+ conditionsToUpdate[conditionIdx] = UPDATE_REPLACE;
+ return true;
+ }
+ }
+ if (simplePredicate.has_stop()) {
+ if (replacedMatchers.find(simplePredicate.stop()) != replacedMatchers.end()) {
+ conditionsToUpdate[conditionIdx] = UPDATE_REPLACE;
+ return true;
+ }
+ }
+ if (simplePredicate.has_stop_all()) {
+ if (replacedMatchers.find(simplePredicate.stop_all()) != replacedMatchers.end()) {
+ conditionsToUpdate[conditionIdx] = UPDATE_REPLACE;
+ return true;
+ }
+ }
+ conditionsToUpdate[conditionIdx] = UPDATE_PRESERVE;
+ return true;
+ }
+ case Predicate::ContentsCase::kCombination: {
+ // Need to recurse on the children to see if any of the child predicates changed.
+ cycleTracker[conditionIdx] = true;
+ UpdateStatus status = UPDATE_PRESERVE;
+ for (const int64_t childPredicateId : predicate.combination().predicate()) {
+ const auto& childIt = newConditionTrackerMap.find(childPredicateId);
+ if (childIt == newConditionTrackerMap.end()) {
+ ALOGW("Predicate %lld not found in the config", (long long)childPredicateId);
+ return false;
+ }
+ const int childIdx = childIt->second;
+ if (cycleTracker[childIdx]) {
+ ALOGE("Cycle detected in predicate config");
+ return false;
+ }
+ if (!determineConditionUpdateStatus(config, childIdx, oldConditionTrackerMap,
+ oldConditionTrackers, newConditionTrackerMap,
+ replacedMatchers, conditionsToUpdate,
+ cycleTracker)) {
+ return false;
+ }
+
+ if (conditionsToUpdate[childIdx] == UPDATE_REPLACE) {
+ status = UPDATE_REPLACE;
+ break;
+ }
+ }
+ conditionsToUpdate[conditionIdx] = status;
+ cycleTracker[conditionIdx] = false;
+ return true;
+ }
+ default: {
+ ALOGE("Predicate \"%lld\" malformed", (long long)id);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool updateConditions(const ConfigKey& key, const StatsdConfig& config,
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ const set<int64_t>& replacedMatchers,
+ const unordered_map<int64_t, int>& oldConditionTrackerMap,
+ const vector<sp<ConditionTracker>>& oldConditionTrackers,
+ unordered_map<int64_t, int>& newConditionTrackerMap,
+ vector<sp<ConditionTracker>>& newConditionTrackers,
+ unordered_map<int, vector<int>>& trackerToConditionMap,
+ vector<ConditionState>& conditionCache, set<int64_t>& replacedConditions) {
+ vector<Predicate> conditionProtos;
+ const int conditionTrackerCount = config.predicate_size();
+ conditionProtos.reserve(conditionTrackerCount);
+ newConditionTrackers.reserve(conditionTrackerCount);
+ conditionCache.assign(conditionTrackerCount, ConditionState::kNotEvaluated);
+
+ for (int i = 0; i < conditionTrackerCount; i++) {
+ const Predicate& condition = config.predicate(i);
+ if (newConditionTrackerMap.find(condition.id()) != newConditionTrackerMap.end()) {
+ ALOGE("Duplicate Predicate found!");
+ return false;
+ }
+ newConditionTrackerMap[condition.id()] = i;
+ conditionProtos.push_back(condition);
+ }
+
+ vector<UpdateStatus> conditionsToUpdate(conditionTrackerCount, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(conditionTrackerCount, false);
+ for (int i = 0; i < conditionTrackerCount; i++) {
+ if (!determineConditionUpdateStatus(config, i, oldConditionTrackerMap, oldConditionTrackers,
+ newConditionTrackerMap, replacedMatchers,
+ conditionsToUpdate, cycleTracker)) {
+ return false;
+ }
+ }
+
+ // Update status has been determined for all conditions. Now perform the update.
+ set<int> preservedConditions;
+ for (int i = 0; i < conditionTrackerCount; i++) {
+ const Predicate& predicate = config.predicate(i);
+ const int64_t id = predicate.id();
+ switch (conditionsToUpdate[i]) {
+ case UPDATE_PRESERVE: {
+ preservedConditions.insert(i);
+ const auto& oldConditionTrackerIt = oldConditionTrackerMap.find(id);
+ if (oldConditionTrackerIt == oldConditionTrackerMap.end()) {
+ ALOGE("Could not find Predicate %lld in the previous config, but expected it "
+ "to be there",
+ (long long)id);
+ return false;
+ }
+ const int oldIndex = oldConditionTrackerIt->second;
+ newConditionTrackers.push_back(oldConditionTrackers[oldIndex]);
+ break;
+ }
+ case UPDATE_REPLACE:
+ replacedConditions.insert(id);
+ [[fallthrough]]; // Intentionally fallthrough to create the new condition tracker.
+ case UPDATE_NEW: {
+ sp<ConditionTracker> tracker =
+ createConditionTracker(key, predicate, i, atomMatchingTrackerMap);
+ if (tracker == nullptr) {
+ return false;
+ }
+ newConditionTrackers.push_back(tracker);
+ break;
+ }
+ default: {
+ ALOGE("Condition \"%lld\" update state is unknown. This should never happen",
+ (long long)id);
+ return false;
+ }
+ }
+ }
+
+ // Update indices of preserved predicates.
+ for (const int conditionIndex : preservedConditions) {
+ if (!newConditionTrackers[conditionIndex]->onConfigUpdated(
+ conditionProtos, conditionIndex, newConditionTrackers, atomMatchingTrackerMap,
+ newConditionTrackerMap)) {
+ ALOGE("Failed to update condition %lld",
+ (long long)newConditionTrackers[conditionIndex]->getConditionId());
+ return false;
+ }
+ }
+
+ std::fill(cycleTracker.begin(), cycleTracker.end(), false);
+ for (int conditionIndex = 0; conditionIndex < conditionTrackerCount; conditionIndex++) {
+ const sp<ConditionTracker>& conditionTracker = newConditionTrackers[conditionIndex];
+ // Calling init on preserved conditions is OK. It is needed to fill the condition cache.
+ if (!conditionTracker->init(conditionProtos, newConditionTrackers, newConditionTrackerMap,
+ cycleTracker, conditionCache)) {
+ return false;
+ }
+ for (const int trackerIndex : conditionTracker->getAtomMatchingTrackerIndex()) {
+ vector<int>& conditionList = trackerToConditionMap[trackerIndex];
+ conditionList.push_back(conditionIndex);
+ }
+ }
+ return true;
+}
+
+bool updateStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp<UidMap>& uidMap,
+ const sp<StatsPullerManager>& pullerManager,
+ const sp<AlarmMonitor>& anomalyAlarmMonitor,
+ const sp<AlarmMonitor>& periodicAlarmMonitor, const int64_t timeBaseNs,
+ const int64_t currentTimeNs,
+ const vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers,
+ const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const vector<sp<ConditionTracker>>& oldConditionTrackers,
+ const unordered_map<int64_t, int>& oldConditionTrackerMap,
+ set<int>& allTagIds,
+ vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers,
+ unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ vector<sp<ConditionTracker>>& newConditionTrackers,
+ unordered_map<int64_t, int>& newConditionTrackerMap,
+ unordered_map<int, vector<int>>& trackerToConditionMap) {
+ set<int64_t> replacedMatchers;
+ set<int64_t> replacedConditions;
+ vector<ConditionState> conditionCache;
+
+ if (!updateAtomMatchingTrackers(config, uidMap, oldAtomMatchingTrackerMap,
+ oldAtomMatchingTrackers, allTagIds, newAtomMatchingTrackerMap,
+ newAtomMatchingTrackers, replacedMatchers)) {
+ ALOGE("updateAtomMatchingTrackers failed");
+ return false;
+ }
+ VLOG("updateAtomMatchingTrackers succeeded");
+
+ if (!updateConditions(key, config, newAtomMatchingTrackerMap, replacedMatchers,
+ oldConditionTrackerMap, oldConditionTrackers, newConditionTrackerMap,
+ newConditionTrackers, trackerToConditionMap, conditionCache,
+ replacedConditions)) {
+ ALOGE("updateConditions failed");
+ return false;
+ }
+ VLOG("updateConditions succeeded");
+
+ return true;
+}
+
+} // namespace statsd
+} // namespace os
+} // namespace android
diff --git a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.h b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.h
new file mode 100644
index 000000000000..7ba684a65e88
--- /dev/null
+++ b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <vector>
+
+#include "anomaly/AlarmMonitor.h"
+#include "condition/ConditionTracker.h"
+#include "external/StatsPullerManager.h"
+#include "matchers/AtomMatchingTracker.h"
+
+namespace android {
+namespace os {
+namespace statsd {
+
+// Helper functions for MetricsManager to update itself from a new StatsdConfig.
+// *Note*: only updateStatsdConfig() should be called from outside this file.
+// All other functions are intermediate steps, created to make unit testing easier.
+
+// Possible update states for a component. PRESERVE means we should keep the existing one.
+// REPLACE means we should create a new one because the existing one changed
+// NEW means we should create a new one because one does not currently exist.
+enum UpdateStatus {
+ UPDATE_UNKNOWN = 0,
+ UPDATE_PRESERVE = 1,
+ UPDATE_REPLACE = 2,
+ UPDATE_NEW = 3,
+};
+
+// Recursive function to determine if a matcher needs to be updated.
+// input:
+// [config]: the input StatsdConfig
+// [matcherIdx]: the index of the current matcher to be updated
+// [oldAtomMatchingTrackerMap]: matcher id to index mapping in the existing MetricsManager
+// [oldAtomMatchingTrackers]: stores the existing AtomMatchingTrackers
+// [newAtomMatchingTrackerMap]: matcher id to index mapping in the input StatsdConfig
+// output:
+// [matchersToUpdate]: vector of the update status of each matcher. The matcherIdx index will
+// be updated from UPDATE_UNKNOWN after this call.
+// [cycleTracker]: intermediate param used during recursion.
+// Returns whether the function was successful or not.
+bool determineMatcherUpdateStatus(
+ const StatsdConfig& config, const int matcherIdx,
+ const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const std::vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers,
+ const std::unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ std::vector<UpdateStatus>& matchersToUpdate, std::vector<bool>& cycleTracker);
+
+// Updates the AtomMatchingTrackers.
+// input:
+// [config]: the input StatsdConfig
+// [oldAtomMatchingTrackerMap]: existing matcher id to index mapping
+// [oldAtomMatchingTrackers]: stores the existing AtomMatchingTrackers
+// output:
+// [allTagIds]: contains the set of all interesting tag ids to this config.
+// [newAtomMatchingTrackerMap]: new matcher id to index mapping
+// [newAtomMatchingTrackers]: stores the new AtomMatchingTrackers
+// [replacedMatchers]: set of matcher ids that changed and have been replaced
+bool updateAtomMatchingTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap,
+ const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const std::vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers,
+ std::set<int>& allTagIds,
+ std::unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ std::vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers,
+ std::set<int64_t>& replacedMatchers);
+
+// Recursive function to determine if a condition needs to be updated.
+// input:
+// [config]: the input StatsdConfig
+// [conditionIdx]: the index of the current condition to be updated
+// [oldConditionTrackerMap]: condition id to index mapping in the existing MetricsManager
+// [oldConditionTrackers]: stores the existing ConditionTrackers
+// [newConditionTrackerMap]: condition id to index mapping in the input StatsdConfig
+// [replacedMatchers]: set of replaced matcher ids. conditions using these matchers must be replaced
+// output:
+// [conditionsToUpdate]: vector of the update status of each condition. The conditionIdx index will
+// be updated from UPDATE_UNKNOWN after this call.
+// [cycleTracker]: intermediate param used during recursion.
+// Returns whether the function was successful or not.
+bool determineConditionUpdateStatus(const StatsdConfig& config, const int conditionIdx,
+ const std::unordered_map<int64_t, int>& oldConditionTrackerMap,
+ const std::vector<sp<ConditionTracker>>& oldConditionTrackers,
+ const std::unordered_map<int64_t, int>& newConditionTrackerMap,
+ const std::set<int64_t>& replacedMatchers,
+ std::vector<UpdateStatus>& conditionsToUpdate,
+ std::vector<bool>& cycleTracker);
+
+// Updates ConditionTrackers
+// input:
+// [config]: the input config
+// [atomMatchingTrackerMap]: AtomMatchingTracker name to index mapping from previous step.
+// [replacedMatchers]: ids of replaced matchers. conditions depending on these must also be replaced
+// [oldConditionTrackerMap]: existing matcher id to index mapping
+// [oldConditionTrackers]: stores the existing ConditionTrackers
+// output:
+// [newConditionTrackerMap]: new condition id to index mapping
+// [newConditionTrackers]: stores the sp to all the ConditionTrackers
+// [trackerToConditionMap]: contains the mapping from the index of an atom matcher
+// to indices of condition trackers that use the matcher
+// [conditionCache]: stores the current conditions for each ConditionTracker
+// [replacedConditions]: set of matcher ids that have changed and have been replaced
+bool updateConditions(const ConfigKey& key, const StatsdConfig& config,
+ const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ const std::set<int64_t>& replacedMatchers,
+ const std::unordered_map<int64_t, int>& oldConditionTrackerMap,
+ const std::vector<sp<ConditionTracker>>& oldConditionTrackers,
+ std::unordered_map<int64_t, int>& newConditionTrackerMap,
+ std::vector<sp<ConditionTracker>>& newConditionTrackers,
+ std::unordered_map<int, std::vector<int>>& trackerToConditionMap,
+ std::vector<ConditionState>& conditionCache,
+ std::set<int64_t>& replacedConditions);
+
+// Updates the existing MetricsManager from a new StatsdConfig.
+// Parameters are the members of MetricsManager. See MetricsManager for declaration.
+bool updateStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp<UidMap>& uidMap,
+ const sp<StatsPullerManager>& pullerManager,
+ const sp<AlarmMonitor>& anomalyAlarmMonitor,
+ const sp<AlarmMonitor>& periodicAlarmMonitor, const int64_t timeBaseNs,
+ const int64_t currentTimeNs,
+ const std::vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers,
+ const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const std::vector<sp<ConditionTracker>>& oldConditionTrackers,
+ const std::unordered_map<int64_t, int>& oldConditionTrackerMap,
+ std::set<int>& allTagIds,
+ std::vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers,
+ std::unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ std::vector<sp<ConditionTracker>>& newConditionTrackers,
+ std::unordered_map<int64_t, int>& newConditionTrackerMap,
+ std::unordered_map<int, std::vector<int>>& trackerToConditionMap);
+
+} // namespace statsd
+} // namespace os
+} // namespace android
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
index 8917c36bb608..3f40c90d515a 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
@@ -22,21 +22,23 @@
#include <inttypes.h>
#include "FieldValue.h"
-#include "MetricProducer.h"
#include "condition/CombinationConditionTracker.h"
#include "condition/SimpleConditionTracker.h"
#include "external/StatsPullerManager.h"
-#include "matchers/CombinationLogMatchingTracker.h"
+#include "hash.h"
+#include "matchers/CombinationAtomMatchingTracker.h"
#include "matchers/EventMatcherWizard.h"
-#include "matchers/SimpleLogMatchingTracker.h"
+#include "matchers/SimpleAtomMatchingTracker.h"
#include "metrics/CountMetricProducer.h"
#include "metrics/DurationMetricProducer.h"
#include "metrics/EventMetricProducer.h"
#include "metrics/GaugeMetricProducer.h"
+#include "metrics/MetricProducer.h"
#include "metrics/ValueMetricProducer.h"
#include "state/StateManager.h"
#include "stats_util.h"
+using google::protobuf::MessageLite;
using std::set;
using std::unordered_map;
using std::vector;
@@ -59,20 +61,77 @@ bool hasLeafNode(const FieldMatcher& matcher) {
return true;
}
+bool getMetricProtoHash(const MessageLite& metric, const int64_t id, const bool hasActivation,
+ const uint64_t activationHash, uint64_t& metricHash) {
+ string serializedMetric;
+ if (!metric.SerializeToString(&serializedMetric)) {
+ ALOGE("Unable to serialize metric %lld", (long long)id);
+ return false;
+ }
+ metricHash = Hash64(serializedMetric);
+ if (hasActivation) {
+ metricHash = Hash64(to_string(metricHash).append(to_string(activationHash)));
+ }
+ return true;
+}
+
} // namespace
-bool handleMetricWithLogTrackers(const int64_t what, const int metricIndex,
- const bool usedForDimension,
- const vector<sp<LogMatchingTracker>>& allAtomMatchers,
- const unordered_map<int64_t, int>& logTrackerMap,
- unordered_map<int, std::vector<int>>& trackerToMetricMap,
- int& logTrackerIndex) {
- auto logTrackerIt = logTrackerMap.find(what);
- if (logTrackerIt == logTrackerMap.end()) {
+sp<AtomMatchingTracker> createAtomMatchingTracker(const AtomMatcher& logMatcher, const int index,
+ const sp<UidMap>& uidMap) {
+ string serializedMatcher;
+ if (!logMatcher.SerializeToString(&serializedMatcher)) {
+ ALOGE("Unable to serialize matcher %lld", (long long)logMatcher.id());
+ return nullptr;
+ }
+ uint64_t protoHash = Hash64(serializedMatcher);
+ switch (logMatcher.contents_case()) {
+ case AtomMatcher::ContentsCase::kSimpleAtomMatcher:
+ return new SimpleAtomMatchingTracker(logMatcher.id(), index, protoHash,
+ logMatcher.simple_atom_matcher(), uidMap);
+ case AtomMatcher::ContentsCase::kCombination:
+ return new CombinationAtomMatchingTracker(logMatcher.id(), index, protoHash);
+ default:
+ ALOGE("Matcher \"%lld\" malformed", (long long)logMatcher.id());
+ return nullptr;
+ }
+}
+
+sp<ConditionTracker> createConditionTracker(
+ const ConfigKey& key, const Predicate& predicate, const int index,
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap) {
+ string serializedPredicate;
+ if (!predicate.SerializeToString(&serializedPredicate)) {
+ ALOGE("Unable to serialize predicate %lld", (long long)predicate.id());
+ return nullptr;
+ }
+ uint64_t protoHash = Hash64(serializedPredicate);
+ switch (predicate.contents_case()) {
+ case Predicate::ContentsCase::kSimplePredicate: {
+ return new SimpleConditionTracker(key, predicate.id(), protoHash, index,
+ predicate.simple_predicate(), atomMatchingTrackerMap);
+ }
+ case Predicate::ContentsCase::kCombination: {
+ return new CombinationConditionTracker(predicate.id(), index, protoHash);
+ }
+ default:
+ ALOGE("Predicate \"%lld\" malformed", (long long)predicate.id());
+ return nullptr;
+ }
+}
+
+bool handleMetricWithAtomMatchingTrackers(
+ const int64_t what, const int metricIndex, const bool usedForDimension,
+ const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ unordered_map<int, std::vector<int>>& trackerToMetricMap, int& logTrackerIndex) {
+ auto logTrackerIt = atomMatchingTrackerMap.find(what);
+ if (logTrackerIt == atomMatchingTrackerMap.end()) {
ALOGW("cannot find the AtomMatcher \"%lld\" in config", (long long)what);
return false;
}
- if (usedForDimension && allAtomMatchers[logTrackerIt->second]->getAtomIds().size() > 1) {
+ if (usedForDimension &&
+ allAtomMatchingTrackers[logTrackerIt->second]->getAtomIds().size() > 1) {
ALOGE("AtomMatcher \"%lld\" has more than one tag ids. When a metric has dimension, "
"the \"what\" can only about one atom type.",
(long long)what);
@@ -84,17 +143,17 @@ bool handleMetricWithLogTrackers(const int64_t what, const int metricIndex,
return true;
}
-bool handlePullMetricTriggerWithLogTrackers(
+bool handlePullMetricTriggerWithAtomMatchingTrackers(
const int64_t trigger, const int metricIndex,
- const vector<sp<LogMatchingTracker>>& allAtomMatchers,
- const unordered_map<int64_t, int>& logTrackerMap,
+ const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap,
unordered_map<int, std::vector<int>>& trackerToMetricMap, int& logTrackerIndex) {
- auto logTrackerIt = logTrackerMap.find(trigger);
- if (logTrackerIt == logTrackerMap.end()) {
+ auto logTrackerIt = atomMatchingTrackerMap.find(trigger);
+ if (logTrackerIt == atomMatchingTrackerMap.end()) {
ALOGW("cannot find the AtomMatcher \"%lld\" in config", (long long)trigger);
return false;
}
- if (allAtomMatchers[logTrackerIt->second]->getAtomIds().size() > 1) {
+ if (allAtomMatchingTrackers[logTrackerIt->second]->getAtomIds().size() > 1) {
ALOGE("AtomMatcher \"%lld\" has more than one tag ids."
"Trigger can only be one atom type.",
(long long)trigger);
@@ -125,8 +184,6 @@ bool handleMetricWithConditions(
ALOGW("cannot find Predicate \"%lld\" in the config", (long long)link.condition());
return false;
}
- allConditionTrackers[condition_it->second]->setSliced(true);
- allConditionTrackers[it->second]->setSliced(true);
}
conditionIndex = condition_it->second;
@@ -184,44 +241,55 @@ bool handleMetricWithStateLink(const FieldMatcher& stateMatcher,
// to provide the producer with state about its activators and deactivators.
// Returns false if there are errors.
bool handleMetricActivation(
- const StatsdConfig& config,
- const int64_t metricId,
- const int metricIndex,
+ const StatsdConfig& config, const int64_t metricId, const int metricIndex,
const unordered_map<int64_t, int>& metricToActivationMap,
- const unordered_map<int64_t, int>& logTrackerMap,
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap, bool& hasActivation,
unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
vector<int>& metricsWithActivation,
unordered_map<int, shared_ptr<Activation>>& eventActivationMap,
- unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap) {
+ unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap,
+ uint64_t& activationHash) {
// Check if metric has an associated activation
auto itr = metricToActivationMap.find(metricId);
- if (itr == metricToActivationMap.end()) return true;
+ if (itr == metricToActivationMap.end()) {
+ hasActivation = false;
+ return true;
+ }
+ hasActivation = true;
int activationIndex = itr->second;
const MetricActivation& metricActivation = config.metric_activation(activationIndex);
+ string serializedActivation;
+ if (!metricActivation.SerializeToString(&serializedActivation)) {
+ ALOGE("Unable to serialize metric activation for metric %lld", (long long)metricId);
+ return false;
+ }
+ activationHash = Hash64(serializedActivation);
+
for (int i = 0; i < metricActivation.event_activation_size(); i++) {
const EventActivation& activation = metricActivation.event_activation(i);
- auto itr = logTrackerMap.find(activation.atom_matcher_id());
- if (itr == logTrackerMap.end()) {
+ auto itr = atomMatchingTrackerMap.find(activation.atom_matcher_id());
+ if (itr == atomMatchingTrackerMap.end()) {
ALOGE("Atom matcher not found for event activation.");
return false;
}
- ActivationType activationType = (activation.has_activation_type()) ?
- activation.activation_type() : metricActivation.activation_type();
- std::shared_ptr<Activation> activationWrapper = std::make_shared<Activation>(
- activationType, activation.ttl_seconds() * NS_PER_SEC);
+ ActivationType activationType = (activation.has_activation_type())
+ ? activation.activation_type()
+ : metricActivation.activation_type();
+ std::shared_ptr<Activation> activationWrapper =
+ std::make_shared<Activation>(activationType, activation.ttl_seconds() * NS_PER_SEC);
int atomMatcherIndex = itr->second;
activationAtomTrackerToMetricMap[atomMatcherIndex].push_back(metricIndex);
eventActivationMap.emplace(atomMatcherIndex, activationWrapper);
if (activation.has_deactivation_atom_matcher_id()) {
- itr = logTrackerMap.find(activation.deactivation_atom_matcher_id());
- if (itr == logTrackerMap.end()) {
+ itr = atomMatchingTrackerMap.find(activation.deactivation_atom_matcher_id());
+ if (itr == atomMatchingTrackerMap.end()) {
ALOGE("Atom matcher not found for event deactivation.");
return false;
}
@@ -235,43 +303,34 @@ bool handleMetricActivation(
return true;
}
-bool initLogTrackers(const StatsdConfig& config, const UidMap& uidMap,
- unordered_map<int64_t, int>& logTrackerMap,
- vector<sp<LogMatchingTracker>>& allAtomMatchers, set<int>& allTagIds) {
+bool initAtomMatchingTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap,
+ unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ set<int>& allTagIds) {
vector<AtomMatcher> matcherConfigs;
const int atomMatcherCount = config.atom_matcher_size();
matcherConfigs.reserve(atomMatcherCount);
- allAtomMatchers.reserve(atomMatcherCount);
+ allAtomMatchingTrackers.reserve(atomMatcherCount);
for (int i = 0; i < atomMatcherCount; i++) {
const AtomMatcher& logMatcher = config.atom_matcher(i);
-
- int index = allAtomMatchers.size();
- switch (logMatcher.contents_case()) {
- case AtomMatcher::ContentsCase::kSimpleAtomMatcher:
- allAtomMatchers.push_back(new SimpleLogMatchingTracker(
- logMatcher.id(), index, logMatcher.simple_atom_matcher(), uidMap));
- break;
- case AtomMatcher::ContentsCase::kCombination:
- allAtomMatchers.push_back(
- new CombinationLogMatchingTracker(logMatcher.id(), index));
- break;
- default:
- ALOGE("Matcher \"%lld\" malformed", (long long)logMatcher.id());
- return false;
- // continue;
+ sp<AtomMatchingTracker> tracker = createAtomMatchingTracker(logMatcher, i, uidMap);
+ if (tracker == nullptr) {
+ return false;
}
- if (logTrackerMap.find(logMatcher.id()) != logTrackerMap.end()) {
+ allAtomMatchingTrackers.push_back(tracker);
+ if (atomMatchingTrackerMap.find(logMatcher.id()) != atomMatchingTrackerMap.end()) {
ALOGE("Duplicate AtomMatcher found!");
return false;
}
- logTrackerMap[logMatcher.id()] = index;
+ atomMatchingTrackerMap[logMatcher.id()] = i;
matcherConfigs.push_back(logMatcher);
}
- vector<bool> stackTracker2(allAtomMatchers.size(), false);
- for (auto& matcher : allAtomMatchers) {
- if (!matcher->init(matcherConfigs, allAtomMatchers, logTrackerMap, stackTracker2)) {
+ vector<bool> stackTracker2(allAtomMatchingTrackers.size(), false);
+ for (auto& matcher : allAtomMatchingTrackers) {
+ if (!matcher->init(matcherConfigs, allAtomMatchingTrackers, atomMatchingTrackerMap,
+ stackTracker2)) {
return false;
}
// Collect all the tag ids that are interesting. TagIds exist in leaf nodes only.
@@ -282,7 +341,7 @@ bool initLogTrackers(const StatsdConfig& config, const UidMap& uidMap,
}
bool initConditions(const ConfigKey& key, const StatsdConfig& config,
- const unordered_map<int64_t, int>& logTrackerMap,
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap,
unordered_map<int64_t, int>& conditionTrackerMap,
vector<sp<ConditionTracker>>& allConditionTrackers,
unordered_map<int, std::vector<int>>& trackerToConditionMap,
@@ -291,32 +350,21 @@ bool initConditions(const ConfigKey& key, const StatsdConfig& config,
const int conditionTrackerCount = config.predicate_size();
conditionConfigs.reserve(conditionTrackerCount);
allConditionTrackers.reserve(conditionTrackerCount);
- initialConditionCache.reserve(conditionTrackerCount);
- std::fill(initialConditionCache.begin(), initialConditionCache.end(), ConditionState::kUnknown);
+ initialConditionCache.assign(conditionTrackerCount, ConditionState::kNotEvaluated);
for (int i = 0; i < conditionTrackerCount; i++) {
const Predicate& condition = config.predicate(i);
- int index = allConditionTrackers.size();
- switch (condition.contents_case()) {
- case Predicate::ContentsCase::kSimplePredicate: {
- allConditionTrackers.push_back(new SimpleConditionTracker(
- key, condition.id(), index, condition.simple_predicate(), logTrackerMap));
- break;
- }
- case Predicate::ContentsCase::kCombination: {
- allConditionTrackers.push_back(
- new CombinationConditionTracker(condition.id(), index));
- break;
- }
- default:
- ALOGE("Predicate \"%lld\" malformed", (long long)condition.id());
- return false;
+ sp<ConditionTracker> tracker =
+ createConditionTracker(key, condition, i, atomMatchingTrackerMap);
+ if (tracker == nullptr) {
+ return false;
}
+ allConditionTrackers.push_back(tracker);
if (conditionTrackerMap.find(condition.id()) != conditionTrackerMap.end()) {
ALOGE("Duplicate Predicate found!");
return false;
}
- conditionTrackerMap[condition.id()] = index;
+ conditionTrackerMap[condition.id()] = i;
conditionConfigs.push_back(condition);
}
@@ -327,7 +375,7 @@ bool initConditions(const ConfigKey& key, const StatsdConfig& config,
stackTracker, initialConditionCache)) {
return false;
}
- for (const int trackerIndex : conditionTracker->getLogTrackerIndex()) {
+ for (const int trackerIndex : conditionTracker->getAtomMatchingTrackerIndex()) {
auto& conditionList = trackerToConditionMap[trackerIndex];
conditionList.push_back(i);
}
@@ -336,12 +384,20 @@ bool initConditions(const ConfigKey& key, const StatsdConfig& config,
}
bool initStates(const StatsdConfig& config, unordered_map<int64_t, int>& stateAtomIdMap,
- unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps) {
+ unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
+ map<int64_t, uint64_t>& stateProtoHashes) {
for (int i = 0; i < config.state_size(); i++) {
const State& state = config.state(i);
const int64_t stateId = state.id();
stateAtomIdMap[stateId] = state.atom_id();
+ string serializedState;
+ if (!state.SerializeToString(&serializedState)) {
+ ALOGE("Unable to serialize state %lld", (long long)stateId);
+ return false;
+ }
+ stateProtoHashes[stateId] = Hash64(serializedState);
+
const StateMap& stateMap = state.map();
for (auto group : stateMap.group()) {
for (auto value : group.value()) {
@@ -355,9 +411,9 @@ bool initStates(const StatsdConfig& config, unordered_map<int64_t, int>& stateAt
bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseTimeNs,
const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager,
- const unordered_map<int64_t, int>& logTrackerMap,
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap,
const unordered_map<int64_t, int>& conditionTrackerMap,
- const vector<sp<LogMatchingTracker>>& allAtomMatchers,
+ const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
const unordered_map<int64_t, int>& stateAtomIdMap,
const unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
vector<sp<ConditionTracker>>& allConditionTrackers,
@@ -370,7 +426,7 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
vector<int>& metricsWithActivation) {
sp<ConditionWizard> wizard = new ConditionWizard(allConditionTrackers);
- sp<EventMatcherWizard> matcherWizard = new EventMatcherWizard(allAtomMatchers);
+ sp<EventMatcherWizard> matcherWizard = new EventMatcherWizard(allAtomMatchingTrackers);
const int allMetricsCount = config.count_metric_size() + config.duration_metric_size() +
config.event_metric_size() + config.gauge_metric_size() +
config.value_metric_size();
@@ -383,7 +439,7 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
const MetricActivation& metricActivation = config.metric_activation(i);
int64_t metricId = metricActivation.metric_id();
if (metricToActivationMap.find(metricId) != metricToActivationMap.end()) {
- ALOGE("Metric %lld has multiple MetricActivations", (long long) metricId);
+ ALOGE("Metric %lld has multiple MetricActivations", (long long)metricId);
return false;
}
metricToActivationMap.insert({metricId, i});
@@ -401,10 +457,10 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
int metricIndex = allMetricProducers.size();
metricMap.insert({metric.id(), metricIndex});
int trackerIndex;
- if (!handleMetricWithLogTrackers(metric.what(), metricIndex,
- metric.has_dimensions_in_what(),
- allAtomMatchers, logTrackerMap, trackerToMetricMap,
- trackerIndex)) {
+ if (!handleMetricWithAtomMatchingTrackers(metric.what(), metricIndex,
+ metric.has_dimensions_in_what(),
+ allAtomMatchingTrackers, atomMatchingTrackerMap,
+ trackerToMetricMap, trackerIndex)) {
return false;
}
@@ -436,18 +492,25 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
}
}
+ bool hasActivation = false;
unordered_map<int, shared_ptr<Activation>> eventActivationMap;
unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
- bool success = handleMetricActivation(config, metric.id(), metricIndex,
- metricToActivationMap, logTrackerMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation, eventActivationMap,
- eventDeactivationMap);
+ uint64_t activationHash;
+ bool success = handleMetricActivation(
+ config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
+ hasActivation, activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation, eventActivationMap, eventDeactivationMap, activationHash);
if (!success) return false;
- sp<MetricProducer> countProducer =
- new CountMetricProducer(key, metric, conditionIndex, initialConditionCache, wizard,
- timeBaseTimeNs, currentTimeNs, eventActivationMap,
- eventDeactivationMap, slicedStateAtoms, stateGroupMap);
+ uint64_t metricHash;
+ if (!getMetricProtoHash(metric, metric.id(), hasActivation, activationHash, metricHash)) {
+ return false;
+ }
+
+ sp<MetricProducer> countProducer = new CountMetricProducer(
+ key, metric, conditionIndex, initialConditionCache, wizard, metricHash,
+ timeBaseTimeNs, currentTimeNs, eventActivationMap, eventDeactivationMap,
+ slicedStateAtoms, stateGroupMap);
allMetricProducers.push_back(countProducer);
}
@@ -476,24 +539,27 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
int trackerIndices[3] = {-1, -1, -1};
if (!simplePredicate.has_start() ||
- !handleMetricWithLogTrackers(simplePredicate.start(), metricIndex,
- metric.has_dimensions_in_what(), allAtomMatchers,
- logTrackerMap, trackerToMetricMap, trackerIndices[0])) {
+ !handleMetricWithAtomMatchingTrackers(simplePredicate.start(), metricIndex,
+ metric.has_dimensions_in_what(),
+ allAtomMatchingTrackers, atomMatchingTrackerMap,
+ trackerToMetricMap, trackerIndices[0])) {
ALOGE("Duration metrics must specify a valid the start event matcher");
return false;
}
if (simplePredicate.has_stop() &&
- !handleMetricWithLogTrackers(simplePredicate.stop(), metricIndex,
- metric.has_dimensions_in_what(), allAtomMatchers,
- logTrackerMap, trackerToMetricMap, trackerIndices[1])) {
+ !handleMetricWithAtomMatchingTrackers(simplePredicate.stop(), metricIndex,
+ metric.has_dimensions_in_what(),
+ allAtomMatchingTrackers, atomMatchingTrackerMap,
+ trackerToMetricMap, trackerIndices[1])) {
return false;
}
if (simplePredicate.has_stop_all() &&
- !handleMetricWithLogTrackers(simplePredicate.stop_all(), metricIndex,
- metric.has_dimensions_in_what(), allAtomMatchers,
- logTrackerMap, trackerToMetricMap, trackerIndices[2])) {
+ !handleMetricWithAtomMatchingTrackers(simplePredicate.stop_all(), metricIndex,
+ metric.has_dimensions_in_what(),
+ allAtomMatchingTrackers, atomMatchingTrackerMap,
+ trackerToMetricMap, trackerIndices[2])) {
return false;
}
@@ -542,19 +608,26 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
}
}
+ bool hasActivation = false;
unordered_map<int, shared_ptr<Activation>> eventActivationMap;
unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
- bool success = handleMetricActivation(config, metric.id(), metricIndex,
- metricToActivationMap, logTrackerMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation, eventActivationMap,
- eventDeactivationMap);
+ uint64_t activationHash;
+ bool success = handleMetricActivation(
+ config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
+ hasActivation, activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation, eventActivationMap, eventDeactivationMap, activationHash);
if (!success) return false;
+ uint64_t metricHash;
+ if (!getMetricProtoHash(metric, metric.id(), hasActivation, activationHash, metricHash)) {
+ return false;
+ }
+
sp<MetricProducer> durationMetric = new DurationMetricProducer(
key, metric, conditionIndex, initialConditionCache, trackerIndices[0],
- trackerIndices[1], trackerIndices[2], nesting, wizard, internalDimensions,
- timeBaseTimeNs, currentTimeNs, eventActivationMap, eventDeactivationMap,
- slicedStateAtoms, stateGroupMap);
+ trackerIndices[1], trackerIndices[2], nesting, wizard, metricHash,
+ internalDimensions, timeBaseTimeNs, currentTimeNs, eventActivationMap,
+ eventDeactivationMap, slicedStateAtoms, stateGroupMap);
allMetricProducers.push_back(durationMetric);
}
@@ -569,8 +642,9 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
return false;
}
int trackerIndex;
- if (!handleMetricWithLogTrackers(metric.what(), metricIndex, false, allAtomMatchers,
- logTrackerMap, trackerToMetricMap, trackerIndex)) {
+ if (!handleMetricWithAtomMatchingTrackers(metric.what(), metricIndex, false,
+ allAtomMatchingTrackers, atomMatchingTrackerMap,
+ trackerToMetricMap, trackerIndex)) {
return false;
}
@@ -589,17 +663,24 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
}
}
+ bool hasActivation = false;
unordered_map<int, shared_ptr<Activation>> eventActivationMap;
unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
- bool success = handleMetricActivation(config, metric.id(), metricIndex,
- metricToActivationMap, logTrackerMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation, eventActivationMap,
- eventDeactivationMap);
+ uint64_t activationHash;
+ bool success = handleMetricActivation(
+ config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
+ hasActivation, activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation, eventActivationMap, eventDeactivationMap, activationHash);
if (!success) return false;
- sp<MetricProducer> eventMetric =
- new EventMetricProducer(key, metric, conditionIndex, initialConditionCache, wizard,
- timeBaseTimeNs, eventActivationMap, eventDeactivationMap);
+ uint64_t metricHash;
+ if (!getMetricProtoHash(metric, metric.id(), hasActivation, activationHash, metricHash)) {
+ return false;
+ }
+
+ sp<MetricProducer> eventMetric = new EventMetricProducer(
+ key, metric, conditionIndex, initialConditionCache, wizard, metricHash,
+ timeBaseTimeNs, eventActivationMap, eventDeactivationMap);
allMetricProducers.push_back(eventMetric);
}
@@ -625,14 +706,14 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
int metricIndex = allMetricProducers.size();
metricMap.insert({metric.id(), metricIndex});
int trackerIndex;
- if (!handleMetricWithLogTrackers(metric.what(), metricIndex,
- metric.has_dimensions_in_what(),
- allAtomMatchers, logTrackerMap, trackerToMetricMap,
- trackerIndex)) {
+ if (!handleMetricWithAtomMatchingTrackers(metric.what(), metricIndex,
+ metric.has_dimensions_in_what(),
+ allAtomMatchingTrackers, atomMatchingTrackerMap,
+ trackerToMetricMap, trackerIndex)) {
return false;
}
- sp<LogMatchingTracker> atomMatcher = allAtomMatchers.at(trackerIndex);
+ sp<AtomMatchingTracker> atomMatcher = allAtomMatchingTrackers.at(trackerIndex);
// If it is pulled atom, it should be simple matcher with one tagId.
if (atomMatcher->getAtomIds().size() != 1) {
return false;
@@ -678,18 +759,26 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
}
}
+ bool hasActivation = false;
unordered_map<int, shared_ptr<Activation>> eventActivationMap;
unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
+ uint64_t activationHash;
bool success = handleMetricActivation(
- config, metric.id(), metricIndex, metricToActivationMap, logTrackerMap,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- metricsWithActivation, eventActivationMap, eventDeactivationMap);
+ config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
+ hasActivation, activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation, eventActivationMap, eventDeactivationMap, activationHash);
if (!success) return false;
+ uint64_t metricHash;
+ if (!getMetricProtoHash(metric, metric.id(), hasActivation, activationHash, metricHash)) {
+ return false;
+ }
+
sp<MetricProducer> valueProducer = new ValueMetricProducer(
- key, metric, conditionIndex, initialConditionCache, wizard, trackerIndex,
- matcherWizard, pullTagId, timeBaseTimeNs, currentTimeNs, pullerManager,
- eventActivationMap, eventDeactivationMap, slicedStateAtoms, stateGroupMap);
+ key, metric, conditionIndex, initialConditionCache, wizard, metricHash,
+ trackerIndex, matcherWizard, pullTagId, timeBaseTimeNs, currentTimeNs,
+ pullerManager, eventActivationMap, eventDeactivationMap, slicedStateAtoms,
+ stateGroupMap);
allMetricProducers.push_back(valueProducer);
}
@@ -717,14 +806,14 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
int metricIndex = allMetricProducers.size();
metricMap.insert({metric.id(), metricIndex});
int trackerIndex;
- if (!handleMetricWithLogTrackers(metric.what(), metricIndex,
- metric.has_dimensions_in_what(),
- allAtomMatchers, logTrackerMap, trackerToMetricMap,
- trackerIndex)) {
+ if (!handleMetricWithAtomMatchingTrackers(metric.what(), metricIndex,
+ metric.has_dimensions_in_what(),
+ allAtomMatchingTrackers, atomMatchingTrackerMap,
+ trackerToMetricMap, trackerIndex)) {
return false;
}
- sp<LogMatchingTracker> atomMatcher = allAtomMatchers.at(trackerIndex);
+ sp<AtomMatchingTracker> atomMatcher = allAtomMatchingTrackers.at(trackerIndex);
// For GaugeMetric atom, it should be simple matcher with one tagId.
if (atomMatcher->getAtomIds().size() != 1) {
return false;
@@ -743,12 +832,13 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
if (metric.sampling_type() != GaugeMetric::FIRST_N_SAMPLES) {
return false;
}
- if (!handlePullMetricTriggerWithLogTrackers(metric.trigger_event(), metricIndex,
- allAtomMatchers, logTrackerMap,
- trackerToMetricMap, triggerTrackerIndex)) {
+ if (!handlePullMetricTriggerWithAtomMatchingTrackers(
+ metric.trigger_event(), metricIndex, allAtomMatchingTrackers,
+ atomMatchingTrackerMap, trackerToMetricMap, triggerTrackerIndex)) {
return false;
}
- sp<LogMatchingTracker> triggerAtomMatcher = allAtomMatchers.at(triggerTrackerIndex);
+ sp<AtomMatchingTracker> triggerAtomMatcher =
+ allAtomMatchingTrackers.at(triggerTrackerIndex);
triggerAtomId = *(triggerAtomMatcher->getAtomIds().begin());
}
@@ -773,18 +863,25 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
}
}
+ bool hasActivation = false;
unordered_map<int, shared_ptr<Activation>> eventActivationMap;
unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
- bool success = handleMetricActivation(config, metric.id(), metricIndex,
- metricToActivationMap, logTrackerMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation, eventActivationMap,
- eventDeactivationMap);
+ uint64_t activationHash;
+ bool success = handleMetricActivation(
+ config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
+ hasActivation, activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation, eventActivationMap, eventDeactivationMap, activationHash);
if (!success) return false;
+ uint64_t metricHash;
+ if (!getMetricProtoHash(metric, metric.id(), hasActivation, activationHash, metricHash)) {
+ return false;
+ }
+
sp<MetricProducer> gaugeProducer = new GaugeMetricProducer(
- key, metric, conditionIndex, initialConditionCache, wizard, trackerIndex,
- matcherWizard, pullTagId, triggerAtomId, atomTagId, timeBaseTimeNs, currentTimeNs,
- pullerManager, eventActivationMap, eventDeactivationMap);
+ key, metric, conditionIndex, initialConditionCache, wizard, metricHash,
+ trackerIndex, matcherWizard, pullTagId, triggerAtomId, atomTagId, timeBaseTimeNs,
+ currentTimeNs, pullerManager, eventActivationMap, eventDeactivationMap);
allMetricProducers.push_back(gaugeProducer);
}
for (int i = 0; i < config.no_report_metric_size(); ++i) {
@@ -813,8 +910,7 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
return true;
}
-bool initAlerts(const StatsdConfig& config,
- const unordered_map<int64_t, int>& metricProducerMap,
+bool initAlerts(const StatsdConfig& config, const unordered_map<int64_t, int>& metricProducerMap,
unordered_map<int64_t, int>& alertTrackerMap,
const sp<AlarmMonitor>& anomalyAlarmMonitor,
vector<sp<MetricProducer>>& allMetricProducers,
@@ -832,8 +928,8 @@ bool initAlerts(const StatsdConfig& config,
return false;
}
if (alert.trigger_if_sum_gt() < 0 || alert.num_buckets() <= 0) {
- ALOGW("invalid alert: threshold=%f num_buckets= %d",
- alert.trigger_if_sum_gt(), alert.num_buckets());
+ ALOGW("invalid alert: threshold=%f num_buckets= %d", alert.trigger_if_sum_gt(),
+ alert.num_buckets());
return false;
}
const int metricIndex = itr->second;
@@ -853,14 +949,13 @@ bool initAlerts(const StatsdConfig& config,
}
if (subscription.subscriber_information_case() ==
Subscription::SubscriberInformationCase::SUBSCRIBER_INFORMATION_NOT_SET) {
- ALOGW("subscription \"%lld\" has no subscriber info.\"",
- (long long)subscription.id());
+ ALOGW("subscription \"%lld\" has no subscriber info.\"", (long long)subscription.id());
return false;
}
const auto& itr = alertTrackerMap.find(subscription.rule_id());
if (itr == alertTrackerMap.end()) {
ALOGW("subscription \"%lld\" has unknown rule id: \"%lld\"",
- (long long)subscription.id(), (long long)subscription.rule_id());
+ (long long)subscription.id(), (long long)subscription.rule_id());
return false;
}
const int anomalyTrackerIndex = itr->second;
@@ -870,12 +965,11 @@ bool initAlerts(const StatsdConfig& config,
}
bool initAlarms(const StatsdConfig& config, const ConfigKey& key,
- const sp<AlarmMonitor>& periodicAlarmMonitor,
- const int64_t timeBaseNs, const int64_t currentTimeNs,
- vector<sp<AlarmTracker>>& allAlarmTrackers) {
+ const sp<AlarmMonitor>& periodicAlarmMonitor, const int64_t timeBaseNs,
+ const int64_t currentTimeNs, vector<sp<AlarmTracker>>& allAlarmTrackers) {
unordered_map<int64_t, int> alarmTrackerMap;
int64_t startMillis = timeBaseNs / 1000 / 1000;
- int64_t currentTimeMillis = currentTimeNs / 1000 /1000;
+ int64_t currentTimeMillis = currentTimeNs / 1000 / 1000;
for (int i = 0; i < config.alarm_size(); i++) {
const Alarm& alarm = config.alarm(i);
if (alarm.offset_millis() <= 0) {
@@ -888,8 +982,7 @@ bool initAlarms(const StatsdConfig& config, const ConfigKey& key,
}
alarmTrackerMap.insert(std::make_pair(alarm.id(), allAlarmTrackers.size()));
allAlarmTrackers.push_back(
- new AlarmTracker(startMillis, currentTimeMillis,
- alarm, key, periodicAlarmMonitor));
+ new AlarmTracker(startMillis, currentTimeMillis, alarm, key, periodicAlarmMonitor));
}
for (int i = 0; i < config.subscription_size(); ++i) {
const Subscription& subscription = config.subscription(i);
@@ -898,14 +991,13 @@ bool initAlarms(const StatsdConfig& config, const ConfigKey& key,
}
if (subscription.subscriber_information_case() ==
Subscription::SubscriberInformationCase::SUBSCRIBER_INFORMATION_NOT_SET) {
- ALOGW("subscription \"%lld\" has no subscriber info.\"",
- (long long)subscription.id());
+ ALOGW("subscription \"%lld\" has no subscriber info.\"", (long long)subscription.id());
return false;
}
const auto& itr = alarmTrackerMap.find(subscription.rule_id());
if (itr == alarmTrackerMap.end()) {
ALOGW("subscription \"%lld\" has unknown rule id: \"%lld\"",
- (long long)subscription.id(), (long long)subscription.rule_id());
+ (long long)subscription.id(), (long long)subscription.rule_id());
return false;
}
const int trackerIndex = itr->second;
@@ -914,14 +1006,17 @@ bool initAlarms(const StatsdConfig& config, const ConfigKey& key,
return true;
}
-bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap& uidMap,
+bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp<UidMap>& uidMap,
const sp<StatsPullerManager>& pullerManager,
const sp<AlarmMonitor>& anomalyAlarmMonitor,
const sp<AlarmMonitor>& periodicAlarmMonitor, const int64_t timeBaseNs,
const int64_t currentTimeNs, set<int>& allTagIds,
- vector<sp<LogMatchingTracker>>& allAtomMatchers,
+ vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ unordered_map<int64_t, int>& atomMatchingTrackerMap,
vector<sp<ConditionTracker>>& allConditionTrackers,
+ unordered_map<int64_t, int>& conditionTrackerMap,
vector<sp<MetricProducer>>& allMetricProducers,
+ unordered_map<int64_t, int>& metricProducerMap,
vector<sp<AnomalyTracker>>& allAnomalyTrackers,
vector<sp<AlarmTracker>>& allPeriodicAlarmTrackers,
unordered_map<int, std::vector<int>>& conditionToMetricMap,
@@ -930,37 +1025,35 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap&
unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
unordered_map<int64_t, int>& alertTrackerMap,
- vector<int>& metricsWithActivation,
- std::set<int64_t>& noReportMetricIds) {
- unordered_map<int64_t, int> logTrackerMap;
- unordered_map<int64_t, int> conditionTrackerMap;
+ vector<int>& metricsWithActivation, map<int64_t, uint64_t>& stateProtoHashes,
+ set<int64_t>& noReportMetricIds) {
vector<ConditionState> initialConditionCache;
- unordered_map<int64_t, int> metricProducerMap;
unordered_map<int64_t, int> stateAtomIdMap;
unordered_map<int64_t, unordered_map<int, int64_t>> allStateGroupMaps;
- if (!initLogTrackers(config, uidMap, logTrackerMap, allAtomMatchers, allTagIds)) {
- ALOGE("initLogMatchingTrackers failed");
+ if (!initAtomMatchingTrackers(config, uidMap, atomMatchingTrackerMap, allAtomMatchingTrackers,
+ allTagIds)) {
+ ALOGE("initAtomMatchingTrackers failed");
return false;
}
- VLOG("initLogMatchingTrackers succeed...");
+ VLOG("initAtomMatchingTrackers succeed...");
- if (!initConditions(key, config, logTrackerMap, conditionTrackerMap, allConditionTrackers,
- trackerToConditionMap, initialConditionCache)) {
+ if (!initConditions(key, config, atomMatchingTrackerMap, conditionTrackerMap,
+ allConditionTrackers, trackerToConditionMap, initialConditionCache)) {
ALOGE("initConditionTrackers failed");
return false;
}
- if (!initStates(config, stateAtomIdMap, allStateGroupMaps)) {
+ if (!initStates(config, stateAtomIdMap, allStateGroupMaps, stateProtoHashes)) {
ALOGE("initStates failed");
return false;
}
- if (!initMetrics(key, config, timeBaseNs, currentTimeNs, pullerManager, logTrackerMap,
- conditionTrackerMap, allAtomMatchers, stateAtomIdMap, allStateGroupMaps,
- allConditionTrackers, initialConditionCache, allMetricProducers,
- conditionToMetricMap, trackerToMetricMap, metricProducerMap, noReportMetricIds,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- metricsWithActivation)) {
+ if (!initMetrics(key, config, timeBaseNs, currentTimeNs, pullerManager, atomMatchingTrackerMap,
+ conditionTrackerMap, allAtomMatchingTrackers, stateAtomIdMap,
+ allStateGroupMaps, allConditionTrackers, initialConditionCache,
+ allMetricProducers, conditionToMetricMap, trackerToMetricMap,
+ metricProducerMap, noReportMetricIds, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation)) {
ALOGE("initMetricProducers failed");
return false;
}
@@ -969,8 +1062,8 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap&
ALOGE("initAlerts failed");
return false;
}
- if (!initAlarms(config, key, periodicAlarmMonitor,
- timeBaseNs, currentTimeNs, allPeriodicAlarmTrackers)) {
+ if (!initAlarms(config, key, periodicAlarmMonitor, timeBaseNs, currentTimeNs,
+ allPeriodicAlarmTrackers)) {
ALOGE("initAlarms failed");
return false;
}
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.h b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h
index 96b5c26ff789..4979c3051133 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.h
+++ b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h
@@ -20,41 +20,63 @@
#include <unordered_map>
#include <vector>
-#include "../anomaly/AlarmTracker.h"
-#include "../condition/ConditionTracker.h"
-#include "../external/StatsPullerManager.h"
-#include "../matchers/LogMatchingTracker.h"
-#include "../metrics/MetricProducer.h"
+#include "anomaly/AlarmTracker.h"
+#include "condition/ConditionTracker.h"
+#include "external/StatsPullerManager.h"
+#include "matchers/AtomMatchingTracker.h"
+#include "metrics/MetricProducer.h"
namespace android {
namespace os {
namespace statsd {
+// Helper functions for creating individual config components from StatsdConfig.
+// Should only be called from metrics_manager_util and config_update_utils.
+
+// Create a AtomMatchingTracker.
+// input:
+// [logMatcher]: the input AtomMatcher from the StatsdConfig
+// [index]: the index of the matcher
+// output:
+// new AtomMatchingTracker, or null if the tracker is unable to be created
+sp<AtomMatchingTracker> createAtomMatchingTracker(const AtomMatcher& logMatcher, const int index,
+ const sp<UidMap>& uidMap);
+
+// Create a ConditionTracker.
+// input:
+// [predicate]: the input Predicate from the StatsdConfig
+// [index]: the index of the condition tracker
+// [atomMatchingTrackerMap]: map of atom matcher id to its index in allAtomMatchingTrackers
+// output:
+// new ConditionTracker, or null if the tracker is unable to be created
+sp<ConditionTracker> createConditionTracker(
+ const ConfigKey& key, const Predicate& predicate, const int index,
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap);
+
// Helper functions for MetricsManager to initialize from StatsdConfig.
// *Note*: only initStatsdConfig() should be called from outside.
// All other functions are intermediate
// steps, created to make unit tests easier. And most of the parameters in these
// functions are temporary objects in the initialization phase.
-// Initialize the LogMatchingTrackers.
+// Initialize the AtomMatchingTrackers.
// input:
// [key]: the config key that this config belongs to
// [config]: the input StatsdConfig
// output:
-// [logTrackerMap]: this map should contain matcher name to index mapping
-// [allAtomMatchers]: should store the sp to all the LogMatchingTracker
+// [atomMatchingTrackerMap]: this map should contain matcher name to index mapping
+// [allAtomMatchingTrackers]: should store the sp to all the AtomMatchingTracker
// [allTagIds]: contains the set of all interesting tag ids to this config.
-bool initLogTrackers(const StatsdConfig& config,
- const UidMap& uidMap,
- std::unordered_map<int64_t, int>& logTrackerMap,
- std::vector<sp<LogMatchingTracker>>& allAtomMatchers,
- std::set<int>& allTagIds);
+bool initAtomMatchingTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap,
+ std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ std::set<int>& allTagIds);
// Initialize ConditionTrackers
// input:
// [key]: the config key that this config belongs to
// [config]: the input config
-// [logTrackerMap]: LogMatchingTracker name to index mapping from previous step.
+// [atomMatchingTrackerMap]: AtomMatchingTracker name to index mapping from previous step.
// output:
// [conditionTrackerMap]: this map should contain condition name to index mapping
// [allConditionTrackers]: stores the sp to all the ConditionTrackers
@@ -62,11 +84,10 @@ bool initLogTrackers(const StatsdConfig& config,
// log tracker to condition trackers that use the log tracker
// [initialConditionCache]: stores the initial conditions for each ConditionTracker
bool initConditions(const ConfigKey& key, const StatsdConfig& config,
- const std::unordered_map<int64_t, int>& logTrackerMap,
+ const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
std::unordered_map<int64_t, int>& conditionTrackerMap,
std::vector<sp<ConditionTracker>>& allConditionTrackers,
std::unordered_map<int, std::vector<int>>& trackerToConditionMap,
- std::unordered_map<int, std::vector<MetricConditionLink>>& eventConditionLinks,
std::vector<ConditionState>& initialConditionCache);
// Initialize State maps using State protos in the config. These maps will
@@ -77,15 +98,17 @@ bool initConditions(const ConfigKey& key, const StatsdConfig& config,
// [stateAtomIdMap]: this map should contain the mapping from state ids to atom ids
// [allStateGroupMaps]: this map should contain the mapping from states ids and state
// values to state group ids for all states
+// [stateProtoHashes]: contains a map of state id to the hash of the State proto from the config
bool initStates(const StatsdConfig& config, unordered_map<int64_t, int>& stateAtomIdMap,
- unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps);
+ unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
+ std::map<int64_t, uint64_t>& stateProtoHashes);
// Initialize MetricProducers.
// input:
// [key]: the config key that this config belongs to
// [config]: the input config
// [timeBaseSec]: start time base for all metrics
-// [logTrackerMap]: LogMatchingTracker name to index mapping from previous step.
+// [atomMatchingTrackerMap]: AtomMatchingTracker name to index mapping from previous step.
// [conditionTrackerMap]: condition name to index mapping
// [stateAtomIdMap]: contains the mapping from state ids to atom ids
// [allStateGroupMaps]: contains the mapping from atom ids and state values to
@@ -97,11 +120,10 @@ bool initStates(const StatsdConfig& config, unordered_map<int64_t, int>& stateAt
// [trackerToMetricMap]: contains the mapping from log tracker to MetricProducer index.
bool initMetrics(
const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseTimeNs,
- const int64_t currentTimeNs, UidMap& uidMap, const sp<StatsPullerManager>& pullerManager,
- const std::unordered_map<int64_t, int>& logTrackerMap,
+ const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager,
+ const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
const std::unordered_map<int64_t, int>& conditionTrackerMap,
- const std::unordered_map<int, std::vector<MetricConditionLink>>& eventConditionLinks,
- const vector<sp<LogMatchingTracker>>& allAtomMatchers,
+ const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
const unordered_map<int64_t, int>& stateAtomIdMap,
const unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
vector<sp<ConditionTracker>>& allConditionTrackers,
@@ -116,14 +138,17 @@ bool initMetrics(
// Initialize MetricsManager from StatsdConfig.
// Parameters are the members of MetricsManager. See MetricsManager for declaration.
-bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap& uidMap,
+bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp<UidMap>& uidMap,
const sp<StatsPullerManager>& pullerManager,
const sp<AlarmMonitor>& anomalyAlarmMonitor,
const sp<AlarmMonitor>& periodicAlarmMonitor, const int64_t timeBaseNs,
const int64_t currentTimeNs, std::set<int>& allTagIds,
- std::vector<sp<LogMatchingTracker>>& allAtomMatchers,
+ std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
std::vector<sp<ConditionTracker>>& allConditionTrackers,
+ std::unordered_map<int64_t, int>& conditionTrackerMap,
std::vector<sp<MetricProducer>>& allMetricProducers,
+ std::unordered_map<int64_t, int>& metricProducerMap,
vector<sp<AnomalyTracker>>& allAnomalyTrackers,
vector<sp<AlarmTracker>>& allPeriodicAlarmTrackers,
std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
@@ -133,6 +158,7 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap&
unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
std::unordered_map<int64_t, int>& alertTrackerMap,
vector<int>& metricsWithActivation,
+ std::map<int64_t, uint64_t>& stateProtoHashes,
std::set<int64_t>& noReportMetricIds);
} // namespace statsd
diff --git a/cmds/statsd/src/packages/PackageInfoListener.h b/cmds/statsd/src/packages/PackageInfoListener.h
index 6c50a8c41770..1bc84c5433f9 100644
--- a/cmds/statsd/src/packages/PackageInfoListener.h
+++ b/cmds/statsd/src/packages/PackageInfoListener.h
@@ -17,6 +17,8 @@
#ifndef STATSD_PACKAGE_INFO_LISTENER_H
#define STATSD_PACKAGE_INFO_LISTENER_H
+#include <utils/RefBase.h>
+
#include <string>
namespace android {
diff --git a/cmds/statsd/src/packages/UidMap.h b/cmds/statsd/src/packages/UidMap.h
index 22250aee402e..622321b804ec 100644
--- a/cmds/statsd/src/packages/UidMap.h
+++ b/cmds/statsd/src/packages/UidMap.h
@@ -17,7 +17,6 @@
#pragma once
#include "config/ConfigKey.h"
-#include "config/ConfigListener.h"
#include "packages/PackageInfoListener.h"
#include "stats_util.h"
diff --git a/cmds/statsd/src/shell/ShellSubscriber.cpp b/cmds/statsd/src/shell/ShellSubscriber.cpp
index fd883c29dba0..9d8f0c24e253 100644
--- a/cmds/statsd/src/shell/ShellSubscriber.cpp
+++ b/cmds/statsd/src/shell/ShellSubscriber.cpp
@@ -191,7 +191,7 @@ void ShellSubscriber::writePulledAtomsLocked(const vector<std::shared_ptr<LogEve
mProto.clear();
int count = 0;
for (const auto& event : data) {
- if (matchesSimple(*mUidMap, matcher, *event)) {
+ if (matchesSimple(mUidMap, matcher, *event)) {
count++;
uint64_t atomToken = mProto.start(util::FIELD_TYPE_MESSAGE |
util::FIELD_COUNT_REPEATED | FIELD_ID_ATOM);
@@ -209,7 +209,7 @@ void ShellSubscriber::onLogEvent(const LogEvent& event) {
mProto.clear();
for (const auto& matcher : mSubscriptionInfo->mPushedMatchers) {
- if (matchesSimple(*mUidMap, matcher, event)) {
+ if (matchesSimple(mUidMap, matcher, event)) {
uint64_t atomToken = mProto.start(util::FIELD_TYPE_MESSAGE |
util::FIELD_COUNT_REPEATED | FIELD_ID_ATOM);
event.ToProto(mProto);
diff --git a/cmds/statsd/src/stats_log_util.h b/cmds/statsd/src/stats_log_util.h
index eb65dc6979c5..10e065e4113f 100644
--- a/cmds/statsd/src/stats_log_util.h
+++ b/cmds/statsd/src/stats_log_util.h
@@ -97,7 +97,7 @@ bool parseProtoOutputStream(ProtoOutputStream& protoOutput, T* message) {
return message->ParseFromArray(pbBytes.c_str(), pbBytes.size());
}
-// Checks the truncate timestamp annotation as well as the blacklisted range of 300,000 - 304,999.
+// Checks the truncate timestamp annotation as well as the restricted range of 300,000 - 304,999.
// Returns the truncated timestamp to the nearest 5 minutes if needed.
int64_t truncateTimestampIfNecessary(const LogEvent& event);
diff --git a/cmds/statsd/tests/LogEntryMatcher_test.cpp b/cmds/statsd/tests/LogEntryMatcher_test.cpp
index 6264c075426a..92cd04f37ee0 100644
--- a/cmds/statsd/tests/LogEntryMatcher_test.cpp
+++ b/cmds/statsd/tests/LogEntryMatcher_test.cpp
@@ -110,7 +110,7 @@ void makeBoolLogEvent(LogEvent* logEvent, const int32_t atomId, const int64_t ti
} // anonymous namespace
TEST(AtomMatcherTest, TestSimpleMatcher) {
- UidMap uidMap;
+ sp<UidMap> uidMap = new UidMap();
// Set up the matcher
AtomMatcher matcher;
@@ -129,7 +129,7 @@ TEST(AtomMatcherTest, TestSimpleMatcher) {
}
TEST(AtomMatcherTest, TestAttributionMatcher) {
- UidMap uidMap;
+ sp<UidMap> uidMap = new UidMap();
std::vector<int> attributionUids = {1111, 2222, 3333};
std::vector<string> attributionTags = {"location1", "location2", "location3"};
@@ -204,7 +204,7 @@ TEST(AtomMatcherTest, TestAttributionMatcher) {
"pkg0");
EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
- uidMap.updateMap(
+ uidMap->updateMap(
1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
{android::String16("v1"), android::String16("v1"), android::String16("v2"),
android::String16("v1"), android::String16("v2")},
@@ -356,8 +356,8 @@ TEST(AtomMatcherTest, TestAttributionMatcher) {
}
TEST(AtomMatcherTest, TestUidFieldMatcher) {
- UidMap uidMap;
- uidMap.updateMap(
+ sp<UidMap> uidMap = new UidMap();
+ uidMap->updateMap(
1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
{android::String16("v1"), android::String16("v1"), android::String16("v2"),
android::String16("v1"), android::String16("v2")},
@@ -392,8 +392,8 @@ TEST(AtomMatcherTest, TestUidFieldMatcher) {
}
TEST(AtomMatcherTest, TestNeqAnyStringMatcher) {
- UidMap uidMap;
- uidMap.updateMap(
+ sp<UidMap> uidMap = new UidMap();
+ uidMap->updateMap(
1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
{android::String16("v1"), android::String16("v1"), android::String16("v2"),
android::String16("v1"), android::String16("v2")},
@@ -453,8 +453,8 @@ TEST(AtomMatcherTest, TestNeqAnyStringMatcher) {
}
TEST(AtomMatcherTest, TestEqAnyStringMatcher) {
- UidMap uidMap;
- uidMap.updateMap(
+ sp<UidMap> uidMap = new UidMap();
+ uidMap->updateMap(
1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
{android::String16("v1"), android::String16("v1"), android::String16("v2"),
android::String16("v1"), android::String16("v2")},
@@ -517,7 +517,7 @@ TEST(AtomMatcherTest, TestEqAnyStringMatcher) {
}
TEST(AtomMatcherTest, TestBoolMatcher) {
- UidMap uidMap;
+ sp<UidMap> uidMap = new UidMap();
// Set up the matcher
AtomMatcher matcher;
auto simpleMatcher = matcher.mutable_simple_atom_matcher();
@@ -550,7 +550,7 @@ TEST(AtomMatcherTest, TestBoolMatcher) {
}
TEST(AtomMatcherTest, TestStringMatcher) {
- UidMap uidMap;
+ sp<UidMap> uidMap = new UidMap();
// Set up the matcher
AtomMatcher matcher;
auto simpleMatcher = matcher.mutable_simple_atom_matcher();
@@ -568,7 +568,7 @@ TEST(AtomMatcherTest, TestStringMatcher) {
}
TEST(AtomMatcherTest, TestMultiFieldsMatcher) {
- UidMap uidMap;
+ sp<UidMap> uidMap = new UidMap();
// Set up the matcher
AtomMatcher matcher;
auto simpleMatcher = matcher.mutable_simple_atom_matcher();
@@ -597,7 +597,7 @@ TEST(AtomMatcherTest, TestMultiFieldsMatcher) {
}
TEST(AtomMatcherTest, TestIntComparisonMatcher) {
- UidMap uidMap;
+ sp<UidMap> uidMap = new UidMap();
// Set up the matcher
AtomMatcher matcher;
auto simpleMatcher = matcher.mutable_simple_atom_matcher();
@@ -654,7 +654,7 @@ TEST(AtomMatcherTest, TestIntComparisonMatcher) {
}
TEST(AtomMatcherTest, TestFloatComparisonMatcher) {
- UidMap uidMap;
+ sp<UidMap> uidMap = new UidMap();
// Set up the matcher
AtomMatcher matcher;
auto simpleMatcher = matcher.mutable_simple_atom_matcher();
diff --git a/cmds/statsd/tests/MetricsManager_test.cpp b/cmds/statsd/tests/MetricsManager_test.cpp
index 6259757fe092..2dd774e7dfc9 100644
--- a/cmds/statsd/tests/MetricsManager_test.cpp
+++ b/cmds/statsd/tests/MetricsManager_test.cpp
@@ -23,12 +23,12 @@
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
#include "metrics/metrics_test_helper.h"
#include "src/condition/ConditionTracker.h"
-#include "src/matchers/LogMatchingTracker.h"
+#include "src/matchers/AtomMatchingTracker.h"
#include "src/metrics/CountMetricProducer.h"
#include "src/metrics/GaugeMetricProducer.h"
#include "src/metrics/MetricProducer.h"
#include "src/metrics/ValueMetricProducer.h"
-#include "src/metrics/metrics_manager_util.h"
+#include "src/metrics/parsing_utils/metrics_manager_util.h"
#include "src/state/StateManager.h"
#include "statsd_test_util.h"
@@ -48,7 +48,6 @@ namespace statsd {
namespace {
const ConfigKey kConfigKey(0, 12345);
-const long kAlertId = 3;
const long timeBaseSec = 1000;
@@ -90,287 +89,6 @@ StatsdConfig buildGoodConfig() {
metric->set_bucket(ONE_MINUTE);
metric->mutable_dimensions_in_what()->set_field(2 /*SCREEN_STATE_CHANGE*/);
metric->mutable_dimensions_in_what()->add_child()->set_field(1);
-
- config.add_no_report_metric(3);
-
- auto alert = config.add_alert();
- alert->set_id(kAlertId);
- alert->set_metric_id(3);
- alert->set_num_buckets(10);
- alert->set_refractory_period_secs(100);
- alert->set_trigger_if_sum_gt(100);
- return config;
-}
-
-StatsdConfig buildCircleMatchers() {
- StatsdConfig config;
- config.set_id(12345);
-
- AtomMatcher* eventMatcher = config.add_atom_matcher();
- eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
-
- SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
- simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
- simpleAtomMatcher->add_field_value_matcher()->set_field(
- 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
- simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
- 2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
-
- eventMatcher = config.add_atom_matcher();
- eventMatcher->set_id(StringToId("SCREEN_ON_OR_OFF"));
-
- AtomMatcher_Combination* combination = eventMatcher->mutable_combination();
- combination->set_operation(LogicalOperation::OR);
- combination->add_matcher(StringToId("SCREEN_IS_ON"));
- // Circle dependency
- combination->add_matcher(StringToId("SCREEN_ON_OR_OFF"));
-
- return config;
-}
-
-StatsdConfig buildAlertWithUnknownMetric() {
- StatsdConfig config;
- config.set_id(12345);
-
- AtomMatcher* eventMatcher = config.add_atom_matcher();
- eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
-
- CountMetric* metric = config.add_count_metric();
- metric->set_id(3);
- metric->set_what(StringToId("SCREEN_IS_ON"));
- metric->set_bucket(ONE_MINUTE);
- metric->mutable_dimensions_in_what()->set_field(2 /*SCREEN_STATE_CHANGE*/);
- metric->mutable_dimensions_in_what()->add_child()->set_field(1);
-
- auto alert = config.add_alert();
- alert->set_id(3);
- alert->set_metric_id(2);
- alert->set_num_buckets(10);
- alert->set_refractory_period_secs(100);
- alert->set_trigger_if_sum_gt(100);
- return config;
-}
-
-StatsdConfig buildMissingMatchers() {
- StatsdConfig config;
- config.set_id(12345);
-
- AtomMatcher* eventMatcher = config.add_atom_matcher();
- eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
-
- SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
- simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
- simpleAtomMatcher->add_field_value_matcher()->set_field(
- 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
- simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
- 2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
-
- eventMatcher = config.add_atom_matcher();
- eventMatcher->set_id(StringToId("SCREEN_ON_OR_OFF"));
-
- AtomMatcher_Combination* combination = eventMatcher->mutable_combination();
- combination->set_operation(LogicalOperation::OR);
- combination->add_matcher(StringToId("SCREEN_IS_ON"));
- // undefined matcher
- combination->add_matcher(StringToId("ABC"));
-
- return config;
-}
-
-StatsdConfig buildMissingPredicate() {
- StatsdConfig config;
- config.set_id(12345);
-
- CountMetric* metric = config.add_count_metric();
- metric->set_id(3);
- metric->set_what(StringToId("SCREEN_EVENT"));
- metric->set_bucket(ONE_MINUTE);
- metric->set_condition(StringToId("SOME_CONDITION"));
-
- AtomMatcher* eventMatcher = config.add_atom_matcher();
- eventMatcher->set_id(StringToId("SCREEN_EVENT"));
-
- SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
- simpleAtomMatcher->set_atom_id(2);
-
- return config;
-}
-
-StatsdConfig buildDimensionMetricsWithMultiTags() {
- StatsdConfig config;
- config.set_id(12345);
-
- AtomMatcher* eventMatcher = config.add_atom_matcher();
- eventMatcher->set_id(StringToId("BATTERY_VERY_LOW"));
- SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
- simpleAtomMatcher->set_atom_id(2);
-
- eventMatcher = config.add_atom_matcher();
- eventMatcher->set_id(StringToId("BATTERY_VERY_VERY_LOW"));
- simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
- simpleAtomMatcher->set_atom_id(3);
-
- eventMatcher = config.add_atom_matcher();
- eventMatcher->set_id(StringToId("BATTERY_LOW"));
-
- AtomMatcher_Combination* combination = eventMatcher->mutable_combination();
- combination->set_operation(LogicalOperation::OR);
- combination->add_matcher(StringToId("BATTERY_VERY_LOW"));
- combination->add_matcher(StringToId("BATTERY_VERY_VERY_LOW"));
-
- // Count process state changes, slice by uid, while SCREEN_IS_OFF
- CountMetric* metric = config.add_count_metric();
- metric->set_id(3);
- metric->set_what(StringToId("BATTERY_LOW"));
- metric->set_bucket(ONE_MINUTE);
- // This case is interesting. We want to dimension across two atoms.
- metric->mutable_dimensions_in_what()->add_child()->set_field(1);
-
- auto alert = config.add_alert();
- alert->set_id(kAlertId);
- alert->set_metric_id(3);
- alert->set_num_buckets(10);
- alert->set_refractory_period_secs(100);
- alert->set_trigger_if_sum_gt(100);
- return config;
-}
-
-StatsdConfig buildCirclePredicates() {
- StatsdConfig config;
- config.set_id(12345);
-
- AtomMatcher* eventMatcher = config.add_atom_matcher();
- eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
-
- SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
- simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
- simpleAtomMatcher->add_field_value_matcher()->set_field(
- 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
- simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
- 2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
-
- eventMatcher = config.add_atom_matcher();
- eventMatcher->set_id(StringToId("SCREEN_IS_OFF"));
-
- simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
- simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
- simpleAtomMatcher->add_field_value_matcher()->set_field(
- 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
- simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
- 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_OFF*/);
-
- auto condition = config.add_predicate();
- condition->set_id(StringToId("SCREEN_IS_ON"));
- SimplePredicate* simplePredicate = condition->mutable_simple_predicate();
- simplePredicate->set_start(StringToId("SCREEN_IS_ON"));
- simplePredicate->set_stop(StringToId("SCREEN_IS_OFF"));
-
- condition = config.add_predicate();
- condition->set_id(StringToId("SCREEN_IS_EITHER_ON_OFF"));
-
- Predicate_Combination* combination = condition->mutable_combination();
- combination->set_operation(LogicalOperation::OR);
- combination->add_predicate(StringToId("SCREEN_IS_ON"));
- combination->add_predicate(StringToId("SCREEN_IS_EITHER_ON_OFF"));
-
- return config;
-}
-
-StatsdConfig buildConfigWithDifferentPredicates() {
- StatsdConfig config;
- config.set_id(12345);
-
- auto pulledAtomMatcher =
- CreateSimpleAtomMatcher("SUBSYSTEM_SLEEP", util::SUBSYSTEM_SLEEP_STATE);
- *config.add_atom_matcher() = pulledAtomMatcher;
- auto screenOnAtomMatcher = CreateScreenTurnedOnAtomMatcher();
- *config.add_atom_matcher() = screenOnAtomMatcher;
- auto screenOffAtomMatcher = CreateScreenTurnedOffAtomMatcher();
- *config.add_atom_matcher() = screenOffAtomMatcher;
- auto batteryNoneAtomMatcher = CreateBatteryStateNoneMatcher();
- *config.add_atom_matcher() = batteryNoneAtomMatcher;
- auto batteryUsbAtomMatcher = CreateBatteryStateUsbMatcher();
- *config.add_atom_matcher() = batteryUsbAtomMatcher;
-
- // Simple condition with InitialValue set to default (unknown).
- auto screenOnUnknownPredicate = CreateScreenIsOnPredicate();
- *config.add_predicate() = screenOnUnknownPredicate;
-
- // Simple condition with InitialValue set to false.
- auto screenOnFalsePredicate = config.add_predicate();
- screenOnFalsePredicate->set_id(StringToId("ScreenIsOnInitialFalse"));
- SimplePredicate* simpleScreenOnFalsePredicate =
- screenOnFalsePredicate->mutable_simple_predicate();
- simpleScreenOnFalsePredicate->set_start(screenOnAtomMatcher.id());
- simpleScreenOnFalsePredicate->set_stop(screenOffAtomMatcher.id());
- simpleScreenOnFalsePredicate->set_initial_value(SimplePredicate_InitialValue_FALSE);
-
- // Simple condition with InitialValue set to false.
- auto onBatteryFalsePredicate = config.add_predicate();
- onBatteryFalsePredicate->set_id(StringToId("OnBatteryInitialFalse"));
- SimplePredicate* simpleOnBatteryFalsePredicate =
- onBatteryFalsePredicate->mutable_simple_predicate();
- simpleOnBatteryFalsePredicate->set_start(batteryNoneAtomMatcher.id());
- simpleOnBatteryFalsePredicate->set_stop(batteryUsbAtomMatcher.id());
- simpleOnBatteryFalsePredicate->set_initial_value(SimplePredicate_InitialValue_FALSE);
-
- // Combination condition with both simple condition InitialValues set to false.
- auto screenOnFalseOnBatteryFalsePredicate = config.add_predicate();
- screenOnFalseOnBatteryFalsePredicate->set_id(StringToId("ScreenOnFalseOnBatteryFalse"));
- screenOnFalseOnBatteryFalsePredicate->mutable_combination()->set_operation(
- LogicalOperation::AND);
- addPredicateToPredicateCombination(*screenOnFalsePredicate,
- screenOnFalseOnBatteryFalsePredicate);
- addPredicateToPredicateCombination(*onBatteryFalsePredicate,
- screenOnFalseOnBatteryFalsePredicate);
-
- // Combination condition with one simple condition InitialValue set to unknown and one set to
- // false.
- auto screenOnUnknownOnBatteryFalsePredicate = config.add_predicate();
- screenOnUnknownOnBatteryFalsePredicate->set_id(StringToId("ScreenOnUnknowneOnBatteryFalse"));
- screenOnUnknownOnBatteryFalsePredicate->mutable_combination()->set_operation(
- LogicalOperation::AND);
- addPredicateToPredicateCombination(screenOnUnknownPredicate,
- screenOnUnknownOnBatteryFalsePredicate);
- addPredicateToPredicateCombination(*onBatteryFalsePredicate,
- screenOnUnknownOnBatteryFalsePredicate);
-
- // Simple condition metric with initial value false.
- ValueMetric* metric1 = config.add_value_metric();
- metric1->set_id(StringToId("ValueSubsystemSleepWhileScreenOnInitialFalse"));
- metric1->set_what(pulledAtomMatcher.id());
- *metric1->mutable_value_field() =
- CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
- metric1->set_bucket(FIVE_MINUTES);
- metric1->set_condition(screenOnFalsePredicate->id());
-
- // Simple condition metric with initial value unknown.
- ValueMetric* metric2 = config.add_value_metric();
- metric2->set_id(StringToId("ValueSubsystemSleepWhileScreenOnInitialUnknown"));
- metric2->set_what(pulledAtomMatcher.id());
- *metric2->mutable_value_field() =
- CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
- metric2->set_bucket(FIVE_MINUTES);
- metric2->set_condition(screenOnUnknownPredicate.id());
-
- // Combination condition metric with initial values false and false.
- ValueMetric* metric3 = config.add_value_metric();
- metric3->set_id(StringToId("ValueSubsystemSleepWhileScreenOnFalseDeviceUnpluggedFalse"));
- metric3->set_what(pulledAtomMatcher.id());
- *metric3->mutable_value_field() =
- CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
- metric3->set_bucket(FIVE_MINUTES);
- metric3->set_condition(screenOnFalseOnBatteryFalsePredicate->id());
-
- // Combination condition metric with initial values unknown and false.
- ValueMetric* metric4 = config.add_value_metric();
- metric4->set_id(StringToId("ValueSubsystemSleepWhileScreenOnUnknownDeviceUnpluggedFalse"));
- metric4->set_what(pulledAtomMatcher.id());
- *metric4->mutable_value_field() =
- CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
- metric4->set_bucket(FIVE_MINUTES);
- metric4->set_condition(screenOnUnknownOnBatteryFalsePredicate->id());
-
return config;
}
@@ -379,274 +97,6 @@ bool isSubset(const set<int32_t>& set1, const set<int32_t>& set2) {
}
} // anonymous namespace
-TEST(MetricsManagerTest, TestInitialConditions) {
- UidMap uidMap;
- sp<StatsPullerManager> pullerManager = new StatsPullerManager();
- sp<AlarmMonitor> anomalyAlarmMonitor;
- sp<AlarmMonitor> periodicAlarmMonitor;
- StatsdConfig config = buildConfigWithDifferentPredicates();
- set<int> allTagIds;
- vector<sp<LogMatchingTracker>> allAtomMatchers;
- vector<sp<ConditionTracker>> allConditionTrackers;
- vector<sp<MetricProducer>> allMetricProducers;
- std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
- std::vector<sp<AlarmTracker>> allAlarmTrackers;
- unordered_map<int, std::vector<int>> conditionToMetricMap;
- unordered_map<int, std::vector<int>> trackerToMetricMap;
- unordered_map<int, std::vector<int>> trackerToConditionMap;
- unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
- unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
- unordered_map<int64_t, int> alertTrackerMap;
- vector<int> metricsWithActivation;
- std::set<int64_t> noReportMetricIds;
-
- EXPECT_TRUE(initStatsdConfig(
- kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
- timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, allConditionTrackers,
- allMetricProducers, allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
- trackerToMetricMap, trackerToConditionMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation,
- noReportMetricIds));
- ASSERT_EQ(4u, allMetricProducers.size());
- ASSERT_EQ(5u, allConditionTrackers.size());
-
- ConditionKey queryKey;
- vector<ConditionState> conditionCache(5, ConditionState::kNotEvaluated);
-
- allConditionTrackers[3]->isConditionMet(queryKey, allConditionTrackers, false, conditionCache);
- allConditionTrackers[4]->isConditionMet(queryKey, allConditionTrackers, false, conditionCache);
- EXPECT_EQ(ConditionState::kUnknown, conditionCache[0]);
- EXPECT_EQ(ConditionState::kFalse, conditionCache[1]);
- EXPECT_EQ(ConditionState::kFalse, conditionCache[2]);
- EXPECT_EQ(ConditionState::kFalse, conditionCache[3]);
- EXPECT_EQ(ConditionState::kUnknown, conditionCache[4]);
-
- EXPECT_EQ(ConditionState::kFalse, allMetricProducers[0]->mCondition);
- EXPECT_EQ(ConditionState::kUnknown, allMetricProducers[1]->mCondition);
- EXPECT_EQ(ConditionState::kFalse, allMetricProducers[2]->mCondition);
- EXPECT_EQ(ConditionState::kUnknown, allMetricProducers[3]->mCondition);
-}
-
-TEST(MetricsManagerTest, TestGoodConfig) {
- UidMap uidMap;
- sp<StatsPullerManager> pullerManager = new StatsPullerManager();
- sp<AlarmMonitor> anomalyAlarmMonitor;
- sp<AlarmMonitor> periodicAlarmMonitor;
- StatsdConfig config = buildGoodConfig();
- set<int> allTagIds;
- vector<sp<LogMatchingTracker>> allAtomMatchers;
- vector<sp<ConditionTracker>> allConditionTrackers;
- vector<sp<MetricProducer>> allMetricProducers;
- std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
- std::vector<sp<AlarmTracker>> allAlarmTrackers;
- unordered_map<int, std::vector<int>> conditionToMetricMap;
- unordered_map<int, std::vector<int>> trackerToMetricMap;
- unordered_map<int, std::vector<int>> trackerToConditionMap;
- unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
- unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
- unordered_map<int64_t, int> alertTrackerMap;
- vector<int> metricsWithActivation;
- std::set<int64_t> noReportMetricIds;
-
- EXPECT_TRUE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
- periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
- allAtomMatchers, allConditionTrackers, allMetricProducers,
- allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
- trackerToMetricMap, trackerToConditionMap,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- alertTrackerMap, metricsWithActivation,
- noReportMetricIds));
- ASSERT_EQ(1u, allMetricProducers.size());
- ASSERT_EQ(1u, allAnomalyTrackers.size());
- ASSERT_EQ(1u, noReportMetricIds.size());
- ASSERT_EQ(1u, alertTrackerMap.size());
- EXPECT_NE(alertTrackerMap.find(kAlertId), alertTrackerMap.end());
- EXPECT_EQ(alertTrackerMap.find(kAlertId)->second, 0);
-}
-
-TEST(MetricsManagerTest, TestDimensionMetricsWithMultiTags) {
- UidMap uidMap;
- sp<StatsPullerManager> pullerManager = new StatsPullerManager();
- sp<AlarmMonitor> anomalyAlarmMonitor;
- sp<AlarmMonitor> periodicAlarmMonitor;
- StatsdConfig config = buildDimensionMetricsWithMultiTags();
- set<int> allTagIds;
- vector<sp<LogMatchingTracker>> allAtomMatchers;
- vector<sp<ConditionTracker>> allConditionTrackers;
- vector<sp<MetricProducer>> allMetricProducers;
- std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
- std::vector<sp<AlarmTracker>> allAlarmTrackers;
- unordered_map<int, std::vector<int>> conditionToMetricMap;
- unordered_map<int, std::vector<int>> trackerToMetricMap;
- unordered_map<int, std::vector<int>> trackerToConditionMap;
- unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
- unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
- unordered_map<int64_t, int> alertTrackerMap;
- vector<int> metricsWithActivation;
- std::set<int64_t> noReportMetricIds;
-
- EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
- periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
- allAtomMatchers, allConditionTrackers, allMetricProducers,
- allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
- trackerToMetricMap, trackerToConditionMap,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- alertTrackerMap, metricsWithActivation,
- noReportMetricIds));
-}
-
-TEST(MetricsManagerTest, TestCircleLogMatcherDependency) {
- UidMap uidMap;
- sp<StatsPullerManager> pullerManager = new StatsPullerManager();
- sp<AlarmMonitor> anomalyAlarmMonitor;
- sp<AlarmMonitor> periodicAlarmMonitor;
- StatsdConfig config = buildCircleMatchers();
- set<int> allTagIds;
- vector<sp<LogMatchingTracker>> allAtomMatchers;
- vector<sp<ConditionTracker>> allConditionTrackers;
- vector<sp<MetricProducer>> allMetricProducers;
- std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
- std::vector<sp<AlarmTracker>> allAlarmTrackers;
- unordered_map<int, std::vector<int>> conditionToMetricMap;
- unordered_map<int, std::vector<int>> trackerToMetricMap;
- unordered_map<int, std::vector<int>> trackerToConditionMap;
- unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
- unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
- unordered_map<int64_t, int> alertTrackerMap;
- vector<int> metricsWithActivation;
- std::set<int64_t> noReportMetricIds;
-
- EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
- periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
- allAtomMatchers, allConditionTrackers, allMetricProducers,
- allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
- trackerToMetricMap, trackerToConditionMap,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- alertTrackerMap, metricsWithActivation,
- noReportMetricIds));
-}
-
-TEST(MetricsManagerTest, TestMissingMatchers) {
- UidMap uidMap;
- sp<StatsPullerManager> pullerManager = new StatsPullerManager();
- sp<AlarmMonitor> anomalyAlarmMonitor;
- sp<AlarmMonitor> periodicAlarmMonitor;
- StatsdConfig config = buildMissingMatchers();
- set<int> allTagIds;
- vector<sp<LogMatchingTracker>> allAtomMatchers;
- vector<sp<ConditionTracker>> allConditionTrackers;
- vector<sp<MetricProducer>> allMetricProducers;
- std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
- std::vector<sp<AlarmTracker>> allAlarmTrackers;
- unordered_map<int, std::vector<int>> conditionToMetricMap;
- unordered_map<int, std::vector<int>> trackerToMetricMap;
- unordered_map<int, std::vector<int>> trackerToConditionMap;
- unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
- unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
- unordered_map<int64_t, int> alertTrackerMap;
- vector<int> metricsWithActivation;
- std::set<int64_t> noReportMetricIds;
- EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
- periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
- allAtomMatchers, allConditionTrackers, allMetricProducers,
- allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
- trackerToMetricMap, trackerToConditionMap,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- alertTrackerMap, metricsWithActivation,
- noReportMetricIds));
-}
-
-TEST(MetricsManagerTest, TestMissingPredicate) {
- UidMap uidMap;
- sp<StatsPullerManager> pullerManager = new StatsPullerManager();
- sp<AlarmMonitor> anomalyAlarmMonitor;
- sp<AlarmMonitor> periodicAlarmMonitor;
- StatsdConfig config = buildMissingPredicate();
- set<int> allTagIds;
- vector<sp<LogMatchingTracker>> allAtomMatchers;
- vector<sp<ConditionTracker>> allConditionTrackers;
- vector<sp<MetricProducer>> allMetricProducers;
- std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
- std::vector<sp<AlarmTracker>> allAlarmTrackers;
- unordered_map<int, std::vector<int>> conditionToMetricMap;
- unordered_map<int, std::vector<int>> trackerToMetricMap;
- unordered_map<int, std::vector<int>> trackerToConditionMap;
- unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
- unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
- unordered_map<int64_t, int> alertTrackerMap;
- vector<int> metricsWithActivation;
- std::set<int64_t> noReportMetricIds;
- EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
- periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
- allAtomMatchers, allConditionTrackers, allMetricProducers,
- allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
- trackerToMetricMap, trackerToConditionMap,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- alertTrackerMap, metricsWithActivation, noReportMetricIds));
-}
-
-TEST(MetricsManagerTest, TestCirclePredicateDependency) {
- UidMap uidMap;
- sp<StatsPullerManager> pullerManager = new StatsPullerManager();
- sp<AlarmMonitor> anomalyAlarmMonitor;
- sp<AlarmMonitor> periodicAlarmMonitor;
- StatsdConfig config = buildCirclePredicates();
- set<int> allTagIds;
- vector<sp<LogMatchingTracker>> allAtomMatchers;
- vector<sp<ConditionTracker>> allConditionTrackers;
- vector<sp<MetricProducer>> allMetricProducers;
- std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
- std::vector<sp<AlarmTracker>> allAlarmTrackers;
- unordered_map<int, std::vector<int>> conditionToMetricMap;
- unordered_map<int, std::vector<int>> trackerToMetricMap;
- unordered_map<int, std::vector<int>> trackerToConditionMap;
- unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
- unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
- unordered_map<int64_t, int> alertTrackerMap;
- vector<int> metricsWithActivation;
- std::set<int64_t> noReportMetricIds;
-
- EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
- periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
- allAtomMatchers, allConditionTrackers, allMetricProducers,
- allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
- trackerToMetricMap, trackerToConditionMap,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- alertTrackerMap, metricsWithActivation,
- noReportMetricIds));
-}
-
-TEST(MetricsManagerTest, testAlertWithUnknownMetric) {
- UidMap uidMap;
- sp<StatsPullerManager> pullerManager = new StatsPullerManager();
- sp<AlarmMonitor> anomalyAlarmMonitor;
- sp<AlarmMonitor> periodicAlarmMonitor;
- StatsdConfig config = buildAlertWithUnknownMetric();
- set<int> allTagIds;
- vector<sp<LogMatchingTracker>> allAtomMatchers;
- vector<sp<ConditionTracker>> allConditionTrackers;
- vector<sp<MetricProducer>> allMetricProducers;
- std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
- std::vector<sp<AlarmTracker>> allAlarmTrackers;
- unordered_map<int, std::vector<int>> conditionToMetricMap;
- unordered_map<int, std::vector<int>> trackerToMetricMap;
- unordered_map<int, std::vector<int>> trackerToConditionMap;
- unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
- unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
- unordered_map<int64_t, int> alertTrackerMap;
- vector<int> metricsWithActivation;
- std::set<int64_t> noReportMetricIds;
-
- EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
- periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
- allAtomMatchers, allConditionTrackers, allMetricProducers,
- allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
- trackerToMetricMap, trackerToConditionMap,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- alertTrackerMap, metricsWithActivation,
- noReportMetricIds));
-}
-
TEST(MetricsManagerTest, TestLogSources) {
string app1 = "app1";
set<int32_t> app1Uids = {1111, 11111};
@@ -680,7 +130,7 @@ TEST(MetricsManagerTest, TestLogSources) {
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> periodicAlarmMonitor;
- StatsdConfig config = buildGoodConfig();
+ StatsdConfig config;
config.add_allowed_log_source("AID_SYSTEM");
config.add_allowed_log_source(app1);
config.add_default_pull_packages("AID_SYSTEM");
@@ -744,7 +194,7 @@ TEST(MetricsManagerTest, TestCheckLogCredentialsWhitelistedAtom) {
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> periodicAlarmMonitor;
- StatsdConfig config = buildGoodConfig();
+ StatsdConfig config;
config.add_whitelisted_atom_ids(3);
config.add_whitelisted_atom_ids(4);
diff --git a/cmds/statsd/tests/StatsLogProcessor_test.cpp b/cmds/statsd/tests/StatsLogProcessor_test.cpp
index 1e6680c47567..1409b621fdf6 100644
--- a/cmds/statsd/tests/StatsLogProcessor_test.cpp
+++ b/cmds/statsd/tests/StatsLogProcessor_test.cpp
@@ -68,7 +68,7 @@ TEST(StatsLogProcessorTest, TestRateLimitByteSize) {
sp<StatsPullerManager> pullerManager = new StatsPullerManager();
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> periodicAlarmMonitor;
- // Construct the processor with a dummy sendBroadcast function that does nothing.
+ // Construct the processor with a no-op sendBroadcast function that does nothing.
StatsLogProcessor p(m, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor, 0,
[](const ConfigKey& key) { return true; },
[](const int&, const vector<int64_t>&) {return true;});
@@ -896,8 +896,8 @@ TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivations) {
EXPECT_TRUE(metricProducer2->isActive());
int i = 0;
- for (; i < metricsManager1->mAllAtomMatchers.size(); i++) {
- if (metricsManager1->mAllAtomMatchers[i]->getId() ==
+ for (; i < metricsManager1->mAllAtomMatchingTrackers.size(); i++) {
+ if (metricsManager1->mAllAtomMatchingTrackers[i]->getId() ==
metric1ActivationTrigger1->atom_matcher_id()) {
break;
}
@@ -908,8 +908,8 @@ TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivations) {
EXPECT_EQ(kNotActive, activation1->state);
i = 0;
- for (; i < metricsManager1->mAllAtomMatchers.size(); i++) {
- if (metricsManager1->mAllAtomMatchers[i]->getId() ==
+ for (; i < metricsManager1->mAllAtomMatchingTrackers.size(); i++) {
+ if (metricsManager1->mAllAtomMatchingTrackers[i]->getId() ==
metric1ActivationTrigger2->atom_matcher_id()) {
break;
}
@@ -981,8 +981,8 @@ TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivations) {
EXPECT_TRUE(metricProducer1002->isActive());
i = 0;
- for (; i < metricsManager1001->mAllAtomMatchers.size(); i++) {
- if (metricsManager1001->mAllAtomMatchers[i]->getId() ==
+ for (; i < metricsManager1001->mAllAtomMatchingTrackers.size(); i++) {
+ if (metricsManager1001->mAllAtomMatchingTrackers[i]->getId() ==
metric1ActivationTrigger1->atom_matcher_id()) {
break;
}
@@ -993,8 +993,8 @@ TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivations) {
EXPECT_EQ(kNotActive, activation1001_1->state);
i = 0;
- for (; i < metricsManager1001->mAllAtomMatchers.size(); i++) {
- if (metricsManager1001->mAllAtomMatchers[i]->getId() ==
+ for (; i < metricsManager1001->mAllAtomMatchingTrackers.size(); i++) {
+ if (metricsManager1001->mAllAtomMatchingTrackers[i]->getId() ==
metric1ActivationTrigger2->atom_matcher_id()) {
break;
}
@@ -1082,8 +1082,8 @@ TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivations) {
EXPECT_TRUE(metricProducerTimeBase3_2->isActive());
i = 0;
- for (; i < metricsManagerTimeBase3->mAllAtomMatchers.size(); i++) {
- if (metricsManagerTimeBase3->mAllAtomMatchers[i]->getId() ==
+ for (; i < metricsManagerTimeBase3->mAllAtomMatchingTrackers.size(); i++) {
+ if (metricsManagerTimeBase3->mAllAtomMatchingTrackers[i]->getId() ==
metric1ActivationTrigger1->atom_matcher_id()) {
break;
}
@@ -1094,8 +1094,8 @@ TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivations) {
EXPECT_EQ(kNotActive, activationTimeBase3_1->state);
i = 0;
- for (; i < metricsManagerTimeBase3->mAllAtomMatchers.size(); i++) {
- if (metricsManagerTimeBase3->mAllAtomMatchers[i]->getId() ==
+ for (; i < metricsManagerTimeBase3->mAllAtomMatchingTrackers.size(); i++) {
+ if (metricsManagerTimeBase3->mAllAtomMatchingTrackers[i]->getId() ==
metric1ActivationTrigger2->atom_matcher_id()) {
break;
}
@@ -1184,8 +1184,8 @@ TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivations) {
EXPECT_TRUE(metricProducerTimeBase4_2->isActive());
i = 0;
- for (; i < metricsManagerTimeBase4->mAllAtomMatchers.size(); i++) {
- if (metricsManagerTimeBase4->mAllAtomMatchers[i]->getId() ==
+ for (; i < metricsManagerTimeBase4->mAllAtomMatchingTrackers.size(); i++) {
+ if (metricsManagerTimeBase4->mAllAtomMatchingTrackers[i]->getId() ==
metric1ActivationTrigger1->atom_matcher_id()) {
break;
}
@@ -1196,8 +1196,8 @@ TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivations) {
EXPECT_EQ(kNotActive, activationTimeBase4_1->state);
i = 0;
- for (; i < metricsManagerTimeBase4->mAllAtomMatchers.size(); i++) {
- if (metricsManagerTimeBase4->mAllAtomMatchers[i]->getId() ==
+ for (; i < metricsManagerTimeBase4->mAllAtomMatchingTrackers.size(); i++) {
+ if (metricsManagerTimeBase4->mAllAtomMatchingTrackers[i]->getId() ==
metric1ActivationTrigger2->atom_matcher_id()) {
break;
}
@@ -1585,8 +1585,8 @@ TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart) {
EXPECT_TRUE(metricProducer3->isActive());
// Check event activations.
- ASSERT_EQ(metricsManager1->mAllAtomMatchers.size(), 4);
- EXPECT_EQ(metricsManager1->mAllAtomMatchers[0]->getId(),
+ ASSERT_EQ(metricsManager1->mAllAtomMatchingTrackers.size(), 4);
+ EXPECT_EQ(metricsManager1->mAllAtomMatchingTrackers[0]->getId(),
metric1ActivationTrigger1->atom_matcher_id());
const auto& activation1 = metricProducer1->mEventActivationMap.at(0);
EXPECT_EQ(100 * NS_PER_SEC, activation1->ttl_ns);
@@ -1594,7 +1594,7 @@ TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart) {
EXPECT_EQ(kNotActive, activation1->state);
EXPECT_EQ(ACTIVATE_ON_BOOT, activation1->activationType);
- EXPECT_EQ(metricsManager1->mAllAtomMatchers[1]->getId(),
+ EXPECT_EQ(metricsManager1->mAllAtomMatchingTrackers[1]->getId(),
metric1ActivationTrigger2->atom_matcher_id());
const auto& activation2 = metricProducer1->mEventActivationMap.at(1);
EXPECT_EQ(200 * NS_PER_SEC, activation2->ttl_ns);
@@ -1602,7 +1602,7 @@ TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart) {
EXPECT_EQ(kNotActive, activation2->state);
EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation2->activationType);
- EXPECT_EQ(metricsManager1->mAllAtomMatchers[2]->getId(),
+ EXPECT_EQ(metricsManager1->mAllAtomMatchingTrackers[2]->getId(),
metric2ActivationTrigger1->atom_matcher_id());
const auto& activation3 = metricProducer2->mEventActivationMap.at(2);
EXPECT_EQ(100 * NS_PER_SEC, activation3->ttl_ns);
@@ -1610,7 +1610,7 @@ TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart) {
EXPECT_EQ(kNotActive, activation3->state);
EXPECT_EQ(ACTIVATE_ON_BOOT, activation3->activationType);
- EXPECT_EQ(metricsManager1->mAllAtomMatchers[3]->getId(),
+ EXPECT_EQ(metricsManager1->mAllAtomMatchingTrackers[3]->getId(),
metric2ActivationTrigger2->atom_matcher_id());
const auto& activation4 = metricProducer2->mEventActivationMap.at(3);
EXPECT_EQ(200 * NS_PER_SEC, activation4->ttl_ns);
@@ -1685,8 +1685,8 @@ TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart) {
// Activation 1 is kActiveOnBoot.
// Activation 2 and 3 are not active.
// Activation 4 is active.
- ASSERT_EQ(metricsManager2->mAllAtomMatchers.size(), 4);
- EXPECT_EQ(metricsManager2->mAllAtomMatchers[0]->getId(),
+ ASSERT_EQ(metricsManager2->mAllAtomMatchingTrackers.size(), 4);
+ EXPECT_EQ(metricsManager2->mAllAtomMatchingTrackers[0]->getId(),
metric1ActivationTrigger1->atom_matcher_id());
const auto& activation1001 = metricProducer1001->mEventActivationMap.at(0);
EXPECT_EQ(100 * NS_PER_SEC, activation1001->ttl_ns);
@@ -1694,7 +1694,7 @@ TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart) {
EXPECT_EQ(kActiveOnBoot, activation1001->state);
EXPECT_EQ(ACTIVATE_ON_BOOT, activation1001->activationType);
- EXPECT_EQ(metricsManager2->mAllAtomMatchers[1]->getId(),
+ EXPECT_EQ(metricsManager2->mAllAtomMatchingTrackers[1]->getId(),
metric1ActivationTrigger2->atom_matcher_id());
const auto& activation1002 = metricProducer1001->mEventActivationMap.at(1);
EXPECT_EQ(200 * NS_PER_SEC, activation1002->ttl_ns);
@@ -1702,7 +1702,7 @@ TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart) {
EXPECT_EQ(kNotActive, activation1002->state);
EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation1002->activationType);
- EXPECT_EQ(metricsManager2->mAllAtomMatchers[2]->getId(),
+ EXPECT_EQ(metricsManager2->mAllAtomMatchingTrackers[2]->getId(),
metric2ActivationTrigger1->atom_matcher_id());
const auto& activation1003 = metricProducer1002->mEventActivationMap.at(2);
EXPECT_EQ(100 * NS_PER_SEC, activation1003->ttl_ns);
@@ -1710,7 +1710,7 @@ TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart) {
EXPECT_EQ(kNotActive, activation1003->state);
EXPECT_EQ(ACTIVATE_ON_BOOT, activation1003->activationType);
- EXPECT_EQ(metricsManager2->mAllAtomMatchers[3]->getId(),
+ EXPECT_EQ(metricsManager2->mAllAtomMatchingTrackers[3]->getId(),
metric2ActivationTrigger2->atom_matcher_id());
const auto& activation1004 = metricProducer1002->mEventActivationMap.at(3);
EXPECT_EQ(200 * NS_PER_SEC, activation1004->ttl_ns);
diff --git a/cmds/statsd/tests/UidMap_test.cpp b/cmds/statsd/tests/UidMap_test.cpp
index 293e8ed1c44c..33bdc64333e0 100644
--- a/cmds/statsd/tests/UidMap_test.cpp
+++ b/cmds/statsd/tests/UidMap_test.cpp
@@ -44,7 +44,7 @@ TEST(UidMapTest, TestIsolatedUID) {
sp<StatsPullerManager> pullerManager = new StatsPullerManager();
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> subscriberAlarmMonitor;
- // Construct the processor with a dummy sendBroadcast function that does nothing.
+ // Construct the processor with a no-op sendBroadcast function that does nothing.
StatsLogProcessor p(
m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor, 0,
[](const ConfigKey& key) { return true; },
diff --git a/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp b/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp
index 07b5311b1207..8998b5f98df5 100644
--- a/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp
+++ b/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp
@@ -39,6 +39,7 @@ const ConfigKey kConfigKey(0, 12345);
const int ATTRIBUTION_NODE_FIELD_ID = 1;
const int ATTRIBUTION_UID_FIELD_ID = 1;
const int TAG_ID = 1;
+const uint64_t protoHash = 0x123456789;
SimplePredicate getWakeLockHeldCondition(bool countNesting, bool defaultFalse,
bool outputSlicedUid, Position position) {
@@ -123,7 +124,7 @@ TEST(SimpleConditionTrackerTest, TestNonSlicedInitialValueFalse) {
trackerNameIndexMap[StringToId("SCREEN_TURNED_ON")] = 0;
trackerNameIndexMap[StringToId("SCREEN_TURNED_OFF")] = 1;
- SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"),
+ SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"), protoHash,
0 /*tracker index*/, simplePredicate,
trackerNameIndexMap);
@@ -177,7 +178,7 @@ TEST(SimpleConditionTrackerTest, TestNonSlicedInitialValueUnknown) {
trackerNameIndexMap[StringToId("SCREEN_TURNED_ON")] = 0;
trackerNameIndexMap[StringToId("SCREEN_TURNED_OFF")] = 1;
- SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"),
+ SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"), protoHash,
0 /*tracker index*/, simplePredicate,
trackerNameIndexMap);
@@ -231,8 +232,9 @@ TEST(SimpleConditionTrackerTest, TestNonSlicedCondition) {
trackerNameIndexMap[StringToId("SCREEN_TURNED_ON")] = 0;
trackerNameIndexMap[StringToId("SCREEN_TURNED_OFF")] = 1;
- SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"), 0 /*tracker index*/,
- simplePredicate, trackerNameIndexMap);
+ SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"), protoHash,
+ 0 /*tracker index*/, simplePredicate,
+ trackerNameIndexMap);
EXPECT_FALSE(conditionTracker.isSliced());
// This event is not accessed in this test besides dimensions which is why this is okay.
@@ -317,7 +319,7 @@ TEST(SimpleConditionTrackerTest, TestNonSlicedConditionNestCounting) {
trackerNameIndexMap[StringToId("SCREEN_TURNED_ON")] = 0;
trackerNameIndexMap[StringToId("SCREEN_TURNED_OFF")] = 1;
- SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"),
+ SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"), protoHash,
0 /*condition tracker index*/, simplePredicate,
trackerNameIndexMap);
EXPECT_FALSE(conditionTracker.isSliced());
@@ -392,7 +394,7 @@ TEST(SimpleConditionTrackerTest, TestSlicedCondition) {
trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
- SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
+ SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName), protoHash,
0 /*condition tracker index*/, simplePredicate,
trackerNameIndexMap);
@@ -514,7 +516,7 @@ TEST(SimpleConditionTrackerTest, TestSlicedWithNoOutputDim) {
trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
- SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
+ SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName), protoHash,
0 /*condition tracker index*/, simplePredicate,
trackerNameIndexMap);
@@ -610,7 +612,7 @@ TEST(SimpleConditionTrackerTest, TestStopAll) {
trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
- SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
+ SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName), protoHash,
0 /*condition tracker index*/, simplePredicate,
trackerNameIndexMap);
diff --git a/cmds/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp b/cmds/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp
index 95e301002a1b..70e7365ec238 100644
--- a/cmds/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp
@@ -12,14 +12,19 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include <android/binder_ibinder.h>
+#include <android/binder_interface_utils.h>
#include <gtest/gtest.h>
-#include "src/anomaly/DurationAnomalyTracker.h"
+#include <vector>
+
#include "src/StatsLogProcessor.h"
+#include "src/StatsService.h"
+#include "src/anomaly/DurationAnomalyTracker.h"
#include "src/stats_log_util.h"
#include "tests/statsd_test_util.h"
-#include <vector>
+using ::ndk::SharedRefBase;
namespace android {
namespace os {
@@ -29,6 +34,9 @@ namespace statsd {
namespace {
+const int kConfigKey = 789130124;
+const int kCallingUid = 0;
+
StatsdConfig CreateStatsdConfig(int num_buckets,
uint64_t threshold_ns,
DurationMetric::AggregationType aggregationType,
@@ -89,6 +97,13 @@ MetricDimensionKey dimensionKey2(
(int32_t)0x02010101), Value((int32_t)222))}),
DEFAULT_DIMENSION_KEY);
+void sendConfig(shared_ptr<StatsService>& service, const StatsdConfig& config) {
+ string str;
+ config.SerializeToString(&str);
+ std::vector<uint8_t> configAsVec(str.begin(), str.end());
+ service->addConfiguration(kConfigKey, configAsVec, kCallingUid);
+}
+
} // namespace
TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
@@ -98,16 +113,18 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
const uint64_t alert_id = config.alert(0).id();
const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
- int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
- int64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000;
+ shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
+ sendConfig(service, config);
- ConfigKey cfgKey;
- auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+ auto processor = service->mProcessor;
ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
ASSERT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
+ int64_t bucketStartTimeNs = processor->mTimeBaseNs;
+ int64_t roundedBucketStartTimeNs = bucketStartTimeNs / NS_PER_SEC * NS_PER_SEC;
+ int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1e6;
+
sp<AnomalyTracker> anomalyTracker =
processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
@@ -158,12 +175,13 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
const int64_t alarmFiredTimestampSec0 = anomalyTracker->getAlarmTimestampSec(dimensionKey1);
EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + NS_PER_SEC + 109) / NS_PER_SEC + 1,
(uint32_t)alarmFiredTimestampSec0);
+ EXPECT_EQ(alarmFiredTimestampSec0,
+ processor->getAnomalyAlarmMonitor()->getRegisteredAlarmTimeSec());
// Anomaly alarm fired.
- auto alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
- static_cast<uint32_t>(alarmFiredTimestampSec0));
- ASSERT_EQ(1u, alarmSet.size());
- processor->onAnomalyAlarmFired(alarmFiredTimestampSec0 * NS_PER_SEC, alarmSet);
+ auto alarmTriggerEvent = CreateBatterySaverOnEvent(alarmFiredTimestampSec0 * NS_PER_SEC);
+ processor->OnLogEvent(alarmTriggerEvent.get(), alarmFiredTimestampSec0 * NS_PER_SEC);
+
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(refractory_period_sec + alarmFiredTimestampSec0,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
@@ -179,39 +197,39 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Acquire wakelock wl1.
- acquire_event =
- CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs - 5 * NS_PER_SEC - 11,
- attributionUids2, attributionTags2, "wl1");
+ acquire_event = CreateAcquireWakelockEvent(
+ roundedBucketStartTimeNs + bucketSizeNs - 5 * NS_PER_SEC - 11, attributionUids2,
+ attributionTags2, "wl1");
processor->OnLogEvent(acquire_event.get());
const int64_t alarmFiredTimestampSec1 = anomalyTracker->getAlarmTimestampSec(dimensionKey1);
EXPECT_EQ((bucketStartTimeNs + bucketSizeNs - 5 * NS_PER_SEC) / NS_PER_SEC,
(uint64_t)alarmFiredTimestampSec1);
// Release wakelock wl1.
- release_event =
- CreateReleaseWakelockEvent(bucketStartTimeNs + bucketSizeNs - 4 * NS_PER_SEC - 10,
- attributionUids2, attributionTags2, "wl1");
- processor->OnLogEvent(release_event.get());
+ int64_t release_event_time = roundedBucketStartTimeNs + bucketSizeNs - 4 * NS_PER_SEC - 10;
+ release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids2,
+ attributionTags2, "wl1");
+ processor->OnLogEvent(release_event.get(), release_event_time);
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
- EXPECT_EQ(refractory_period_sec +
- (bucketStartTimeNs + bucketSizeNs - 4 * NS_PER_SEC - 10) / NS_PER_SEC + 1,
+ EXPECT_EQ(refractory_period_sec + (release_event_time) / NS_PER_SEC + 1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
- alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
+ auto alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
static_cast<uint32_t>(alarmFiredTimestampSec1));
ASSERT_EQ(0u, alarmSet.size());
// Acquire wakelock wl1 near the end of bucket #0.
- acquire_event = CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs - 2,
+ acquire_event = CreateAcquireWakelockEvent(roundedBucketStartTimeNs + bucketSizeNs - 2,
attributionUids1, attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
// Release the event at early bucket #1.
- release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + bucketSizeNs + NS_PER_SEC - 1,
- attributionUids1, attributionTags1, "wl1");
- processor->OnLogEvent(release_event.get());
+ release_event_time = roundedBucketStartTimeNs + bucketSizeNs + NS_PER_SEC - 1;
+ release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids1,
+ attributionTags1, "wl1");
+ processor->OnLogEvent(release_event.get(), release_event_time);
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
// Anomaly detected when stopping the alarm. The refractory period does not change.
EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + NS_PER_SEC) / NS_PER_SEC,
@@ -236,17 +254,17 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
// Condition turns true.
screen_off_event =
- CreateScreenStateChangedEvent(bucketStartTimeNs + 2 * bucketSizeNs + NS_PER_SEC,
+ CreateScreenStateChangedEvent(roundedBucketStartTimeNs + 2 * bucketSizeNs + NS_PER_SEC,
android::view::DisplayStateEnum::DISPLAY_STATE_OFF);
processor->OnLogEvent(screen_off_event.get());
EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs + NS_PER_SEC + threshold_ns) / NS_PER_SEC,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
// Condition turns to false.
- screen_on_event =
- CreateScreenStateChangedEvent(bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC + 1,
- android::view::DisplayStateEnum::DISPLAY_STATE_ON);
- processor->OnLogEvent(screen_on_event.get());
+ int64_t condition_false_time = bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC + 1;
+ screen_on_event = CreateScreenStateChangedEvent(
+ condition_false_time, android::view::DisplayStateEnum::DISPLAY_STATE_ON);
+ processor->OnLogEvent(screen_on_event.get(), condition_false_time);
// Condition turns to false. Cancelled the alarm.
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
// Detected one anomaly.
@@ -262,12 +280,11 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2 + 2 + 1,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
- release_event =
- CreateReleaseWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 5 * NS_PER_SEC,
- attributionUids2, attributionTags2, "wl1");
+ release_event_time = roundedBucketStartTimeNs + 2 * bucketSizeNs + 5 * NS_PER_SEC;
+ release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids2,
+ attributionTags2, "wl1");
processor->OnLogEvent(release_event.get());
- EXPECT_EQ(refractory_period_sec +
- (bucketStartTimeNs + 2 * bucketSizeNs + 5 * NS_PER_SEC) / NS_PER_SEC,
+ EXPECT_EQ(refractory_period_sec + (release_event_time) / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
}
@@ -279,16 +296,18 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets) {
const uint64_t alert_id = config.alert(0).id();
const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
- int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
- int64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000;
+ shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
+ sendConfig(service, config);
- ConfigKey cfgKey;
- auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+ auto processor = service->mProcessor;
ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
ASSERT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
+ int64_t bucketStartTimeNs = processor->mTimeBaseNs;
+ int64_t roundedBucketStartTimeNs = bucketStartTimeNs / NS_PER_SEC * NS_PER_SEC;
+ int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1e6;
+
sp<AnomalyTracker> anomalyTracker =
processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
@@ -298,96 +317,97 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets) {
// Acquire wakelock "wc1" in bucket #0.
auto acquire_event =
- CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs - NS_PER_SEC / 2 - 1,
+ CreateAcquireWakelockEvent(roundedBucketStartTimeNs + bucketSizeNs - NS_PER_SEC / 2 - 1,
attributionUids1, attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 1,
+ EXPECT_EQ((roundedBucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 1,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Release wakelock "wc1" in bucket #0.
- auto release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + bucketSizeNs - 1,
- attributionUids1, attributionTags1, "wl1");
- processor->OnLogEvent(release_event.get());
+ int64_t release_event_time = roundedBucketStartTimeNs + bucketSizeNs - 1;
+ auto release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids1,
+ attributionTags1, "wl1");
+ processor->OnLogEvent(release_event.get(), release_event_time);
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Acquire wakelock "wc1" in bucket #1.
- acquire_event = CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs + 1,
- attributionUids2, attributionTags2, "wl1");
+ acquire_event =
+ CreateAcquireWakelockEvent(roundedBucketStartTimeNs + bucketSizeNs + NS_PER_SEC + 1,
+ attributionUids2, attributionTags2, "wl1");
processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 1,
+ EXPECT_EQ((bucketStartTimeNs + bucketSizeNs + NS_PER_SEC) / NS_PER_SEC + 1,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
- release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + bucketSizeNs + 100,
- attributionUids2, attributionTags2, "wl1");
- processor->OnLogEvent(release_event.get());
+ release_event_time = roundedBucketStartTimeNs + bucketSizeNs + NS_PER_SEC + 100;
+ release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids2,
+ attributionTags2, "wl1");
+ processor->OnLogEvent(release_event.get(), release_event_time);
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Acquire wakelock "wc2" in bucket #2.
- acquire_event = CreateAcquireWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 1,
- attributionUids3, attributionTags3, "wl2");
+ acquire_event =
+ CreateAcquireWakelockEvent(roundedBucketStartTimeNs + 2 * bucketSizeNs + NS_PER_SEC + 1,
+ attributionUids3, attributionTags3, "wl2");
processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2,
+ EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 3,
anomalyTracker->getAlarmTimestampSec(dimensionKey2));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
// Release wakelock "wc2" in bucket #2.
- release_event =
- CreateReleaseWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC,
- attributionUids3, attributionTags3, "wl2");
- processor->OnLogEvent(release_event.get());
+ release_event_time = roundedBucketStartTimeNs + 2 * bucketSizeNs + 3 * NS_PER_SEC;
+ release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids3,
+ attributionTags3, "wl2");
+ processor->OnLogEvent(release_event.get(), release_event_time);
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey2));
- EXPECT_EQ(refractory_period_sec +
- (bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC) / NS_PER_SEC,
+ EXPECT_EQ(refractory_period_sec + (release_event_time) / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
// Acquire wakelock "wc1" in bucket #2.
acquire_event =
- CreateAcquireWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC,
+ CreateAcquireWakelockEvent(roundedBucketStartTimeNs + 2 * bucketSizeNs + 3 * NS_PER_SEC,
attributionUids2, attributionTags2, "wl1");
processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2 + 1,
+ EXPECT_EQ((roundedBucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 3 + 1,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Release wakelock "wc1" in bucket #2.
- release_event =
- CreateReleaseWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 2.5 * NS_PER_SEC,
- attributionUids2, attributionTags2, "wl1");
- processor->OnLogEvent(release_event.get());
+ release_event_time = roundedBucketStartTimeNs + 2 * bucketSizeNs + 3.5 * NS_PER_SEC;
+ release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids2,
+ attributionTags2, "wl1");
+ processor->OnLogEvent(release_event.get(), release_event_time);
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
- EXPECT_EQ(refractory_period_sec +
- (int64_t)(bucketStartTimeNs + 2 * bucketSizeNs + 2.5 * NS_PER_SEC) /
- NS_PER_SEC +
- 1,
+ EXPECT_EQ(refractory_period_sec + (release_event_time) / NS_PER_SEC + 1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
- acquire_event =
- CreateAcquireWakelockEvent(bucketStartTimeNs + 6 * bucketSizeNs - NS_PER_SEC + 4,
- attributionUids3, attributionTags3, "wl2");
+ acquire_event = CreateAcquireWakelockEvent(roundedBucketStartTimeNs + 6 * bucketSizeNs + 4,
+ attributionUids3, attributionTags3, "wl2");
processor->OnLogEvent(acquire_event.get());
- acquire_event =
- CreateAcquireWakelockEvent(bucketStartTimeNs + 6 * bucketSizeNs - NS_PER_SEC + 5,
- attributionUids1, attributionTags1, "wl1");
+ acquire_event = CreateAcquireWakelockEvent(roundedBucketStartTimeNs + 6 * bucketSizeNs + 5,
+ attributionUids1, attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 1,
+ EXPECT_EQ((roundedBucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 2,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
- EXPECT_EQ((bucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 1,
+ EXPECT_EQ((roundedBucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 2,
anomalyTracker->getAlarmTimestampSec(dimensionKey2));
- release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + 6 * bucketSizeNs + 2,
- attributionUids3, attributionTags3, "wl2");
- processor->OnLogEvent(release_event.get());
- release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + 6 * bucketSizeNs + 6,
- attributionUids1, attributionTags1, "wl1");
- processor->OnLogEvent(release_event.get());
+ release_event_time = roundedBucketStartTimeNs + 6 * bucketSizeNs + NS_PER_SEC + 2;
+ release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids3,
+ attributionTags3, "wl2");
+ processor->OnLogEvent(release_event.get(), release_event_time);
+ release_event = CreateReleaseWakelockEvent(release_event_time + 4, attributionUids1,
+ attributionTags1, "wl1");
+ processor->OnLogEvent(release_event.get(), release_event_time + 4);
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey2));
// The buckets are not messed up across dimensions. Only one dimension has anomaly triggered.
- EXPECT_EQ(refractory_period_sec + (int64_t)(bucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC +
+ EXPECT_EQ(refractory_period_sec +
+ (int64_t)(roundedBucketStartTimeNs + 6 * bucketSizeNs + NS_PER_SEC) /
+ NS_PER_SEC +
1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
}
@@ -396,20 +416,22 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period) {
const int num_buckets = 2;
const uint64_t threshold_ns = 3 * NS_PER_SEC;
auto config = CreateStatsdConfig(num_buckets, threshold_ns, DurationMetric::SUM, false);
- int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
- int64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000;
-
const uint64_t alert_id = config.alert(0).id();
+ int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1e6;
const uint32_t refractory_period_sec = 3 * bucketSizeNs / NS_PER_SEC;
config.mutable_alert(0)->set_refractory_period_secs(refractory_period_sec);
- ConfigKey cfgKey;
- auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+ shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
+ sendConfig(service, config);
+
+ auto processor = service->mProcessor;
ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
ASSERT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
+ int64_t bucketStartTimeNs = processor->mTimeBaseNs;
+ int64_t roundedBucketStartTimeNs = bucketStartTimeNs / NS_PER_SEC * NS_PER_SEC;
+
sp<AnomalyTracker> anomalyTracker =
processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
@@ -418,81 +440,81 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period) {
processor->OnLogEvent(screen_off_event.get());
// Acquire wakelock "wc1" in bucket #0.
- auto acquire_event = CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs - 100,
+ auto acquire_event = CreateAcquireWakelockEvent(roundedBucketStartTimeNs + bucketSizeNs - 100,
attributionUids1, attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 3,
+ EXPECT_EQ((roundedBucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 3,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Acquire the wakelock "wc1" again.
acquire_event =
- CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs + 2 * NS_PER_SEC + 1,
+ CreateAcquireWakelockEvent(roundedBucketStartTimeNs + bucketSizeNs + 2 * NS_PER_SEC + 1,
attributionUids1, attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
// The alarm does not change.
- EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 3,
+ EXPECT_EQ((roundedBucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 3,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Anomaly alarm fired late.
- const int64_t firedAlarmTimestampNs = bucketStartTimeNs + 2 * bucketSizeNs - NS_PER_SEC;
- auto alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
- static_cast<uint32_t>(firedAlarmTimestampNs / NS_PER_SEC));
- ASSERT_EQ(1u, alarmSet.size());
- processor->onAnomalyAlarmFired(firedAlarmTimestampNs, alarmSet);
+ const int64_t firedAlarmTimestampNs = roundedBucketStartTimeNs + 2 * bucketSizeNs - NS_PER_SEC;
+ auto alarmTriggerEvent = CreateBatterySaverOnEvent(firedAlarmTimestampNs);
+ processor->OnLogEvent(alarmTriggerEvent.get(), firedAlarmTimestampNs);
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
- acquire_event = CreateAcquireWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs - 100,
+ acquire_event = CreateAcquireWakelockEvent(roundedBucketStartTimeNs + 2 * bucketSizeNs - 100,
attributionUids1, attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
- auto release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 1,
- attributionUids1, attributionTags1, "wl1");
- processor->OnLogEvent(release_event.get());
+ int64_t release_event_time = bucketStartTimeNs + 2 * bucketSizeNs + 1;
+ auto release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids1,
+ attributionTags1, "wl1");
+ processor->OnLogEvent(release_event.get(), release_event_time);
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
// Within the refractory period. No anomaly.
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// A new wakelock, but still within refractory period.
- acquire_event =
- CreateAcquireWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 10 * NS_PER_SEC,
- attributionUids1, attributionTags1, "wl1");
+ acquire_event = CreateAcquireWakelockEvent(
+ roundedBucketStartTimeNs + 2 * bucketSizeNs + 10 * NS_PER_SEC, attributionUids1,
+ attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
- release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + 3 * bucketSizeNs - NS_PER_SEC,
- attributionUids1, attributionTags1, "wl1");
+ release_event =
+ CreateReleaseWakelockEvent(roundedBucketStartTimeNs + 3 * bucketSizeNs - NS_PER_SEC,
+ attributionUids1, attributionTags1, "wl1");
// Still in the refractory period. No anomaly.
processor->OnLogEvent(release_event.get());
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
- acquire_event =
- CreateAcquireWakelockEvent(bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 5,
- attributionUids1, attributionTags1, "wl1");
+ acquire_event = CreateAcquireWakelockEvent(
+ roundedBucketStartTimeNs + 5 * bucketSizeNs - 2 * NS_PER_SEC - 5, attributionUids1,
+ attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + 5 * bucketSizeNs) / NS_PER_SEC,
+ EXPECT_EQ((roundedBucketStartTimeNs + 5 * bucketSizeNs) / NS_PER_SEC + 1,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
- release_event =
- CreateReleaseWakelockEvent(bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 4,
- attributionUids1, attributionTags1, "wl1");
- processor->OnLogEvent(release_event.get());
+ release_event_time = roundedBucketStartTimeNs + 5 * bucketSizeNs - 2 * NS_PER_SEC - 4;
+ release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids1,
+ attributionTags1, "wl1");
+ processor->OnLogEvent(release_event.get(), release_event_time);
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
- acquire_event =
- CreateAcquireWakelockEvent(bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 3,
- attributionUids1, attributionTags1, "wl1");
+ acquire_event = CreateAcquireWakelockEvent(
+ roundedBucketStartTimeNs + 5 * bucketSizeNs - 2 * NS_PER_SEC - 3, attributionUids1,
+ attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + 5 * bucketSizeNs) / NS_PER_SEC,
+ EXPECT_EQ((roundedBucketStartTimeNs + 5 * bucketSizeNs) / NS_PER_SEC + 1,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
}
diff --git a/cmds/statsd/tests/external/StatsPullerManager_test.cpp b/cmds/statsd/tests/external/StatsPullerManager_test.cpp
index c76e85ec75e6..0d539f477016 100644
--- a/cmds/statsd/tests/external/StatsPullerManager_test.cpp
+++ b/cmds/statsd/tests/external/StatsPullerManager_test.cpp
@@ -89,10 +89,10 @@ public:
sp<StatsPullerManager> createPullerManagerAndRegister() {
sp<StatsPullerManager> pullerManager = new StatsPullerManager();
shared_ptr<FakePullAtomCallback> cb1 = SharedRefBase::make<FakePullAtomCallback>(uid1);
- pullerManager->RegisterPullAtomCallback(uid1, pullTagId1, coolDownNs, timeoutNs, {}, cb1, true);
+ pullerManager->RegisterPullAtomCallback(uid1, pullTagId1, coolDownNs, timeoutNs, {}, cb1);
shared_ptr<FakePullAtomCallback> cb2 = SharedRefBase::make<FakePullAtomCallback>(uid2);
- pullerManager->RegisterPullAtomCallback(uid2, pullTagId1, coolDownNs, timeoutNs, {}, cb2, true);
- pullerManager->RegisterPullAtomCallback(uid1, pullTagId2, coolDownNs, timeoutNs, {}, cb1, true);
+ pullerManager->RegisterPullAtomCallback(uid2, pullTagId1, coolDownNs, timeoutNs, {}, cb2);
+ pullerManager->RegisterPullAtomCallback(uid1, pullTagId2, coolDownNs, timeoutNs, {}, cb1);
return pullerManager;
}
} // anonymous namespace
@@ -101,14 +101,14 @@ TEST(StatsPullerManagerTest, TestPullInvalidUid) {
sp<StatsPullerManager> pullerManager = createPullerManagerAndRegister();
vector<shared_ptr<LogEvent>> data;
- EXPECT_FALSE(pullerManager->Pull(pullTagId1, {unregisteredUid}, /*timestamp =*/1, &data, true));
+ EXPECT_FALSE(pullerManager->Pull(pullTagId1, {unregisteredUid}, /*timestamp =*/1, &data));
}
TEST(StatsPullerManagerTest, TestPullChoosesCorrectUid) {
sp<StatsPullerManager> pullerManager = createPullerManagerAndRegister();
vector<shared_ptr<LogEvent>> data;
- EXPECT_TRUE(pullerManager->Pull(pullTagId1, {uid1}, /*timestamp =*/1, &data, true));
+ EXPECT_TRUE(pullerManager->Pull(pullTagId1, {uid1}, /*timestamp =*/1, &data));
ASSERT_EQ(data.size(), 1);
EXPECT_EQ(data[0]->GetTagId(), pullTagId1);
ASSERT_EQ(data[0]->getValues().size(), 1);
@@ -121,7 +121,7 @@ TEST(StatsPullerManagerTest, TestPullInvalidConfigKey) {
pullerManager->RegisterPullUidProvider(configKey, uidProvider);
vector<shared_ptr<LogEvent>> data;
- EXPECT_FALSE(pullerManager->Pull(pullTagId1, badConfigKey, /*timestamp =*/1, &data, true));
+ EXPECT_FALSE(pullerManager->Pull(pullTagId1, badConfigKey, /*timestamp =*/1, &data));
}
TEST(StatsPullerManagerTest, TestPullConfigKeyGood) {
@@ -130,7 +130,7 @@ TEST(StatsPullerManagerTest, TestPullConfigKeyGood) {
pullerManager->RegisterPullUidProvider(configKey, uidProvider);
vector<shared_ptr<LogEvent>> data;
- EXPECT_TRUE(pullerManager->Pull(pullTagId1, configKey, /*timestamp =*/1, &data, true));
+ EXPECT_TRUE(pullerManager->Pull(pullTagId1, configKey, /*timestamp =*/1, &data));
EXPECT_EQ(data[0]->GetTagId(), pullTagId1);
ASSERT_EQ(data[0]->getValues().size(), 1);
EXPECT_EQ(data[0]->getValues()[0].mValue.int_value, uid2);
@@ -142,7 +142,7 @@ TEST(StatsPullerManagerTest, TestPullConfigKeyNoPullerWithUid) {
pullerManager->RegisterPullUidProvider(configKey, uidProvider);
vector<shared_ptr<LogEvent>> data;
- EXPECT_FALSE(pullerManager->Pull(pullTagId2, configKey, /*timestamp =*/1, &data, true));
+ EXPECT_FALSE(pullerManager->Pull(pullTagId2, configKey, /*timestamp =*/1, &data));
}
} // namespace statsd
diff --git a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
index bb8e7bfd90f4..8e2864c6fba8 100644
--- a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
@@ -41,6 +41,7 @@ namespace statsd {
namespace {
const ConfigKey kConfigKey(0, 12345);
+const uint64_t protoHash = 0x1234567890;
void makeLogEvent(LogEvent* logEvent, int64_t timestampNs, int atomId) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
@@ -75,7 +76,7 @@ TEST(CountMetricProducerTest, TestFirstBucket) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
- wizard, 5, 600 * NS_PER_SEC + NS_PER_SEC / 2);
+ wizard, protoHash, 5, 600 * NS_PER_SEC + NS_PER_SEC / 2);
EXPECT_EQ(600500000000, countProducer.mCurrentBucketStartTimeNs);
EXPECT_EQ(10, countProducer.mCurrentBucketNum);
EXPECT_EQ(660000000005, countProducer.getCurrentBucketEndTimeNs());
@@ -95,7 +96,7 @@ TEST(CountMetricProducerTest, TestNonDimensionalEvents) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
- wizard, bucketStartTimeNs, bucketStartTimeNs);
+ wizard, protoHash, bucketStartTimeNs, bucketStartTimeNs);
// 2 events in bucket 1.
LogEvent event1(/*uid=*/0, /*pid=*/0);
@@ -158,7 +159,7 @@ TEST(CountMetricProducerTest, TestEventsWithNonSlicedCondition) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
CountMetricProducer countProducer(kConfigKey, metric, 0, {ConditionState::kUnknown}, wizard,
- bucketStartTimeNs, bucketStartTimeNs);
+ protoHash, bucketStartTimeNs, bucketStartTimeNs);
countProducer.onConditionChanged(true, bucketStartTimeNs);
@@ -226,8 +227,8 @@ TEST(CountMetricProducerTest, TestEventsWithSlicedCondition) {
EXPECT_CALL(*wizard, query(_, key2, _)).WillOnce(Return(ConditionState::kTrue));
CountMetricProducer countProducer(kConfigKey, metric, 0 /*condition tracker index*/,
- {ConditionState::kUnknown}, wizard, bucketStartTimeNs,
- bucketStartTimeNs);
+ {ConditionState::kUnknown}, wizard, protoHash,
+ bucketStartTimeNs, bucketStartTimeNs);
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
countProducer.flushIfNeededLocked(bucketStartTimeNs + 1);
@@ -265,7 +266,7 @@ TEST_P(CountMetricProducerTest_PartialBucket, TestSplitInCurrentBucket) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
CountMetricProducer countProducer(kConfigKey, metric, -1 /* no condition */, {}, wizard,
- bucketStartTimeNs, bucketStartTimeNs);
+ protoHash, bucketStartTimeNs, bucketStartTimeNs);
sp<AnomalyTracker> anomalyTracker = countProducer.addAnomalyTracker(alert, alarmMonitor);
EXPECT_TRUE(anomalyTracker != nullptr);
@@ -332,7 +333,7 @@ TEST_P(CountMetricProducerTest_PartialBucket, TestSplitInNextBucket) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
CountMetricProducer countProducer(kConfigKey, metric, -1 /* no condition */, {}, wizard,
- bucketStartTimeNs, bucketStartTimeNs);
+ protoHash, bucketStartTimeNs, bucketStartTimeNs);
// Bucket is flushed yet.
LogEvent event1(/*uid=*/0, /*pid=*/0);
@@ -397,7 +398,7 @@ TEST(CountMetricProducerTest, TestAnomalyDetectionUnSliced) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
- wizard, bucketStartTimeNs, bucketStartTimeNs);
+ wizard, protoHash, bucketStartTimeNs, bucketStartTimeNs);
sp<AnomalyTracker> anomalyTracker = countProducer.addAnomalyTracker(alert, alarmMonitor);
@@ -459,7 +460,7 @@ TEST(CountMetricProducerTest, TestOneWeekTimeUnit) {
int64_t fiveWeeksNs = 5 * 7 * oneDayNs;
CountMetricProducer countProducer(kConfigKey, metric, -1 /* meaning no condition */, {}, wizard,
- oneDayNs, fiveWeeksNs);
+ protoHash, oneDayNs, fiveWeeksNs);
int64_t fiveWeeksOneDayNs = fiveWeeksNs + oneDayNs;
diff --git a/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp b/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp
index 05cfa37b0ee1..d1f89775ed6a 100644
--- a/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp
@@ -45,6 +45,7 @@ namespace statsd {
namespace {
const ConfigKey kConfigKey(0, 12345);
+const uint64_t protoHash = 0x1234567890;
void makeLogEvent(LogEvent* logEvent, int64_t timestampNs, int atomId) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
AStatsEvent_setAtomId(statsEvent, atomId);
@@ -71,10 +72,10 @@ TEST(DurationMetricTrackerTest, TestFirstBucket) {
FieldMatcher dimensions;
- DurationMetricProducer durationProducer(kConfigKey, metric, -1 /*no condition*/, {},
- 1 /* start index */, 2 /* stop index */,
- 3 /* stop_all index */, false /*nesting*/, wizard,
- dimensions, 5, 600 * NS_PER_SEC + NS_PER_SEC / 2);
+ DurationMetricProducer durationProducer(
+ kConfigKey, metric, -1 /*no condition*/, {}, 1 /* start index */, 2 /* stop index */,
+ 3 /* stop_all index */, false /*nesting*/, wizard, protoHash, dimensions, 5,
+ 600 * NS_PER_SEC + NS_PER_SEC / 2);
EXPECT_EQ(600500000000, durationProducer.mCurrentBucketStartTimeNs);
EXPECT_EQ(10, durationProducer.mCurrentBucketNum);
@@ -99,10 +100,10 @@ TEST(DurationMetricTrackerTest, TestNoCondition) {
FieldMatcher dimensions;
- DurationMetricProducer durationProducer(kConfigKey, metric, -1 /*no condition*/, {},
- 1 /* start index */, 2 /* stop index */,
- 3 /* stop_all index */, false /*nesting*/, wizard,
- dimensions, bucketStartTimeNs, bucketStartTimeNs);
+ DurationMetricProducer durationProducer(
+ kConfigKey, metric, -1 /*no condition*/, {}, 1 /* start index */, 2 /* stop index */,
+ 3 /* stop_all index */, false /*nesting*/, wizard, protoHash, dimensions,
+ bucketStartTimeNs, bucketStartTimeNs);
durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
@@ -145,7 +146,7 @@ TEST(DurationMetricTrackerTest, TestNonSlicedCondition) {
DurationMetricProducer durationProducer(
kConfigKey, metric, 0 /* condition index */, {ConditionState::kUnknown},
1 /* start index */, 2 /* stop index */, 3 /* stop_all index */, false /*nesting*/,
- wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
+ wizard, protoHash, dimensions, bucketStartTimeNs, bucketStartTimeNs);
durationProducer.mCondition = ConditionState::kFalse;
EXPECT_FALSE(durationProducer.mCondition);
@@ -195,7 +196,7 @@ TEST(DurationMetricTrackerTest, TestNonSlicedConditionUnknownState) {
DurationMetricProducer durationProducer(
kConfigKey, metric, 0 /* condition index */, {ConditionState::kUnknown},
1 /* start index */, 2 /* stop index */, 3 /* stop_all index */, false /*nesting*/,
- wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
+ wizard, protoHash, dimensions, bucketStartTimeNs, bucketStartTimeNs);
EXPECT_EQ(ConditionState::kUnknown, durationProducer.mCondition);
EXPECT_FALSE(durationProducer.isConditionSliced());
@@ -238,10 +239,10 @@ TEST_P(DurationMetricProducerTest_PartialBucket, TestSumDuration) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
FieldMatcher dimensions;
- DurationMetricProducer durationProducer(kConfigKey, metric, -1 /* no condition */, {},
- 1 /* start index */, 2 /* stop index */,
- 3 /* stop_all index */, false /*nesting*/, wizard,
- dimensions, bucketStartTimeNs, bucketStartTimeNs);
+ DurationMetricProducer durationProducer(
+ kConfigKey, metric, -1 /* no condition */, {}, 1 /* start index */, 2 /* stop index */,
+ 3 /* stop_all index */, false /*nesting*/, wizard, protoHash, dimensions,
+ bucketStartTimeNs, bucketStartTimeNs);
int64_t startTimeNs = bucketStartTimeNs + 1 * NS_PER_SEC;
LogEvent event1(/*uid=*/0, /*pid=*/0);
@@ -301,10 +302,10 @@ TEST_P(DurationMetricProducerTest_PartialBucket, TestSumDurationWithSplitInFollo
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
FieldMatcher dimensions;
- DurationMetricProducer durationProducer(kConfigKey, metric, -1 /* no condition */, {},
- 1 /* start index */, 2 /* stop index */,
- 3 /* stop_all index */, false /*nesting*/, wizard,
- dimensions, bucketStartTimeNs, bucketStartTimeNs);
+ DurationMetricProducer durationProducer(
+ kConfigKey, metric, -1 /* no condition */, {}, 1 /* start index */, 2 /* stop index */,
+ 3 /* stop_all index */, false /*nesting*/, wizard, protoHash, dimensions,
+ bucketStartTimeNs, bucketStartTimeNs);
int64_t startTimeNs = bucketStartTimeNs + 1 * NS_PER_SEC;
LogEvent event1(/*uid=*/0, /*pid=*/0);
@@ -365,10 +366,10 @@ TEST_P(DurationMetricProducerTest_PartialBucket, TestSumDurationAnomaly) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
FieldMatcher dimensions;
- DurationMetricProducer durationProducer(kConfigKey, metric, -1 /* no condition */, {},
- 1 /* start index */, 2 /* stop index */,
- 3 /* stop_all index */, false /*nesting*/, wizard,
- dimensions, bucketStartTimeNs, bucketStartTimeNs);
+ DurationMetricProducer durationProducer(
+ kConfigKey, metric, -1 /* no condition */, {}, 1 /* start index */, 2 /* stop index */,
+ 3 /* stop_all index */, false /*nesting*/, wizard, protoHash, dimensions,
+ bucketStartTimeNs, bucketStartTimeNs);
sp<AnomalyTracker> anomalyTracker = durationProducer.addAnomalyTracker(alert, alarmMonitor);
EXPECT_TRUE(anomalyTracker != nullptr);
@@ -411,10 +412,10 @@ TEST_P(DurationMetricProducerTest_PartialBucket, TestMaxDuration) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
FieldMatcher dimensions;
- DurationMetricProducer durationProducer(kConfigKey, metric, -1 /* no condition */, {},
- 1 /* start index */, 2 /* stop index */,
- 3 /* stop_all index */, false /*nesting*/, wizard,
- dimensions, bucketStartTimeNs, bucketStartTimeNs);
+ DurationMetricProducer durationProducer(
+ kConfigKey, metric, -1 /* no condition */, {}, 1 /* start index */, 2 /* stop index */,
+ 3 /* stop_all index */, false /*nesting*/, wizard, protoHash, dimensions,
+ bucketStartTimeNs, bucketStartTimeNs);
int64_t startTimeNs = bucketStartTimeNs + 1;
LogEvent event1(/*uid=*/0, /*pid=*/0);
@@ -465,10 +466,10 @@ TEST_P(DurationMetricProducerTest_PartialBucket, TestMaxDurationWithSplitInNextB
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
FieldMatcher dimensions;
- DurationMetricProducer durationProducer(kConfigKey, metric, -1 /* no condition */, {},
- 1 /* start index */, 2 /* stop index */,
- 3 /* stop_all index */, false /*nesting*/, wizard,
- dimensions, bucketStartTimeNs, bucketStartTimeNs);
+ DurationMetricProducer durationProducer(
+ kConfigKey, metric, -1 /* no condition */, {}, 1 /* start index */, 2 /* stop index */,
+ 3 /* stop_all index */, false /*nesting*/, wizard, protoHash, dimensions,
+ bucketStartTimeNs, bucketStartTimeNs);
int64_t startTimeNs = bucketStartTimeNs + 1;
LogEvent event1(/*uid=*/0, /*pid=*/0);
diff --git a/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp b/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
index dfbb9da568b0..4bbbd2cb36ad 100644
--- a/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
@@ -36,9 +36,11 @@ namespace android {
namespace os {
namespace statsd {
-const ConfigKey kConfigKey(0, 12345);
namespace {
+const ConfigKey kConfigKey(0, 12345);
+const uint64_t protoHash = 0x1234567890;
+
void makeLogEvent(LogEvent* logEvent, int32_t atomId, int64_t timestampNs, string str) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
AStatsEvent_setAtomId(statsEvent, atomId);
@@ -66,7 +68,7 @@ TEST(EventMetricProducerTest, TestNoCondition) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
EventMetricProducer eventProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
- wizard, bucketStartTimeNs);
+ wizard, protoHash, bucketStartTimeNs);
eventProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
eventProducer.onMatchedLogEvent(1 /*matcher index*/, event2);
@@ -102,7 +104,8 @@ TEST(EventMetricProducerTest, TestEventsWithNonSlicedCondition) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
EventMetricProducer eventProducer(kConfigKey, metric, 0 /*condition index*/,
- {ConditionState::kUnknown}, wizard, bucketStartTimeNs);
+ {ConditionState::kUnknown}, wizard, protoHash,
+ bucketStartTimeNs);
eventProducer.onConditionChanged(true /*condition*/, bucketStartTimeNs);
eventProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
@@ -157,7 +160,8 @@ TEST(EventMetricProducerTest, TestEventsWithSlicedCondition) {
EXPECT_CALL(*wizard, query(_, key2, _)).WillOnce(Return(ConditionState::kTrue));
EventMetricProducer eventProducer(kConfigKey, metric, 0 /*condition index*/,
- {ConditionState::kUnknown}, wizard, bucketStartTimeNs);
+ {ConditionState::kUnknown}, wizard, protoHash,
+ bucketStartTimeNs);
eventProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
eventProducer.onMatchedLogEvent(1 /*matcher index*/, event2);
diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
index 5997bedcdf2d..10606810d806 100644
--- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
@@ -23,7 +23,7 @@
#include "logd/LogEvent.h"
#include "metrics_test_helper.h"
-#include "src/matchers/SimpleLogMatchingTracker.h"
+#include "src/matchers/SimpleAtomMatchingTracker.h"
#include "src/metrics/MetricProducer.h"
#include "src/stats_log_util.h"
#include "stats_event.h"
@@ -47,7 +47,7 @@ namespace {
const ConfigKey kConfigKey(0, 12345);
const int tagId = 1;
const int64_t metricId = 123;
-const int64_t atomMatcherId = 678;
+const uint64_t protoHash = 0x123456789;
const int logEventMatcherIndex = 0;
const int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
const int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
@@ -94,19 +94,17 @@ TEST(GaugeMetricProducerTest, TestFirstBucket) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
- new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<EventMatcherWizard> eventMatcherWizard =
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
// statsd started long ago.
// The metric starts in the middle of the bucket
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
- wizard, logEventMatcherIndex, eventMatcherWizard, -1, -1,
- tagId, 5, 600 * NS_PER_SEC + NS_PER_SEC / 2, pullerManager);
+ wizard, protoHash, logEventMatcherIndex, eventMatcherWizard,
+ -1, -1, tagId, 5, 600 * NS_PER_SEC + NS_PER_SEC / 2,
+ pullerManager);
gaugeProducer.prepareFirstBucket();
EXPECT_EQ(600500000000, gaugeProducer.mCurrentBucketStartTimeNs);
@@ -127,19 +125,15 @@ TEST(GaugeMetricProducerTest, TestPulledEventsNoCondition) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
data->clear();
data->push_back(makeLogEvent(tagId, eventTimeNs + 10, 3, "some value", 11));
@@ -147,8 +141,9 @@ TEST(GaugeMetricProducerTest, TestPulledEventsNoCondition) {
}));
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
- wizard, logEventMatcherIndex, eventMatcherWizard, tagId, -1,
- tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ wizard, protoHash, logEventMatcherIndex, eventMatcherWizard,
+ tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
+ pullerManager);
gaugeProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
@@ -217,15 +212,11 @@ TEST_P(GaugeMetricProducerTest_PartialBucket, TestPushedEvents) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
- wizard, logEventMatcherIndex, eventMatcherWizard,
+ wizard, protoHash, logEventMatcherIndex, eventMatcherWizard,
-1 /* -1 means no pulling */, -1, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
gaugeProducer.prepareFirstBucket();
@@ -301,19 +292,16 @@ TEST_P(GaugeMetricProducerTest_PartialBucket, TestPulled) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
+
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
.WillOnce(Return(false))
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, partialBucketSplitTimeNs);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, eventTimeNs, 2));
@@ -321,8 +309,9 @@ TEST_P(GaugeMetricProducerTest_PartialBucket, TestPulled) {
}));
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
- wizard, logEventMatcherIndex, eventMatcherWizard, tagId, -1,
- tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ wizard, protoHash, logEventMatcherIndex, eventMatcherWizard,
+ tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
+ pullerManager);
gaugeProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
@@ -378,22 +367,19 @@ TEST(GaugeMetricProducerTest, TestPulledWithAppUpgradeDisabled) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
.WillOnce(Return(false));
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
- wizard, logEventMatcherIndex, eventMatcherWizard, tagId, -1,
- tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ wizard, protoHash, logEventMatcherIndex, eventMatcherWizard,
+ tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
+ pullerManager);
gaugeProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
@@ -428,30 +414,26 @@ TEST(GaugeMetricProducerTest, TestPulledEventsWithCondition) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
int64_t conditionChangeNs = bucketStartTimeNs + 8;
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, conditionChangeNs, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, conditionChangeNs, _))
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, eventTimeNs + 10, 100));
return true;
}));
GaugeMetricProducer gaugeProducer(kConfigKey, metric, 0 /*condition index*/,
- {ConditionState::kUnknown}, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, -1, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ {ConditionState::kUnknown}, wizard, protoHash,
+ logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
gaugeProducer.prepareFirstBucket();
gaugeProducer.onConditionChanged(true, conditionChangeNs);
@@ -502,12 +484,8 @@ TEST(GaugeMetricProducerTest, TestPulledEventsWithSlicedCondition) {
dim->set_field(tagId);
dim->add_child()->set_field(1);
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
EXPECT_CALL(*wizard, query(_, _, _))
@@ -527,18 +505,18 @@ TEST(GaugeMetricProducerTest, TestPulledEventsWithSlicedCondition) {
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, sliceConditionChangeNs, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, sliceConditionChangeNs, _))
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
data->push_back(CreateTwoValueLogEvent(tagId, eventTimeNs + 10, 1000, 100));
return true;
}));
GaugeMetricProducer gaugeProducer(kConfigKey, metric, 0 /*condition index*/,
- {ConditionState::kUnknown}, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, -1, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ {ConditionState::kUnknown}, wizard, protoHash,
+ logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
gaugeProducer.prepareFirstBucket();
gaugeProducer.onSlicedConditionMayChange(true, sliceConditionChangeNs);
@@ -566,7 +544,7 @@ TEST(GaugeMetricProducerTest, TestPulledEventsAnomalyDetection) {
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
.WillOnce(Return(false));
GaugeMetric metric;
@@ -577,16 +555,13 @@ TEST(GaugeMetricProducerTest, TestPulledEventsAnomalyDetection) {
gaugeFieldMatcher->set_field(tagId);
gaugeFieldMatcher->add_child()->set_field(2);
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
- wizard, logEventMatcherIndex, eventMatcherWizard, tagId, -1,
- tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ wizard, protoHash, logEventMatcherIndex, eventMatcherWizard,
+ tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
+ pullerManager);
gaugeProducer.prepareFirstBucket();
Alert alert;
@@ -657,24 +632,20 @@ TEST(GaugeMetricProducerTest, TestPullOnTrigger) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, eventTimeNs, 4));
return true;
}))
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 20);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, eventTimeNs, 5));
@@ -684,8 +655,8 @@ TEST(GaugeMetricProducerTest, TestPullOnTrigger) {
int triggerId = 5;
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
- wizard, logEventMatcherIndex, eventMatcherWizard, tagId,
- triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
+ wizard, protoHash, logEventMatcherIndex, eventMatcherWizard,
+ tagId, triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
gaugeProducer.prepareFirstBucket();
@@ -729,31 +700,27 @@ TEST(GaugeMetricProducerTest, TestRemoveDimensionInOutput) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 3);
data->clear();
data->push_back(CreateTwoValueLogEvent(tagId, eventTimeNs, 3, 4));
return true;
}))
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
data->clear();
data->push_back(CreateTwoValueLogEvent(tagId, eventTimeNs, 4, 5));
return true;
}))
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 20);
data->clear();
data->push_back(CreateTwoValueLogEvent(tagId, eventTimeNs, 4, 6));
@@ -763,8 +730,8 @@ TEST(GaugeMetricProducerTest, TestRemoveDimensionInOutput) {
int triggerId = 5;
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
- wizard, logEventMatcherIndex, eventMatcherWizard, tagId,
- triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
+ wizard, protoHash, logEventMatcherIndex, eventMatcherWizard,
+ tagId, triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
gaugeProducer.prepareFirstBucket();
@@ -807,18 +774,14 @@ TEST(GaugeMetricProducerTest_BucketDrop, TestBucketDropWhenBucketTooSmall) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 3, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 3, _))
// Bucket start.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, eventTimeNs, 10));
return true;
@@ -826,8 +789,8 @@ TEST(GaugeMetricProducerTest_BucketDrop, TestBucketDropWhenBucketTooSmall) {
int triggerId = 5;
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
- wizard, logEventMatcherIndex, eventMatcherWizard, tagId,
- triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
+ wizard, protoHash, logEventMatcherIndex, eventMatcherWizard,
+ tagId, triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
gaugeProducer.prepareFirstBucket();
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index 5666501d7d51..b166cc1fe04e 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -22,7 +22,7 @@
#include <vector>
#include "metrics_test_helper.h"
-#include "src/matchers/SimpleLogMatchingTracker.h"
+#include "src/matchers/SimpleAtomMatchingTracker.h"
#include "src/metrics/MetricProducer.h"
#include "src/stats_log_util.h"
#include "tests/statsd_test_util.h"
@@ -46,7 +46,7 @@ namespace {
const ConfigKey kConfigKey(0, 12345);
const int tagId = 1;
const int64_t metricId = 123;
-const int64_t atomMatcherId = 678;
+const uint64_t protoHash = 0x1234567890;
const int logEventMatcherIndex = 0;
const int64_t bucketStartTimeNs = 10000000000;
const int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
@@ -58,7 +58,7 @@ const int64_t bucket6StartTimeNs = bucketStartTimeNs + 5 * bucketSizeNs;
double epsilon = 0.001;
static void assertPastBucketValuesSingleKey(
- const std::unordered_map<MetricDimensionKey, std::vector<ValueBucket>>& mPastBuckets,
+ const std::unordered_map<MetricDimensionKey, std::vector<PastValueBucket>>& mPastBuckets,
const std::initializer_list<int>& expectedValuesList,
const std::initializer_list<int64_t>& expectedDurationNsList,
const std::initializer_list<int64_t>& expectedStartTimeNsList,
@@ -80,7 +80,7 @@ static void assertPastBucketValuesSingleKey(
ASSERT_EQ(1, mPastBuckets.size());
ASSERT_EQ(expectedValues.size(), mPastBuckets.begin()->second.size());
- const vector<ValueBucket>& buckets = mPastBuckets.begin()->second;
+ const vector<PastValueBucket>& buckets = mPastBuckets.begin()->second;
for (int i = 0; i < expectedValues.size(); i++) {
EXPECT_EQ(expectedValues[i], buckets[i].values[0].long_value)
<< "Values differ at index " << i;
@@ -99,12 +99,8 @@ class ValueMetricProducerTestHelper {
public:
static sp<ValueMetricProducer> createValueProducerNoConditions(
sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric) {
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _))
.WillOnce(Return());
@@ -113,8 +109,8 @@ public:
sp<ValueMetricProducer> valueProducer =
new ValueMetricProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
- wizard, logEventMatcherIndex, eventMatcherWizard, tagId,
- bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ wizard, protoHash, logEventMatcherIndex, eventMatcherWizard,
+ tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
valueProducer->prepareFirstBucket();
return valueProducer;
}
@@ -122,12 +118,8 @@ public:
static sp<ValueMetricProducer> createValueProducerWithCondition(
sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric,
ConditionState conditionAfterFirstBucketPrepared) {
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _))
.WillOnce(Return());
@@ -136,7 +128,7 @@ public:
sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
kConfigKey, metric, 0 /*condition index*/, {ConditionState::kUnknown}, wizard,
- logEventMatcherIndex, eventMatcherWizard, tagId, bucketStartTimeNs,
+ protoHash, logEventMatcherIndex, eventMatcherWizard, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
valueProducer->prepareFirstBucket();
valueProducer->mCondition = conditionAfterFirstBucketPrepared;
@@ -147,12 +139,8 @@ public:
sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric,
vector<int32_t> slicedStateAtoms,
unordered_map<int, unordered_map<int, int64_t>> stateGroupMap) {
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _))
.WillOnce(Return());
@@ -160,9 +148,9 @@ public:
.WillRepeatedly(Return());
sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
- kConfigKey, metric, -1 /* no condition */, {}, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager, {},
- {}, slicedStateAtoms, stateGroupMap);
+ kConfigKey, metric, -1 /* no condition */, {}, wizard, protoHash,
+ logEventMatcherIndex, eventMatcherWizard, tagId, bucketStartTimeNs,
+ bucketStartTimeNs, pullerManager, {}, {}, slicedStateAtoms, stateGroupMap);
valueProducer->prepareFirstBucket();
return valueProducer;
}
@@ -172,12 +160,8 @@ public:
vector<int32_t> slicedStateAtoms,
unordered_map<int, unordered_map<int, int64_t>> stateGroupMap,
ConditionState conditionAfterFirstBucketPrepared) {
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _))
.WillOnce(Return());
@@ -186,8 +170,9 @@ public:
sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
kConfigKey, metric, 0 /* condition tracker index */, {ConditionState::kUnknown},
- wizard, logEventMatcherIndex, eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager, {}, {}, slicedStateAtoms, stateGroupMap);
+ wizard, protoHash, logEventMatcherIndex, eventMatcherWizard, tagId,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager, {}, {}, slicedStateAtoms,
+ stateGroupMap);
valueProducer->prepareFirstBucket();
valueProducer->mCondition = conditionAfterFirstBucketPrepared;
return valueProducer;
@@ -237,20 +222,16 @@ TEST(ValueMetricProducerTest, TestCalcPreviousBucketEndTime) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
int64_t startTimeBase = 11;
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
// statsd started long ago.
// The metric starts in the middle of the bucket
ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
- wizard, logEventMatcherIndex, eventMatcherWizard, -1,
- startTimeBase, 22, pullerManager);
+ wizard, protoHash, logEventMatcherIndex, eventMatcherWizard,
+ -1, startTimeBase, 22, pullerManager);
valueProducer.prepareFirstBucket();
EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
@@ -267,20 +248,16 @@ TEST(ValueMetricProducerTest, TestCalcPreviousBucketEndTime) {
TEST(ValueMetricProducerTest, TestFirstBucket) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
// statsd started long ago.
// The metric starts in the middle of the bucket
ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
- wizard, logEventMatcherIndex, eventMatcherWizard, -1, 5,
- 600 * NS_PER_SEC + NS_PER_SEC / 2, pullerManager);
+ wizard, protoHash, logEventMatcherIndex, eventMatcherWizard,
+ -1, 5, 600 * NS_PER_SEC + NS_PER_SEC / 2, pullerManager);
valueProducer.prepareFirstBucket();
EXPECT_EQ(600500000000, valueProducer.mCurrentBucketStartTimeNs);
@@ -294,9 +271,9 @@ TEST(ValueMetricProducerTest, TestFirstBucket) {
TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
return true;
@@ -313,8 +290,9 @@ TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) {
// has one slice
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ ValueMetricProducer::BaseInfo curBaseInfo =
+ valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(11, curBaseInfo.base.long_value);
@@ -329,8 +307,8 @@ TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) {
valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
// has one slice
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(23, curBaseInfo.base.long_value);
@@ -347,8 +325,8 @@ TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) {
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs + 1, 36));
valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(36, curBaseInfo.base.long_value);
@@ -368,19 +346,19 @@ TEST_P(ValueMetricProducerTest_PartialBucket, TestPartialBucketCreated) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
int64_t partialBucketSplitTimeNs = bucket2StartTimeNs + 2;
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Initialize bucket.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 1));
return true;
}))
// Partial bucket.
- .WillOnce(Invoke([partialBucketSplitTimeNs](
- int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ .WillOnce(Invoke([partialBucketSplitTimeNs](int tagId, const ConfigKey&,
+ const int64_t eventTimeNs,
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, partialBucketSplitTimeNs);
data->clear();
data->push_back(
@@ -421,30 +399,27 @@ TEST_P(ValueMetricProducerTest_PartialBucket, TestPartialBucketCreated) {
TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- auto keyValue = atomMatcher.add_field_value_matcher();
- keyValue->set_field(1);
- keyValue->set_eq_int(3);
+ FieldValueMatcher fvm;
+ fvm.set_field(1);
+ fvm.set_eq_int(3);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex, {fvm});
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 3, 3));
return true;
}));
- sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
- kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ new ValueMetricProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, wizard,
+ protoHash, logEventMatcherIndex, eventMatcherWizard, tagId,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
valueProducer->prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
@@ -455,8 +430,9 @@ TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) {
// has one slice
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ ValueMetricProducer::BaseInfo curBaseInfo =
+ valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(11, curBaseInfo.base.long_value);
@@ -484,8 +460,8 @@ TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) {
allData.push_back(CreateTwoValueLogEvent(tagId, bucket4StartTimeNs + 1, 3, 36));
valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
// the base was reset
EXPECT_EQ(true, curBaseInfo.hasBase);
@@ -505,7 +481,7 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) {
metric.set_use_absolute_value_on_reset(true);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
.WillOnce(Return(true));
sp<ValueMetricProducer> valueProducer =
ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
@@ -518,8 +494,9 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) {
// has one slice
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ ValueMetricProducer::BaseInfo curBaseInfo =
+ valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(11, curBaseInfo.base.long_value);
@@ -531,8 +508,8 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) {
valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
// has one slice
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(10, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
@@ -545,8 +522,8 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) {
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs + 1, 36));
valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(36, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
@@ -565,7 +542,7 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) {
TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
.WillOnce(Return(false));
sp<ValueMetricProducer> valueProducer =
ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
@@ -578,8 +555,9 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) {
// has one slice
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ ValueMetricProducer::BaseInfo curBaseInfo =
+ valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(11, curBaseInfo.base.long_value);
@@ -591,8 +569,8 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) {
valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
// has one slice
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(10, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
@@ -602,8 +580,8 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) {
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs + 1, 36));
valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(36, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
@@ -621,23 +599,23 @@ TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8); // First condition change.
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
return true;
}))
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 1); // Second condition change.
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 130));
return true;
}))
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucket3StartTimeNs + 1); // Third condition change.
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 180));
@@ -653,8 +631,9 @@ TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
// has one slice
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ ValueMetricProducer::BaseInfo curBaseInfo =
+ valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
// startUpdated:false sum:0 start:100
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(100, curBaseInfo.base.long_value);
@@ -670,8 +649,8 @@ TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
// has one slice
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(110, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
@@ -683,8 +662,8 @@ TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
// has one slice
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(true, curInterval.hasValue);
EXPECT_EQ(20, curInterval.value.long_value);
EXPECT_EQ(false, curBaseInfo.hasBase);
@@ -698,18 +677,14 @@ TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
TEST_P(ValueMetricProducerTest_PartialBucket, TestPushedEvents) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex,
- eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
- pullerManager);
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
+ logEventMatcherIndex, eventMatcherWizard, -1,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
valueProducer.prepareFirstBucket();
LogEvent event1(/*uid=*/0, /*pid=*/0);
@@ -759,31 +734,27 @@ TEST_P(ValueMetricProducerTest_PartialBucket, TestPushedEvents) {
TEST_P(ValueMetricProducerTest_PartialBucket, TestPulledValue) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
int64_t partialBucketSplitTimeNs = bucket2StartTimeNs + 150;
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
.WillOnce(Return(true))
- .WillOnce(Invoke([partialBucketSplitTimeNs](
- int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ .WillOnce(Invoke([partialBucketSplitTimeNs](int tagId, const ConfigKey&,
+ const int64_t eventTimeNs,
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, partialBucketSplitTimeNs);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, partialBucketSplitTimeNs, 120));
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
+ logEventMatcherIndex, eventMatcherWizard, tagId,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
valueProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
@@ -820,22 +791,18 @@ TEST(ValueMetricProducerTest, TestPulledWithAppUpgradeDisabled) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.set_split_bucket_for_app_upgrade(false);
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
.WillOnce(Return(true));
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
+ logEventMatcherIndex, eventMatcherWizard, tagId,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
valueProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
@@ -854,16 +821,16 @@ TEST_P(ValueMetricProducerTest_PartialBucket, TestPulledValueWhileConditionFalse
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 1); // Condition change to true time.
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 100));
return true;
}))
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs,
bucket2StartTimeNs - 100); // Condition change to false time.
data->clear();
@@ -900,18 +867,14 @@ TEST_P(ValueMetricProducerTest_PartialBucket, TestPulledValueWhileConditionFalse
TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex,
- eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
- pullerManager);
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
+ logEventMatcherIndex, eventMatcherWizard, -1,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
valueProducer.prepareFirstBucket();
LogEvent event1(/*uid=*/0, /*pid=*/0);
@@ -924,8 +887,9 @@ TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) {
// has one slice
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+ valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
+ ValueMetricProducer::BaseInfo curBaseInfo =
+ valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(10, curInterval.value.long_value);
EXPECT_EQ(true, curInterval.hasValue);
@@ -933,7 +897,7 @@ TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) {
// has one slice
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
EXPECT_EQ(30, curInterval.value.long_value);
valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
@@ -944,17 +908,13 @@ TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) {
TEST(ValueMetricProducerTest, TestPushedEventsWithCondition) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
ValueMetricProducer valueProducer(kConfigKey, metric, 0, {ConditionState::kUnknown}, wizard,
- logEventMatcherIndex, eventMatcherWizard, -1,
+ protoHash, logEventMatcherIndex, eventMatcherWizard, -1,
bucketStartTimeNs, bucketStartTimeNs, pullerManager);
valueProducer.prepareFirstBucket();
valueProducer.mCondition = ConditionState::kFalse;
@@ -974,8 +934,8 @@ TEST(ValueMetricProducerTest, TestPushedEventsWithCondition) {
// has one slice
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
EXPECT_EQ(20, curInterval.value.long_value);
LogEvent event3(/*uid=*/0, /*pid=*/0);
@@ -984,7 +944,7 @@ TEST(ValueMetricProducerTest, TestPushedEventsWithCondition) {
// has one slice
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
EXPECT_EQ(50, curInterval.value.long_value);
valueProducer.onConditionChangedLocked(false, bucketStartTimeNs + 35);
@@ -995,7 +955,7 @@ TEST(ValueMetricProducerTest, TestPushedEventsWithCondition) {
// has one slice
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
EXPECT_EQ(50, curInterval.value.long_value);
valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
@@ -1015,17 +975,13 @@ TEST(ValueMetricProducerTest, TestAnomalyDetection) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
- wizard, logEventMatcherIndex, eventMatcherWizard,
+ wizard, protoHash, logEventMatcherIndex, eventMatcherWizard,
-1 /*not pulled*/, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
valueProducer.prepareFirstBucket();
@@ -1081,11 +1037,54 @@ TEST(ValueMetricProducerTest, TestAnomalyDetection) {
std::ceil(1.0 * event6.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
}
+TEST(ValueMetricProducerTest, TestAnomalyDetectionMultipleBucketsSkipped) {
+ sp<AlarmMonitor> alarmMonitor;
+ Alert alert;
+ alert.set_id(101);
+ alert.set_metric_id(metricId);
+ alert.set_trigger_if_sum_gt(100);
+ alert.set_num_buckets(1);
+ const int32_t refPeriodSec = 3;
+ alert.set_refractory_period_secs(refPeriodSec);
+
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
+ vector<std::shared_ptr<LogEvent>>* data) {
+ EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 1); // Condition change to true time.
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 0));
+ return true;
+ }))
+ .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
+ vector<std::shared_ptr<LogEvent>>* data) {
+ EXPECT_EQ(eventTimeNs,
+ bucket3StartTimeNs + 100); // Condition changed to false time.
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 100, 120));
+ return true;
+ }));
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
+ ConditionState::kFalse);
+ sp<AnomalyTracker> anomalyTracker = valueProducer->addAnomalyTracker(alert, alarmMonitor);
+
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
+
+ // multiple buckets should be skipped here.
+ valueProducer->onConditionChanged(false, bucket3StartTimeNs + 100);
+
+ // No alert is fired when multiple buckets are skipped.
+ EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
+}
+
// Test value metric no condition, the pull on bucket boundary come in time and too late
TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
.WillOnce(Return(true));
sp<ValueMetricProducer> valueProducer =
ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
@@ -1099,8 +1098,9 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) {
// has one slice
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ ValueMetricProducer::BaseInfo curBaseInfo =
+ valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
// startUpdated:true sum:0 start:11
EXPECT_EQ(true, curBaseInfo.hasBase);
@@ -1114,8 +1114,8 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) {
valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
// has one slice
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
// tartUpdated:false sum:12
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(23, curBaseInfo.base.long_value);
@@ -1131,8 +1131,8 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) {
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket6StartTimeNs + 1, 36));
valueProducer->onDataPulled(allData, /** succeed */ true, bucket6StartTimeNs);
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
// startUpdated:false sum:12
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(36, curBaseInfo.base.long_value);
@@ -1164,10 +1164,10 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// condition becomes true
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8); // First condition change.
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
@@ -1175,7 +1175,7 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition) {
}))
// condition becomes false
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 1); // Second condition change.
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 120));
@@ -1190,8 +1190,9 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition) {
// has one slice
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ ValueMetricProducer::BaseInfo curBaseInfo =
+ valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(100, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
@@ -1199,8 +1200,8 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition) {
// pull on bucket boundary come late, condition change happens before it
valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8},
{bucketStartTimeNs}, {bucket2StartTimeNs});
EXPECT_EQ(false, curBaseInfo.hasBase);
@@ -1213,8 +1214,8 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition) {
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8},
{bucketStartTimeNs}, {bucket2StartTimeNs});
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
}
@@ -1227,10 +1228,10 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// condition becomes true
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
@@ -1238,7 +1239,7 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2) {
}))
// condition becomes false
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 1);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 120));
@@ -1246,7 +1247,7 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2) {
}))
// condition becomes true again
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 25);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 25, 130));
@@ -1262,8 +1263,9 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2) {
// has one slice
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ ValueMetricProducer::BaseInfo curBaseInfo =
+ valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
// startUpdated:false sum:0 start:100
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(100, curBaseInfo.base.long_value);
@@ -1275,8 +1277,8 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2) {
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8},
{bucketStartTimeNs}, {bucket2StartTimeNs});
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
@@ -1284,8 +1286,8 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2) {
valueProducer->onConditionChanged(true, bucket2StartTimeNs + 25);
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8},
{bucketStartTimeNs}, {bucket2StartTimeNs});
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(130, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
@@ -1296,8 +1298,8 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2) {
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 50, 140));
valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 50);
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(140, curBaseInfo.base.long_value);
EXPECT_EQ(true, curInterval.hasValue);
@@ -1317,18 +1319,14 @@ TEST(ValueMetricProducerTest, TestPushedAggregateMin) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.set_aggregation_type(ValueMetric::MIN);
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex,
- eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
- pullerManager);
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
+ logEventMatcherIndex, eventMatcherWizard, -1,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
valueProducer.prepareFirstBucket();
LogEvent event1(/*uid=*/0, /*pid=*/0);
@@ -1341,7 +1339,7 @@ TEST(ValueMetricProducerTest, TestPushedAggregateMin) {
// has one slice
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
EXPECT_EQ(10, curInterval.value.long_value);
EXPECT_EQ(true, curInterval.hasValue);
@@ -1349,7 +1347,7 @@ TEST(ValueMetricProducerTest, TestPushedAggregateMin) {
// has one slice
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
EXPECT_EQ(10, curInterval.value.long_value);
valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
@@ -1361,18 +1359,14 @@ TEST(ValueMetricProducerTest, TestPushedAggregateMax) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.set_aggregation_type(ValueMetric::MAX);
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex,
- eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
- pullerManager);
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
+ logEventMatcherIndex, eventMatcherWizard, -1,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
valueProducer.prepareFirstBucket();
LogEvent event1(/*uid=*/0, /*pid=*/0);
@@ -1382,7 +1376,7 @@ TEST(ValueMetricProducerTest, TestPushedAggregateMax) {
// has one slice
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
EXPECT_EQ(10, curInterval.value.long_value);
EXPECT_EQ(true, curInterval.hasValue);
@@ -1392,7 +1386,7 @@ TEST(ValueMetricProducerTest, TestPushedAggregateMax) {
// has one slice
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
EXPECT_EQ(20, curInterval.value.long_value);
valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
@@ -1404,18 +1398,14 @@ TEST(ValueMetricProducerTest, TestPushedAggregateAvg) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.set_aggregation_type(ValueMetric::AVG);
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex,
- eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
- pullerManager);
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
+ logEventMatcherIndex, eventMatcherWizard, -1,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
valueProducer.prepareFirstBucket();
LogEvent event1(/*uid=*/0, /*pid=*/0);
@@ -1427,7 +1417,7 @@ TEST(ValueMetricProducerTest, TestPushedAggregateAvg) {
// has one slice
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval;
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
EXPECT_EQ(10, curInterval.value.long_value);
EXPECT_EQ(true, curInterval.hasValue);
EXPECT_EQ(1, curInterval.sampleSize);
@@ -1436,7 +1426,7 @@ TEST(ValueMetricProducerTest, TestPushedAggregateAvg) {
// has one slice
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
EXPECT_EQ(25, curInterval.value.long_value);
EXPECT_EQ(2, curInterval.sampleSize);
@@ -1452,18 +1442,14 @@ TEST(ValueMetricProducerTest, TestPushedAggregateSum) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.set_aggregation_type(ValueMetric::SUM);
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex,
- eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
- pullerManager);
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
+ logEventMatcherIndex, eventMatcherWizard, -1,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
valueProducer.prepareFirstBucket();
LogEvent event1(/*uid=*/0, /*pid=*/0);
@@ -1475,7 +1461,7 @@ TEST(ValueMetricProducerTest, TestPushedAggregateSum) {
// has one slice
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
EXPECT_EQ(10, curInterval.value.long_value);
EXPECT_EQ(true, curInterval.hasValue);
@@ -1483,7 +1469,7 @@ TEST(ValueMetricProducerTest, TestPushedAggregateSum) {
// has one slice
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
EXPECT_EQ(25, curInterval.value.long_value);
valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
@@ -1496,18 +1482,14 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput) {
metric.set_aggregation_type(ValueMetric::MIN);
metric.set_use_diff(true);
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex,
- eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
- pullerManager);
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
+ logEventMatcherIndex, eventMatcherWizard, -1,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
valueProducer.prepareFirstBucket();
LogEvent event1(/*uid=*/0, /*pid=*/0);
@@ -1517,8 +1499,9 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput) {
// has one slice
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+ valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
+ ValueMetricProducer::BaseInfo curBaseInfo =
+ valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(10, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
@@ -1529,7 +1512,7 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput) {
// has one slice
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
EXPECT_EQ(true, curInterval.hasValue);
EXPECT_EQ(5, curInterval.value.long_value);
@@ -1539,8 +1522,8 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput) {
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(15, curBaseInfo.base.long_value);
EXPECT_EQ(true, curInterval.hasValue);
@@ -1550,8 +1533,8 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput) {
CreateRepeatedValueLogEvent(&event4, tagId, bucket2StartTimeNs + 15, 15);
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(15, curBaseInfo.base.long_value);
EXPECT_EQ(true, curInterval.hasValue);
@@ -1568,18 +1551,14 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue) {
metric.set_aggregation_type(ValueMetric::MIN);
metric.set_use_diff(true);
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex,
- eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
- pullerManager);
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
+ logEventMatcherIndex, eventMatcherWizard, -1,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
valueProducer.prepareFirstBucket();
LogEvent event1(/*uid=*/0, /*pid=*/0);
@@ -1592,12 +1571,13 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue) {
// has one slice
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+ valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
+ ValueMetricProducer::BaseInfo curBaseInfo =
+ valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(10, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
- curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[1];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(20, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
@@ -1606,12 +1586,12 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue) {
// has one slice
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(true, curInterval.hasValue);
EXPECT_EQ(5, curInterval.value.long_value);
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[1];
- curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[1];
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[1];
EXPECT_EQ(true, curInterval.hasValue);
EXPECT_EQ(2, curInterval.value.long_value);
@@ -1621,14 +1601,14 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue) {
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(15, curBaseInfo.base.long_value);
EXPECT_EQ(true, curInterval.hasValue);
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[1];
- curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[1];
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[1];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(25, curBaseInfo.base.long_value);
EXPECT_EQ(true, curInterval.hasValue);
@@ -1638,13 +1618,13 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue) {
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(15, curBaseInfo.base.long_value);
EXPECT_EQ(true, curInterval.hasValue);
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[1];
- curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[1];
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[1];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(29, curBaseInfo.base.long_value);
EXPECT_EQ(true, curInterval.hasValue);
@@ -1677,9 +1657,9 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBase) {
metric.set_use_zero_default_base(true);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3));
return true;
@@ -1690,9 +1670,9 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBase) {
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
auto iter = valueProducer->mCurrentSlicedBucket.begin();
- auto& interval1 = iter->second[0];
+ auto& interval1 = iter->second.intervals[0];
auto iterBase = valueProducer->mCurrentBaseInfo.begin();
- auto& baseInfo1 = iterBase->second[0];
+ auto& baseInfo1 = iterBase->second.baseInfos[0];
EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
EXPECT_EQ(true, baseInfo1.hasBase);
EXPECT_EQ(3, baseInfo1.base.long_value);
@@ -1726,8 +1706,8 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBase) {
}
EXPECT_TRUE(it != iter);
EXPECT_TRUE(itBase != iterBase);
- auto& interval2 = it->second[0];
- auto& baseInfo2 = itBase->second[0];
+ auto& interval2 = it->second.intervals[0];
+ auto& baseInfo2 = itBase->second.baseInfos[0];
EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
EXPECT_EQ(true, baseInfo2.hasBase);
EXPECT_EQ(4, baseInfo2.base.long_value);
@@ -1753,9 +1733,9 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) {
metric.set_use_zero_default_base(true);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3));
return true;
@@ -1766,9 +1746,10 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) {
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
const auto& it = valueProducer->mCurrentSlicedBucket.begin();
- ValueMetricProducer::Interval& interval1 = it->second[0];
+ ValueMetricProducer::Interval& interval1 = it->second.intervals[0];
ValueMetricProducer::BaseInfo& baseInfo1 =
- valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat())->second[0];
+ valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat())
+ ->second.baseInfos[0];
EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
EXPECT_EQ(true, baseInfo1.hasBase);
EXPECT_EQ(3, baseInfo1.base.long_value);
@@ -1795,9 +1776,10 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) {
}
}
EXPECT_TRUE(it2 != it);
- ValueMetricProducer::Interval& interval2 = it2->second[0];
+ ValueMetricProducer::Interval& interval2 = it2->second.intervals[0];
ValueMetricProducer::BaseInfo& baseInfo2 =
- valueProducer->mCurrentBaseInfo.find(it2->first.getDimensionKeyInWhat())->second[0];
+ valueProducer->mCurrentBaseInfo.find(it2->first.getDimensionKeyInWhat())
+ ->second.baseInfos[0];
EXPECT_EQ(2, it2->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
EXPECT_EQ(true, baseInfo2.hasBase);
EXPECT_EQ(4, baseInfo2.base.long_value);
@@ -1826,14 +1808,16 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) {
// Get new references now that entries have been deleted from the map
const auto& it3 = valueProducer->mCurrentSlicedBucket.begin();
const auto& it4 = std::next(valueProducer->mCurrentSlicedBucket.begin());
- ASSERT_EQ(it3->second.size(), 1);
- ASSERT_EQ(it4->second.size(), 1);
- ValueMetricProducer::Interval& interval3 = it3->second[0];
- ValueMetricProducer::Interval& interval4 = it4->second[0];
+ ASSERT_EQ(it3->second.intervals.size(), 1);
+ ASSERT_EQ(it4->second.intervals.size(), 1);
+ ValueMetricProducer::Interval& interval3 = it3->second.intervals[0];
+ ValueMetricProducer::Interval& interval4 = it4->second.intervals[0];
ValueMetricProducer::BaseInfo& baseInfo3 =
- valueProducer->mCurrentBaseInfo.find(it3->first.getDimensionKeyInWhat())->second[0];
+ valueProducer->mCurrentBaseInfo.find(it3->first.getDimensionKeyInWhat())
+ ->second.baseInfos[0];
ValueMetricProducer::BaseInfo& baseInfo4 =
- valueProducer->mCurrentBaseInfo.find(it4->first.getDimensionKeyInWhat())->second[0];
+ valueProducer->mCurrentBaseInfo.find(it4->first.getDimensionKeyInWhat())
+ ->second.baseInfos[0];
EXPECT_EQ(true, baseInfo3.hasBase);
EXPECT_EQ(5, baseInfo3.base.long_value);
@@ -1858,9 +1842,9 @@ TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) {
metric.mutable_dimensions_in_what()->add_child()->set_field(1);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3));
return true;
@@ -1871,9 +1855,9 @@ TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) {
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
auto iter = valueProducer->mCurrentSlicedBucket.begin();
- auto& interval1 = iter->second[0];
+ auto& interval1 = iter->second.intervals[0];
auto iterBase = valueProducer->mCurrentBaseInfo.begin();
- auto& baseInfo1 = iterBase->second[0];
+ auto& baseInfo1 = iterBase->second.baseInfos[0];
EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
EXPECT_EQ(true, baseInfo1.hasBase);
EXPECT_EQ(3, baseInfo1.base.long_value);
@@ -1909,8 +1893,8 @@ TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) {
}
EXPECT_TRUE(it != iter);
EXPECT_TRUE(itBase != iterBase);
- auto interval2 = it->second[0];
- auto baseInfo2 = itBase->second[0];
+ auto interval2 = it->second.intervals[0];
+ auto baseInfo2 = itBase->second.baseInfos[0];
EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
EXPECT_EQ(true, baseInfo2.hasBase);
EXPECT_EQ(4, baseInfo2.base.long_value);
@@ -1923,8 +1907,8 @@ TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) {
valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
// Only one interval left. One was trimmed.
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- interval2 = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- baseInfo2 = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ interval2 = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ baseInfo2 = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
EXPECT_EQ(true, baseInfo2.hasBase);
EXPECT_EQ(5, baseInfo2.base.long_value);
@@ -1937,8 +1921,8 @@ TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) {
allData.push_back(CreateTwoValueLogEvent(tagId, bucket5StartTimeNs + 1, 2, 14));
valueProducer->onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
- interval2 = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- baseInfo2 = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ interval2 = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ baseInfo2 = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(true, baseInfo2.hasBase);
EXPECT_EQ(14, baseInfo2.base.long_value);
EXPECT_EQ(false, interval2.hasValue);
@@ -1961,9 +1945,9 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange_EndOfB
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
// Used by onConditionChanged.
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 8, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 8, _))
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
return true;
@@ -1977,8 +1961,9 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange_EndOfB
// has one slice
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo& curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ ValueMetricProducer::BaseInfo& curBaseInfo =
+ valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(100, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
@@ -1995,9 +1980,9 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8); // Condition change to true.
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
@@ -2014,8 +1999,9 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange) {
// has one slice
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo& curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ ValueMetricProducer::BaseInfo& curBaseInfo =
+ valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(100, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
@@ -2034,16 +2020,16 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullFailBeforeConditionChange) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 50));
return false;
}))
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 1); // Condition change to false.
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
@@ -2064,8 +2050,9 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullFailBeforeConditionChange) {
valueProducer->onConditionChanged(false, bucketStartTimeNs + 1);
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ ValueMetricProducer::BaseInfo curBaseInfo =
+ valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(false, valueProducer->mHasGlobalBase);
@@ -2077,9 +2064,9 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullDelayExceeded) {
metric.set_max_pull_delay_sec(0);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 1, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 1, _))
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 120));
return true;
@@ -2097,19 +2084,15 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullDelayExceeded) {
TEST(ValueMetricProducerTest, TestResetBaseOnPullTooLate) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillRepeatedly(Return());
ValueMetricProducer valueProducer(kConfigKey, metric, 0, {ConditionState::kUnknown}, wizard,
- logEventMatcherIndex, eventMatcherWizard, tagId,
+ protoHash, logEventMatcherIndex, eventMatcherWizard, tagId,
bucket2StartTimeNs, bucket2StartTimeNs, pullerManager);
valueProducer.prepareFirstBucket();
valueProducer.mCondition = ConditionState::kFalse;
@@ -2124,9 +2107,9 @@ TEST(ValueMetricProducerTest, TestBaseSetOnConditionChange) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 1, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 1, _))
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 100));
return true;
@@ -2141,8 +2124,9 @@ TEST(ValueMetricProducerTest, TestBaseSetOnConditionChange) {
valueProducer->mHasGlobalBase = true;
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ ValueMetricProducer::BaseInfo curBaseInfo =
+ valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(100, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
@@ -2156,12 +2140,12 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenOneConditionFailed
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// First onConditionChanged
.WillOnce(Return(false))
// Second onConditionChanged
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 3);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 130));
@@ -2194,8 +2178,9 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenOneConditionFailed
// Contains base from last pull which was successful.
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ ValueMetricProducer::BaseInfo curBaseInfo =
+ valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(140, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
@@ -2233,10 +2218,10 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenGuardRailHit) {
metric.set_condition(StringToId("SCREEN_ON"));
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 2, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 2, _))
// First onConditionChanged
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
for (int i = 0; i < 2000; i++) {
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, i));
}
@@ -2290,10 +2275,10 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenInitialPullFailed)
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// First onConditionChanged
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 2);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 120));
@@ -2301,7 +2286,7 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenInitialPullFailed)
}))
// Second onConditionChanged
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 3);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 130));
@@ -2332,8 +2317,9 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenInitialPullFailed)
// Contains base from last pull which was successful.
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ ValueMetricProducer::BaseInfo curBaseInfo =
+ valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(140, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
@@ -2369,10 +2355,10 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenLastPullFailed) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// First onConditionChanged
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 2);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 120));
@@ -2380,7 +2366,7 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenLastPullFailed) {
}))
// Second onConditionChanged
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 3);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 130));
@@ -2411,8 +2397,9 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenLastPullFailed) {
// Last pull failed so base has been reset.
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ ValueMetricProducer::BaseInfo curBaseInfo =
+ valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(false, valueProducer->mHasGlobalBase);
@@ -2442,10 +2429,10 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenLastPullFailed) {
TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onDataPulled) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
// Start bucket.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
return true;
@@ -2475,17 +2462,17 @@ TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onConditionChanged) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// First onConditionChanged
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
return true;
}))
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
data->clear();
return true;
@@ -2498,8 +2485,9 @@ TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onConditionChanged) {
valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ ValueMetricProducer::BaseInfo curBaseInfo =
+ valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(true, valueProducer->mHasGlobalBase);
@@ -2507,8 +2495,8 @@ TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onConditionChanged) {
// Empty pull.
valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(false, valueProducer->mHasGlobalBase);
@@ -2518,24 +2506,24 @@ TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onBucketBoundary) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// First onConditionChanged
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
return true;
}))
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 11);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 2));
return true;
}))
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 12);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 5));
@@ -2551,8 +2539,9 @@ TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onBucketBoundary) {
valueProducer->onConditionChanged(true, bucketStartTimeNs + 12);
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ ValueMetricProducer::BaseInfo curBaseInfo =
+ valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(true, curInterval.hasValue);
EXPECT_EQ(true, valueProducer->mHasGlobalBase);
@@ -2562,8 +2551,8 @@ TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onBucketBoundary) {
allData.clear();
valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
// Data is empty, base should be reset.
EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(5, curBaseInfo.base.long_value);
@@ -2582,10 +2571,10 @@ TEST(ValueMetricProducerTest, TestPartialResetOnBucketBoundaries) {
metric.set_condition(StringToId("SCREEN_ON"));
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 10, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 10, _))
// First onConditionChanged
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
return true;
@@ -2608,14 +2597,14 @@ TEST(ValueMetricProducerTest, TestPartialResetOnBucketBoundaries) {
ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
auto iterator = valueProducer->mCurrentSlicedBucket.begin();
auto baseInfoIter = valueProducer->mCurrentBaseInfo.begin();
- EXPECT_EQ(true, baseInfoIter->second[0].hasBase);
- EXPECT_EQ(2, baseInfoIter->second[0].base.long_value);
- EXPECT_EQ(false, iterator->second[0].hasValue);
+ EXPECT_EQ(true, baseInfoIter->second.baseInfos[0].hasBase);
+ EXPECT_EQ(2, baseInfoIter->second.baseInfos[0].base.long_value);
+ EXPECT_EQ(false, iterator->second.intervals[0].hasValue);
iterator++;
baseInfoIter++;
- EXPECT_EQ(false, baseInfoIter->second[0].hasBase);
- EXPECT_EQ(1, baseInfoIter->second[0].base.long_value);
- EXPECT_EQ(false, iterator->second[0].hasValue);
+ EXPECT_EQ(false, baseInfoIter->second.baseInfos[0].hasBase);
+ EXPECT_EQ(1, baseInfoIter->second.baseInfos[0].base.long_value);
+ EXPECT_EQ(false, iterator->second.intervals[0].hasValue);
EXPECT_EQ(true, valueProducer->mHasGlobalBase);
}
@@ -2625,19 +2614,19 @@ TEST_P(ValueMetricProducerTest_PartialBucket, TestFullBucketResetWhenLastBucketI
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
int64_t partialBucketSplitTimeNs = bucketStartTimeNs + bucketSizeNs / 2;
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Initialization.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
return true;
}))
// notifyAppUpgrade.
- .WillOnce(Invoke([partialBucketSplitTimeNs](
- int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ .WillOnce(Invoke([partialBucketSplitTimeNs](int tagId, const ConfigKey&,
+ const int64_t eventTimeNs,
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, partialBucketSplitTimeNs);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, partialBucketSplitTimeNs, 10));
@@ -2681,10 +2670,10 @@ TEST_P(ValueMetricProducerTest_PartialBucket, TestFullBucketResetWhenLastBucketI
TEST(ValueMetricProducerTest, TestBucketBoundariesOnConditionChange) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Second onConditionChanged.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 10);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 10, 5));
@@ -2692,7 +2681,7 @@ TEST(ValueMetricProducerTest, TestBucketBoundariesOnConditionChange) {
}))
// Third onConditionChanged.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucket3StartTimeNs + 10);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 10, 7));
@@ -2714,8 +2703,8 @@ TEST(ValueMetricProducerTest, TestBucketBoundariesOnConditionChange) {
valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- auto curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ auto curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(5, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
@@ -2752,10 +2741,10 @@ TEST(ValueMetricProducerTest, TestLateOnDataPulledWithDiff) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
// Initialization.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
return true;
@@ -2782,19 +2771,19 @@ TEST_P(ValueMetricProducerTest_PartialBucket, TestBucketBoundariesOnPartialBucke
int64_t partialBucketSplitTimeNs = bucket2StartTimeNs + 2;
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Initialization.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
return true;
}))
// notifyAppUpgrade.
- .WillOnce(Invoke([partialBucketSplitTimeNs](
- int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ .WillOnce(Invoke([partialBucketSplitTimeNs](int tagId, const ConfigKey&,
+ const int64_t eventTimeNs,
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, partialBucketSplitTimeNs);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, partialBucketSplitTimeNs, 10));
@@ -2822,10 +2811,10 @@ TEST(ValueMetricProducerTest, TestDataIsNotUpdatedWhenNoConditionChanged) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// First on condition changed.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
@@ -2833,7 +2822,7 @@ TEST(ValueMetricProducerTest, TestDataIsNotUpdatedWhenNoConditionChanged) {
}))
// Second on condition changed.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
@@ -2849,8 +2838,8 @@ TEST(ValueMetricProducerTest, TestDataIsNotUpdatedWhenNoConditionChanged) {
valueProducer->onConditionChanged(false, bucketStartTimeNs + 12);
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- auto curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ auto curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(true, curInterval.hasValue);
EXPECT_EQ(2, curInterval.value.long_value);
@@ -2867,10 +2856,10 @@ TEST(ValueMetricProducerTest, TestBucketInvalidIfGlobalBaseIsNotSet) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// First condition change.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 10);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
@@ -2878,7 +2867,7 @@ TEST(ValueMetricProducerTest, TestBucketInvalidIfGlobalBaseIsNotSet) {
}))
// 2nd condition change.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 8);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 1));
@@ -2886,7 +2875,7 @@ TEST(ValueMetricProducerTest, TestBucketInvalidIfGlobalBaseIsNotSet) {
}))
// 3rd condition change.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 10);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 1));
@@ -2920,29 +2909,25 @@ TEST(ValueMetricProducerTest, TestBucketInvalidIfGlobalBaseIsNotSet) {
TEST(ValueMetricProducerTest, TestPullNeededFastDump) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillRepeatedly(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
// Initial pull.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs, tagId, 1, 1));
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
+ logEventMatcherIndex, eventMatcherWizard, tagId,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
valueProducer.prepareFirstBucket();
ProtoOutputStream output;
@@ -2958,29 +2943,25 @@ TEST(ValueMetricProducerTest, TestPullNeededFastDump) {
TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillRepeatedly(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
// Initial pull.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs, tagId, 1, 1));
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
+ logEventMatcherIndex, eventMatcherWizard, tagId,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
valueProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
@@ -3002,28 +2983,24 @@ TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) {
TEST(ValueMetricProducerTest, TestPullNeededNoTimeConstraints) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillRepeatedly(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Initial pull.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
data->clear();
data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs, tagId, 1, 1));
return true;
}))
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
data->clear();
data->push_back(
@@ -3031,9 +3008,9 @@ TEST(ValueMetricProducerTest, TestPullNeededNoTimeConstraints) {
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
+ logEventMatcherIndex, eventMatcherWizard, tagId,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
valueProducer.prepareFirstBucket();
ProtoOutputStream output;
@@ -3069,10 +3046,10 @@ TEST(ValueMetricProducerTest, TestPulledData_noDiff_withMultipleConditionChanges
metric.set_use_diff(false);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// condition becomes true
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10));
@@ -3080,7 +3057,7 @@ TEST(ValueMetricProducerTest, TestPulledData_noDiff_withMultipleConditionChanges
}))
// condition becomes false
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 20));
@@ -3095,8 +3072,9 @@ TEST(ValueMetricProducerTest, TestPulledData_noDiff_withMultipleConditionChanges
// has one slice
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ ValueMetricProducer::BaseInfo curBaseInfo =
+ valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(true, curInterval.hasValue);
EXPECT_EQ(20, curInterval.value.long_value);
@@ -3108,8 +3086,8 @@ TEST(ValueMetricProducerTest, TestPulledData_noDiff_withMultipleConditionChanges
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {50 - 8},
{bucketStartTimeNs}, {bucket2StartTimeNs});
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
}
@@ -3119,10 +3097,10 @@ TEST(ValueMetricProducerTest, TestPulledData_noDiff_bucketBoundaryTrue) {
metric.set_use_diff(false);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 8, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 8, _))
// condition becomes true
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10));
return true;
@@ -3141,8 +3119,9 @@ TEST(ValueMetricProducerTest, TestPulledData_noDiff_bucketBoundaryTrue) {
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {30}, {bucketSizeNs - 8},
{bucketStartTimeNs}, {bucket2StartTimeNs});
ValueMetricProducer::Interval curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
+ ValueMetricProducer::BaseInfo curBaseInfo =
+ valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
}
@@ -3170,10 +3149,10 @@ TEST(ValueMetricProducerTest, TestPulledData_noDiff_withFailure) {
metric.set_use_diff(false);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// condition becomes true
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10));
@@ -3210,10 +3189,10 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenDumpReportRequeste
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 20, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 20, _))
// Condition change to true.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 20, 10));
return true;
@@ -3256,10 +3235,10 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenConditionEventWron
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 50, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 50, _))
// Condition change to true.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10));
return true;
@@ -3314,10 +3293,10 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenAccumulateEventWro
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Condition change to true.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10));
@@ -3325,7 +3304,7 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenAccumulateEventWro
}))
// Dump report requested.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 100);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 100, 15));
@@ -3380,10 +3359,10 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenConditionUnknown)
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Condition change to true.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10));
@@ -3391,7 +3370,7 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenConditionUnknown)
}))
// Dump report requested.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10000);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 100, 15));
@@ -3436,10 +3415,10 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenPullFailed) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Condition change to true.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10));
@@ -3486,10 +3465,10 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenMultipleBucketsSki
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Condition change to true.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 10));
@@ -3497,7 +3476,7 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenMultipleBucketsSki
}))
// Dump report requested.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucket4StartTimeNs + 10);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs + 1000, 15));
@@ -3560,10 +3539,10 @@ TEST(ValueMetricProducerTest_BucketDrop, TestBucketDropWhenBucketTooSmall) {
metric.set_min_bucket_size_nanos(10000000000); // 10 seconds
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Condition change to true.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 10));
@@ -3571,7 +3550,7 @@ TEST(ValueMetricProducerTest_BucketDrop, TestBucketDropWhenBucketTooSmall) {
}))
// Dump report requested.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 9000000);
data->clear();
data->push_back(
@@ -3651,10 +3630,10 @@ TEST(ValueMetricProducerTest_BucketDrop, TestConditionUnknownMultipleBuckets) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Condition change to true.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 10 * NS_PER_SEC);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(
@@ -3663,7 +3642,7 @@ TEST(ValueMetricProducerTest_BucketDrop, TestConditionUnknownMultipleBuckets) {
}))
// Dump report requested.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 15 * NS_PER_SEC);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(
@@ -3740,10 +3719,10 @@ TEST(ValueMetricProducerTest_BucketDrop, TestBucketDropWhenForceBucketSplitBefor
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Condition change to true.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 10));
@@ -3751,7 +3730,7 @@ TEST(ValueMetricProducerTest_BucketDrop, TestBucketDropWhenForceBucketSplitBefor
}))
// App Update.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 1000);
data->clear();
data->push_back(
@@ -3806,10 +3785,10 @@ TEST(ValueMetricProducerTest_BucketDrop, TestMultipleBucketDropEvents) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 10, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 10, _))
// Condition change to true.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 10));
return true;
@@ -3857,10 +3836,10 @@ TEST(ValueMetricProducerTest_BucketDrop, TestMaxBucketDropEvents) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// First condition change event.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
for (int i = 0; i < 2000; i++) {
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, i));
@@ -3877,7 +3856,7 @@ TEST(ValueMetricProducerTest_BucketDrop, TestMaxBucketDropEvents) {
.WillOnce(Return(false))
.WillOnce(Return(false))
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 220);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 220, 10));
@@ -3976,10 +3955,10 @@ TEST(ValueMetricProducerTest, TestSlicedState) {
// Set up ValueMetricProducer.
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("SCREEN_STATE");
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// ValueMetricProducer initialized.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
@@ -3987,7 +3966,7 @@ TEST(ValueMetricProducerTest, TestSlicedState) {
}))
// Screen state change to ON.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 5);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 5, 5));
@@ -3995,7 +3974,7 @@ TEST(ValueMetricProducerTest, TestSlicedState) {
}))
// Screen state change to OFF.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 9));
@@ -4003,7 +3982,7 @@ TEST(ValueMetricProducerTest, TestSlicedState) {
}))
// Screen state change to ON.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 15);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 15, 21));
@@ -4011,7 +3990,7 @@ TEST(ValueMetricProducerTest, TestSlicedState) {
}))
// Dump report requested.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 30));
@@ -4034,18 +4013,18 @@ TEST(ValueMetricProducerTest, TestSlicedState) {
// Base for dimension key {}
auto it = valueProducer->mCurrentSlicedBucket.begin();
auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_TRUE(itBase->second[0].hasBase);
- EXPECT_EQ(3, itBase->second[0].base.long_value);
- EXPECT_TRUE(itBase->second[0].hasCurrentState);
- ASSERT_EQ(1, itBase->second[0].currentState.getValues().size());
+ EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
+ EXPECT_EQ(3, itBase->second.baseInfos[0].base.long_value);
+ EXPECT_TRUE(itBase->second.hasCurrentState);
+ ASSERT_EQ(1, itBase->second.currentState.getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
- itBase->second[0].currentState.getValues()[0].mValue.int_value);
+ itBase->second.currentState.getValues()[0].mValue.int_value);
// Value for dimension, state key {{}, kStateUnknown}
EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_FALSE(it->second[0].hasValue);
+ EXPECT_FALSE(it->second.intervals[0].hasValue);
// Bucket status after screen state change kStateUnknown->ON.
auto screenEvent = CreateScreenStateChangedEvent(
@@ -4055,19 +4034,19 @@ TEST(ValueMetricProducerTest, TestSlicedState) {
// Base for dimension key {}
it = valueProducer->mCurrentSlicedBucket.begin();
itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_TRUE(itBase->second[0].hasBase);
- EXPECT_EQ(5, itBase->second[0].base.long_value);
- EXPECT_TRUE(itBase->second[0].hasCurrentState);
- ASSERT_EQ(1, itBase->second[0].currentState.getValues().size());
+ EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
+ EXPECT_EQ(5, itBase->second.baseInfos[0].base.long_value);
+ EXPECT_TRUE(itBase->second.hasCurrentState);
+ ASSERT_EQ(1, itBase->second.currentState.getValues().size());
EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
- itBase->second[0].currentState.getValues()[0].mValue.int_value);
+ itBase->second.currentState.getValues()[0].mValue.int_value);
// Value for dimension, state key {{}, kStateUnknown}
EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(2, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(2, it->second.intervals[0].value.long_value);
// Bucket status after screen state change ON->OFF.
screenEvent = CreateScreenStateChangedEvent(bucketStartTimeNs + 10,
@@ -4077,26 +4056,26 @@ TEST(ValueMetricProducerTest, TestSlicedState) {
// Base for dimension key {}
it = valueProducer->mCurrentSlicedBucket.begin();
itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_TRUE(itBase->second[0].hasBase);
- EXPECT_EQ(9, itBase->second[0].base.long_value);
- EXPECT_TRUE(itBase->second[0].hasCurrentState);
+ EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
+ EXPECT_EQ(9, itBase->second.baseInfos[0].base.long_value);
+ EXPECT_TRUE(itBase->second.hasCurrentState);
EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
- itBase->second[0].currentState.getValues()[0].mValue.int_value);
+ itBase->second.currentState.getValues()[0].mValue.int_value);
// Value for dimension, state key {{}, ON}
EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(4, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(4, it->second.intervals[0].value.long_value);
// Value for dimension, state key {{}, kStateUnknown}
it++;
EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(2, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(2, it->second.intervals[0].value.long_value);
// Bucket status after screen state change OFF->ON.
screenEvent = CreateScreenStateChangedEvent(bucketStartTimeNs + 15,
@@ -4106,35 +4085,35 @@ TEST(ValueMetricProducerTest, TestSlicedState) {
// Base for dimension key {}
it = valueProducer->mCurrentSlicedBucket.begin();
itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_TRUE(itBase->second[0].hasBase);
- EXPECT_EQ(21, itBase->second[0].base.long_value);
- EXPECT_TRUE(itBase->second[0].hasCurrentState);
- ASSERT_EQ(1, itBase->second[0].currentState.getValues().size());
+ EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
+ EXPECT_EQ(21, itBase->second.baseInfos[0].base.long_value);
+ EXPECT_TRUE(itBase->second.hasCurrentState);
+ ASSERT_EQ(1, itBase->second.currentState.getValues().size());
EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
- itBase->second[0].currentState.getValues()[0].mValue.int_value);
+ itBase->second.currentState.getValues()[0].mValue.int_value);
// Value for dimension, state key {{}, OFF}
EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(12, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(12, it->second.intervals[0].value.long_value);
// Value for dimension, state key {{}, ON}
it++;
EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(4, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(4, it->second.intervals[0].value.long_value);
// Value for dimension, state key {{}, kStateUnknown}
it++;
EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(2, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(2, it->second.intervals[0].value.long_value);
// Start dump report and check output.
ProtoOutputStream output;
@@ -4178,10 +4157,10 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithMap) {
// Set up ValueMetricProducer.
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("SCREEN_STATE_ONOFF");
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// ValueMetricProducer initialized.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
@@ -4189,7 +4168,7 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithMap) {
}))
// Screen state change to ON.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 5);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 5, 5));
@@ -4203,7 +4182,7 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithMap) {
// Screen state change to OFF.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 15);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 15, 21));
@@ -4211,7 +4190,7 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithMap) {
}))
// Dump report requested.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 30));
@@ -4245,18 +4224,18 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithMap) {
// Base for dimension key {}
auto it = valueProducer->mCurrentSlicedBucket.begin();
auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_TRUE(itBase->second[0].hasBase);
- EXPECT_EQ(3, itBase->second[0].base.long_value);
- EXPECT_TRUE(itBase->second[0].hasCurrentState);
- ASSERT_EQ(1, itBase->second[0].currentState.getValues().size());
+ EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
+ EXPECT_EQ(3, itBase->second.baseInfos[0].base.long_value);
+ EXPECT_TRUE(itBase->second.hasCurrentState);
+ ASSERT_EQ(1, itBase->second.currentState.getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
- itBase->second[0].currentState.getValues()[0].mValue.int_value);
+ itBase->second.currentState.getValues()[0].mValue.int_value);
// Value for dimension, state key {{}, {kStateUnknown}}
EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_FALSE(it->second[0].hasValue);
+ EXPECT_FALSE(it->second.intervals[0].hasValue);
// Bucket status after screen state change kStateUnknown->ON.
auto screenEvent = CreateScreenStateChangedEvent(
@@ -4266,19 +4245,19 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithMap) {
// Base for dimension key {}
it = valueProducer->mCurrentSlicedBucket.begin();
itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_TRUE(itBase->second[0].hasBase);
- EXPECT_EQ(5, itBase->second[0].base.long_value);
- EXPECT_TRUE(itBase->second[0].hasCurrentState);
- ASSERT_EQ(1, itBase->second[0].currentState.getValues().size());
+ EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
+ EXPECT_EQ(5, itBase->second.baseInfos[0].base.long_value);
+ EXPECT_TRUE(itBase->second.hasCurrentState);
+ ASSERT_EQ(1, itBase->second.currentState.getValues().size());
EXPECT_EQ(screenOnGroup.group_id(),
- itBase->second[0].currentState.getValues()[0].mValue.long_value);
+ itBase->second.currentState.getValues()[0].mValue.long_value);
// Value for dimension, state key {{}, kStateUnknown}
EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(2, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(2, it->second.intervals[0].value.long_value);
// Bucket status after screen state change ON->VR.
// Both ON and VR are in the same state group, so the base should not change.
@@ -4289,19 +4268,19 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithMap) {
// Base for dimension key {}
it = valueProducer->mCurrentSlicedBucket.begin();
itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_TRUE(itBase->second[0].hasBase);
- EXPECT_EQ(5, itBase->second[0].base.long_value);
- EXPECT_TRUE(itBase->second[0].hasCurrentState);
- ASSERT_EQ(1, itBase->second[0].currentState.getValues().size());
+ EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
+ EXPECT_EQ(5, itBase->second.baseInfos[0].base.long_value);
+ EXPECT_TRUE(itBase->second.hasCurrentState);
+ ASSERT_EQ(1, itBase->second.currentState.getValues().size());
EXPECT_EQ(screenOnGroup.group_id(),
- itBase->second[0].currentState.getValues()[0].mValue.int_value);
+ itBase->second.currentState.getValues()[0].mValue.int_value);
// Value for dimension, state key {{}, kStateUnknown}
EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(2, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(2, it->second.intervals[0].value.long_value);
// Bucket status after screen state change VR->ON.
// Both ON and VR are in the same state group, so the base should not change.
@@ -4312,19 +4291,19 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithMap) {
// Base for dimension key {}
it = valueProducer->mCurrentSlicedBucket.begin();
itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_TRUE(itBase->second[0].hasBase);
- EXPECT_EQ(5, itBase->second[0].base.long_value);
- EXPECT_TRUE(itBase->second[0].hasCurrentState);
- ASSERT_EQ(1, itBase->second[0].currentState.getValues().size());
+ EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
+ EXPECT_EQ(5, itBase->second.baseInfos[0].base.long_value);
+ EXPECT_TRUE(itBase->second.hasCurrentState);
+ ASSERT_EQ(1, itBase->second.currentState.getValues().size());
EXPECT_EQ(screenOnGroup.group_id(),
- itBase->second[0].currentState.getValues()[0].mValue.int_value);
+ itBase->second.currentState.getValues()[0].mValue.int_value);
// Value for dimension, state key {{}, kStateUnknown}
EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(2, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(2, it->second.intervals[0].value.long_value);
// Bucket status after screen state change VR->OFF.
screenEvent = CreateScreenStateChangedEvent(bucketStartTimeNs + 15,
@@ -4334,27 +4313,27 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithMap) {
// Base for dimension key {}
it = valueProducer->mCurrentSlicedBucket.begin();
itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_TRUE(itBase->second[0].hasBase);
- EXPECT_EQ(21, itBase->second[0].base.long_value);
- EXPECT_TRUE(itBase->second[0].hasCurrentState);
- ASSERT_EQ(1, itBase->second[0].currentState.getValues().size());
+ EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
+ EXPECT_EQ(21, itBase->second.baseInfos[0].base.long_value);
+ EXPECT_TRUE(itBase->second.hasCurrentState);
+ ASSERT_EQ(1, itBase->second.currentState.getValues().size());
EXPECT_EQ(screenOffGroup.group_id(),
- itBase->second[0].currentState.getValues()[0].mValue.int_value);
+ itBase->second.currentState.getValues()[0].mValue.int_value);
// Value for dimension, state key {{}, ON GROUP}
EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(screenOnGroup.group_id(),
it->first.getStateValuesKey().getValues()[0].mValue.long_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(16, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(16, it->second.intervals[0].value.long_value);
// Value for dimension, state key {{}, kStateUnknown}
it++;
EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(2, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(2, it->second.intervals[0].value.long_value);
// Start dump report and check output.
ProtoOutputStream output;
@@ -4408,10 +4387,10 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
*fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// ValueMetricProducer initialized.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
data->clear();
data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 2 /*uid*/, 7));
@@ -4420,7 +4399,7 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
}))
// Uid 1 process state change from kStateUnknown -> Foreground
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 20);
data->clear();
data->push_back(
@@ -4433,7 +4412,7 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
}))
// Uid 2 process state change from kStateUnknown -> Background
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 40);
data->clear();
data->push_back(
@@ -4446,7 +4425,7 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
}))
// Uid 1 process state change from Foreground -> Background
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 20);
data->clear();
data->push_back(
@@ -4459,7 +4438,7 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
}))
// Uid 1 process state change from Background -> Foreground
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 40);
data->clear();
data->push_back(
@@ -4472,7 +4451,7 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
}))
// Dump report pull.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 50);
data->clear();
data->push_back(
@@ -4497,35 +4476,35 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
// Base for dimension key {uid 1}.
auto it = valueProducer->mCurrentSlicedBucket.begin();
auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_TRUE(itBase->second[0].hasBase);
- EXPECT_EQ(3, itBase->second[0].base.long_value);
- EXPECT_TRUE(itBase->second[0].hasCurrentState);
- ASSERT_EQ(1, itBase->second[0].currentState.getValues().size());
+ EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
+ EXPECT_EQ(3, itBase->second.baseInfos[0].base.long_value);
+ EXPECT_TRUE(itBase->second.hasCurrentState);
+ ASSERT_EQ(1, itBase->second.currentState.getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
- itBase->second[0].currentState.getValues()[0].mValue.int_value);
+ itBase->second.currentState.getValues()[0].mValue.int_value);
// Value for dimension, state key {{uid 1}, kStateUnknown}
ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_FALSE(it->second[0].hasValue);
+ EXPECT_FALSE(it->second.intervals[0].hasValue);
// Base for dimension key {uid 2}
it++;
itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_TRUE(itBase->second[0].hasBase);
- EXPECT_EQ(7, itBase->second[0].base.long_value);
- EXPECT_TRUE(itBase->second[0].hasCurrentState);
- ASSERT_EQ(1, itBase->second[0].currentState.getValues().size());
+ EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
+ EXPECT_EQ(7, itBase->second.baseInfos[0].base.long_value);
+ EXPECT_TRUE(itBase->second.hasCurrentState);
+ ASSERT_EQ(1, itBase->second.currentState.getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
- itBase->second[0].currentState.getValues()[0].mValue.int_value);
+ itBase->second.currentState.getValues()[0].mValue.int_value);
// Value for dimension, state key {{uid 2}, kStateUnknown}
ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_FALSE(it->second[0].hasValue);
+ EXPECT_FALSE(it->second.intervals[0].hasValue);
// Bucket status after uid 1 process state change kStateUnknown -> Foreground.
auto uidProcessEvent = CreateUidProcessStateChangedEvent(
@@ -4535,36 +4514,36 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
// Base for dimension key {uid 1}.
it = valueProducer->mCurrentSlicedBucket.begin();
itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_TRUE(itBase->second[0].hasBase);
- EXPECT_EQ(6, itBase->second[0].base.long_value);
- EXPECT_TRUE(itBase->second[0].hasCurrentState);
- ASSERT_EQ(1, itBase->second[0].currentState.getValues().size());
+ EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
+ EXPECT_EQ(6, itBase->second.baseInfos[0].base.long_value);
+ EXPECT_TRUE(itBase->second.hasCurrentState);
+ ASSERT_EQ(1, itBase->second.currentState.getValues().size());
EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
- itBase->second[0].currentState.getValues()[0].mValue.int_value);
+ itBase->second.currentState.getValues()[0].mValue.int_value);
// Value for key {uid 1, kStateUnknown}.
ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(3, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(3, it->second.intervals[0].value.long_value);
// Base for dimension key {uid 2}
it++;
itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_TRUE(itBase->second[0].hasBase);
- EXPECT_EQ(7, itBase->second[0].base.long_value);
- EXPECT_TRUE(itBase->second[0].hasCurrentState);
- ASSERT_EQ(1, itBase->second[0].currentState.getValues().size());
+ EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
+ EXPECT_EQ(7, itBase->second.baseInfos[0].base.long_value);
+ EXPECT_TRUE(itBase->second.hasCurrentState);
+ ASSERT_EQ(1, itBase->second.currentState.getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
- itBase->second[0].currentState.getValues()[0].mValue.int_value);
+ itBase->second.currentState.getValues()[0].mValue.int_value);
// Value for key {uid 2, kStateUnknown}
ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_FALSE(it->second[0].hasValue);
+ EXPECT_FALSE(it->second.intervals[0].hasValue);
// Bucket status after uid 2 process state change kStateUnknown -> Background.
uidProcessEvent = CreateUidProcessStateChangedEvent(
@@ -4574,36 +4553,36 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
// Base for dimension key {uid 1}.
it = valueProducer->mCurrentSlicedBucket.begin();
itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_TRUE(itBase->second[0].hasBase);
- EXPECT_EQ(6, itBase->second[0].base.long_value);
- EXPECT_TRUE(itBase->second[0].hasCurrentState);
- ASSERT_EQ(1, itBase->second[0].currentState.getValues().size());
+ EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
+ EXPECT_EQ(6, itBase->second.baseInfos[0].base.long_value);
+ EXPECT_TRUE(itBase->second.hasCurrentState);
+ ASSERT_EQ(1, itBase->second.currentState.getValues().size());
EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
- itBase->second[0].currentState.getValues()[0].mValue.int_value);
+ itBase->second.currentState.getValues()[0].mValue.int_value);
// Value for key {uid 1, kStateUnknown}.
ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(3, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(3, it->second.intervals[0].value.long_value);
// Base for dimension key {uid 2}
it++;
itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_TRUE(itBase->second[0].hasBase);
- EXPECT_EQ(9, itBase->second[0].base.long_value);
- EXPECT_TRUE(itBase->second[0].hasCurrentState);
- ASSERT_EQ(1, itBase->second[0].currentState.getValues().size());
+ EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
+ EXPECT_EQ(9, itBase->second.baseInfos[0].base.long_value);
+ EXPECT_TRUE(itBase->second.hasCurrentState);
+ ASSERT_EQ(1, itBase->second.currentState.getValues().size());
EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
- itBase->second[0].currentState.getValues()[0].mValue.int_value);
+ itBase->second.currentState.getValues()[0].mValue.int_value);
// Value for key {uid 2, kStateUnknown}
ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(2, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(2, it->second.intervals[0].value.long_value);
// Pull at end of first bucket.
vector<shared_ptr<LogEvent>> allData;
@@ -4620,36 +4599,36 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
it = valueProducer->mCurrentSlicedBucket.begin();
EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_TRUE(itBase->second[0].hasBase);
- EXPECT_EQ(15, itBase->second[0].base.long_value);
- EXPECT_TRUE(itBase->second[0].hasCurrentState);
- ASSERT_EQ(1, itBase->second[0].currentState.getValues().size());
+ EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
+ EXPECT_EQ(15, itBase->second.baseInfos[0].base.long_value);
+ EXPECT_TRUE(itBase->second.hasCurrentState);
+ ASSERT_EQ(1, itBase->second.currentState.getValues().size());
EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
- itBase->second[0].currentState.getValues()[0].mValue.int_value);
+ itBase->second.currentState.getValues()[0].mValue.int_value);
// Value for key {uid 2, BACKGROUND}.
ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_FALSE(it->second[0].hasValue);
+ EXPECT_FALSE(it->second.intervals[0].hasValue);
// Base for dimension key {uid 1}
it++;
itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_TRUE(itBase->second[0].hasBase);
- EXPECT_EQ(10, itBase->second[0].base.long_value);
- EXPECT_TRUE(itBase->second[0].hasCurrentState);
- ASSERT_EQ(1, itBase->second[0].currentState.getValues().size());
+ EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
+ EXPECT_EQ(10, itBase->second.baseInfos[0].base.long_value);
+ EXPECT_TRUE(itBase->second.hasCurrentState);
+ ASSERT_EQ(1, itBase->second.currentState.getValues().size());
EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
- itBase->second[0].currentState.getValues()[0].mValue.int_value);
+ itBase->second.currentState.getValues()[0].mValue.int_value);
// Value for key {uid 1, kStateUnknown}
ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /* kStateTracker::kUnknown */,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_FALSE(it->second[0].hasValue);
+ EXPECT_FALSE(it->second.intervals[0].hasValue);
// Value for key {uid 1, FOREGROUND}
it++;
@@ -4658,7 +4637,7 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_FALSE(it->second[0].hasValue);
+ EXPECT_FALSE(it->second.intervals[0].hasValue);
// Value for key {uid 2, kStateUnknown}
it++;
@@ -4667,7 +4646,7 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /* kStateTracker::kUnknown */,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_FALSE(it->second[0].hasValue);
+ EXPECT_FALSE(it->second.intervals[0].hasValue);
// Bucket status after uid 1 process state change from Foreground -> Background.
uidProcessEvent = CreateUidProcessStateChangedEvent(
@@ -4680,35 +4659,35 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
// Base for dimension key {uid 2}.
it = valueProducer->mCurrentSlicedBucket.begin();
itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_TRUE(itBase->second[0].hasBase);
- EXPECT_EQ(15, itBase->second[0].base.long_value);
- EXPECT_TRUE(itBase->second[0].hasCurrentState);
- ASSERT_EQ(1, itBase->second[0].currentState.getValues().size());
+ EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
+ EXPECT_EQ(15, itBase->second.baseInfos[0].base.long_value);
+ EXPECT_TRUE(itBase->second.hasCurrentState);
+ ASSERT_EQ(1, itBase->second.currentState.getValues().size());
EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
- itBase->second[0].currentState.getValues()[0].mValue.int_value);
+ itBase->second.currentState.getValues()[0].mValue.int_value);
// Value for key {uid 2, BACKGROUND}.
ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_FALSE(it->second[0].hasValue);
+ EXPECT_FALSE(it->second.intervals[0].hasValue);
// Base for dimension key {uid 1}
it++;
itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_TRUE(itBase->second[0].hasBase);
- EXPECT_EQ(13, itBase->second[0].base.long_value);
- EXPECT_TRUE(itBase->second[0].hasCurrentState);
- ASSERT_EQ(1, itBase->second[0].currentState.getValues().size());
+ EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
+ EXPECT_EQ(13, itBase->second.baseInfos[0].base.long_value);
+ EXPECT_TRUE(itBase->second.hasCurrentState);
+ ASSERT_EQ(1, itBase->second.currentState.getValues().size());
EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
- itBase->second[0].currentState.getValues()[0].mValue.int_value);
+ itBase->second.currentState.getValues()[0].mValue.int_value);
// Value for key {uid 1, kStateUnknown}
ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_FALSE(it->second[0].hasValue);
+ EXPECT_FALSE(it->second.intervals[0].hasValue);
// Value for key {uid 1, FOREGROUND}
it++;
ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
@@ -4716,8 +4695,8 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(3, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(3, it->second.intervals[0].value.long_value);
// Value for key {uid 2, kStateUnknown}
it++;
ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
@@ -4725,7 +4704,7 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_FALSE(it->second[0].hasValue);
+ EXPECT_FALSE(it->second.intervals[0].hasValue);
// Bucket status after uid 1 process state change Background->Foreground.
uidProcessEvent = CreateUidProcessStateChangedEvent(
@@ -4737,36 +4716,36 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
// Base for dimension key {uid 2}
it = valueProducer->mCurrentSlicedBucket.begin();
itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_TRUE(itBase->second[0].hasBase);
- EXPECT_EQ(15, itBase->second[0].base.long_value);
- EXPECT_TRUE(itBase->second[0].hasCurrentState);
- ASSERT_EQ(1, itBase->second[0].currentState.getValues().size());
+ EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
+ EXPECT_EQ(15, itBase->second.baseInfos[0].base.long_value);
+ EXPECT_TRUE(itBase->second.hasCurrentState);
+ ASSERT_EQ(1, itBase->second.currentState.getValues().size());
EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
- itBase->second[0].currentState.getValues()[0].mValue.int_value);
+ itBase->second.currentState.getValues()[0].mValue.int_value);
// Value for key {uid 2, BACKGROUND}
ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_FALSE(it->second[0].hasValue);
+ EXPECT_FALSE(it->second.intervals[0].hasValue);
// Base for dimension key {uid 1}
it++;
itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_TRUE(itBase->second[0].hasBase);
- EXPECT_EQ(17, itBase->second[0].base.long_value);
- EXPECT_TRUE(itBase->second[0].hasCurrentState);
- ASSERT_EQ(1, itBase->second[0].currentState.getValues().size());
+ EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
+ EXPECT_EQ(17, itBase->second.baseInfos[0].base.long_value);
+ EXPECT_TRUE(itBase->second.hasCurrentState);
+ ASSERT_EQ(1, itBase->second.currentState.getValues().size());
EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
- itBase->second[0].currentState.getValues()[0].mValue.int_value);
+ itBase->second.currentState.getValues()[0].mValue.int_value);
// Value for key {uid 1, kStateUnknown}
ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_FALSE(it->second[0].hasValue);
+ EXPECT_FALSE(it->second.intervals[0].hasValue);
// Value for key {uid 1, BACKGROUND}
it++;
@@ -4775,8 +4754,8 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(4, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(4, it->second.intervals[0].value.long_value);
// Value for key {uid 1, FOREGROUND}
it++;
@@ -4785,8 +4764,8 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(3, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(3, it->second.intervals[0].value.long_value);
// Value for key {uid 2, kStateUnknown}
it++;
@@ -4852,10 +4831,10 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithCondition) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithConditionAndState(
"BATTERY_SAVER_MODE_STATE");
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Condition changed to true.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 20 * NS_PER_SEC);
data->clear();
data->push_back(
@@ -4864,7 +4843,7 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithCondition) {
}))
// Battery saver mode state changed to OFF.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 30 * NS_PER_SEC);
data->clear();
data->push_back(
@@ -4873,7 +4852,7 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithCondition) {
}))
// Condition changed to false.
.WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 10 * NS_PER_SEC);
data->clear();
data->push_back(CreateRepeatedValueLogEvent(
@@ -4907,23 +4886,23 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithCondition) {
valueProducer->onConditionChanged(true, bucketStartTimeNs + 20 * NS_PER_SEC);
// Base for dimension key {}
ASSERT_EQ(1UL, valueProducer->mCurrentBaseInfo.size());
- std::unordered_map<HashableDimensionKey, std::vector<ValueMetricProducer::BaseInfo>>::iterator
+ std::unordered_map<HashableDimensionKey, ValueMetricProducer::DimensionsInWhatInfo>::iterator
itBase = valueProducer->mCurrentBaseInfo.find(DEFAULT_DIMENSION_KEY);
- EXPECT_TRUE(itBase->second[0].hasBase);
- EXPECT_EQ(3, itBase->second[0].base.long_value);
- EXPECT_TRUE(itBase->second[0].hasCurrentState);
- ASSERT_EQ(1, itBase->second[0].currentState.getValues().size());
+ EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
+ EXPECT_EQ(3, itBase->second.baseInfos[0].base.long_value);
+ EXPECT_TRUE(itBase->second.hasCurrentState);
+ ASSERT_EQ(1, itBase->second.currentState.getValues().size());
EXPECT_EQ(BatterySaverModeStateChanged::ON,
- itBase->second[0].currentState.getValues()[0].mValue.int_value);
+ itBase->second.currentState.getValues()[0].mValue.int_value);
// Value for key {{}, -1}
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- std::unordered_map<MetricDimensionKey, std::vector<ValueMetricProducer::Interval>>::iterator
- it = valueProducer->mCurrentSlicedBucket.begin();
+ std::unordered_map<MetricDimensionKey, ValueMetricProducer::CurrentValueBucket>::iterator it =
+ valueProducer->mCurrentSlicedBucket.begin();
EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(-1 /*StateTracker::kUnknown*/,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_FALSE(it->second[0].hasValue);
+ EXPECT_FALSE(it->second.intervals[0].hasValue);
// Bucket status after battery saver mode OFF event.
unique_ptr<LogEvent> batterySaverOffEvent =
@@ -4932,12 +4911,12 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithCondition) {
// Base for dimension key {}
ASSERT_EQ(1UL, valueProducer->mCurrentBaseInfo.size());
itBase = valueProducer->mCurrentBaseInfo.find(DEFAULT_DIMENSION_KEY);
- EXPECT_TRUE(itBase->second[0].hasBase);
- EXPECT_EQ(5, itBase->second[0].base.long_value);
- EXPECT_TRUE(itBase->second[0].hasCurrentState);
- ASSERT_EQ(1, itBase->second[0].currentState.getValues().size());
+ EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
+ EXPECT_EQ(5, itBase->second.baseInfos[0].base.long_value);
+ EXPECT_TRUE(itBase->second.hasCurrentState);
+ ASSERT_EQ(1, itBase->second.currentState.getValues().size());
EXPECT_EQ(BatterySaverModeStateChanged::OFF,
- itBase->second[0].currentState.getValues()[0].mValue.int_value);
+ itBase->second.currentState.getValues()[0].mValue.int_value);
// Value for key {{}, ON}
ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
it = valueProducer->mCurrentSlicedBucket.begin();
@@ -4945,8 +4924,8 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithCondition) {
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(BatterySaverModeStateChanged::ON,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(2, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(2, it->second.intervals[0].value.long_value);
// Pull at end of first bucket.
vector<shared_ptr<LogEvent>> allData;
@@ -4959,23 +4938,23 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithCondition) {
// Base for dimension key {}
ASSERT_EQ(1UL, valueProducer->mCurrentBaseInfo.size());
itBase = valueProducer->mCurrentBaseInfo.find(DEFAULT_DIMENSION_KEY);
- EXPECT_TRUE(itBase->second[0].hasBase);
- EXPECT_EQ(11, itBase->second[0].base.long_value);
- EXPECT_TRUE(itBase->second[0].hasCurrentState);
- ASSERT_EQ(1, itBase->second[0].currentState.getValues().size());
+ EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
+ EXPECT_EQ(11, itBase->second.baseInfos[0].base.long_value);
+ EXPECT_TRUE(itBase->second.hasCurrentState);
+ ASSERT_EQ(1, itBase->second.currentState.getValues().size());
EXPECT_EQ(BatterySaverModeStateChanged::OFF,
- itBase->second[0].currentState.getValues()[0].mValue.int_value);
+ itBase->second.currentState.getValues()[0].mValue.int_value);
// Bucket 2 status after condition change to false.
valueProducer->onConditionChanged(false, bucket2StartTimeNs + 10 * NS_PER_SEC);
// Base for dimension key {}
ASSERT_EQ(1UL, valueProducer->mCurrentBaseInfo.size());
itBase = valueProducer->mCurrentBaseInfo.find(DEFAULT_DIMENSION_KEY);
- EXPECT_FALSE(itBase->second[0].hasBase);
- EXPECT_TRUE(itBase->second[0].hasCurrentState);
- ASSERT_EQ(1, itBase->second[0].currentState.getValues().size());
+ EXPECT_FALSE(itBase->second.baseInfos[0].hasBase);
+ EXPECT_TRUE(itBase->second.hasCurrentState);
+ ASSERT_EQ(1, itBase->second.currentState.getValues().size());
EXPECT_EQ(BatterySaverModeStateChanged::OFF,
- itBase->second[0].currentState.getValues()[0].mValue.int_value);
+ itBase->second.currentState.getValues()[0].mValue.int_value);
// Value for key {{}, OFF}
ASSERT_EQ(3UL, valueProducer->mCurrentSlicedBucket.size());
it = valueProducer->mCurrentSlicedBucket.begin();
@@ -4983,8 +4962,8 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithCondition) {
ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
EXPECT_EQ(BatterySaverModeStateChanged::OFF,
it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_TRUE(it->second[0].hasValue);
- EXPECT_EQ(4, it->second[0].value.long_value);
+ EXPECT_TRUE(it->second.intervals[0].hasValue);
+ EXPECT_EQ(4, it->second.intervals[0].value.long_value);
// Start dump report and check output.
ProtoOutputStream output;
diff --git a/cmds/statsd/tests/metrics/metrics_test_helper.h b/cmds/statsd/tests/metrics/metrics_test_helper.h
index eeb38a4644fd..39232c194ada 100644
--- a/cmds/statsd/tests/metrics/metrics_test_helper.h
+++ b/cmds/statsd/tests/metrics/metrics_test_helper.h
@@ -38,11 +38,10 @@ public:
int64_t nextPulltimeNs, int64_t intervalNs));
MOCK_METHOD3(UnRegisterReceiver,
void(int tagId, const ConfigKey& key, wp<PullDataReceiver> receiver));
- MOCK_METHOD5(Pull, bool(const int pullCode, const ConfigKey& key, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool useUids));
- MOCK_METHOD5(Pull,
- bool(const int pullCode, const vector<int32_t>& uids, const int64_t eventTimeNs,
- vector<std::shared_ptr<LogEvent>>* data, bool useUids));
+ MOCK_METHOD4(Pull, bool(const int pullCode, const ConfigKey& key, const int64_t eventTimeNs,
+ vector<std::shared_ptr<LogEvent>>* data));
+ MOCK_METHOD4(Pull, bool(const int pullCode, const vector<int32_t>& uids,
+ const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data));
MOCK_METHOD2(RegisterPullUidProvider,
void(const ConfigKey& configKey, wp<PullUidProvider> provider));
MOCK_METHOD2(UnregisterPullUidProvider,
diff --git a/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp b/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
new file mode 100644
index 000000000000..843d836a2c0b
--- /dev/null
+++ b/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
@@ -0,0 +1,897 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/metrics/parsing_utils/config_update_utils.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <private/android_filesystem_config.h>
+#include <stdio.h>
+
+#include <set>
+#include <unordered_map>
+#include <vector>
+
+#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
+#include "src/condition/CombinationConditionTracker.h"
+#include "src/condition/SimpleConditionTracker.h"
+#include "src/matchers/CombinationAtomMatchingTracker.h"
+#include "src/metrics/parsing_utils/metrics_manager_util.h"
+#include "tests/statsd_test_util.h"
+
+using namespace testing;
+using android::sp;
+using android::os::statsd::Predicate;
+using std::map;
+using std::set;
+using std::unordered_map;
+using std::vector;
+
+#ifdef __ANDROID__
+
+namespace android {
+namespace os {
+namespace statsd {
+
+namespace {
+
+ConfigKey key(123, 456);
+const int64_t timeBaseNs = 1000;
+sp<UidMap> uidMap = new UidMap();
+sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+sp<AlarmMonitor> anomalyAlarmMonitor;
+sp<AlarmMonitor> periodicAlarmMonitor;
+set<int> allTagIds;
+vector<sp<AtomMatchingTracker>> oldAtomMatchingTrackers;
+unordered_map<int64_t, int> oldAtomMatchingTrackerMap;
+vector<sp<ConditionTracker>> oldConditionTrackers;
+unordered_map<int64_t, int> oldConditionTrackerMap;
+vector<sp<MetricProducer>> oldMetricProducers;
+unordered_map<int64_t, int> oldMetricProducerMap;
+std::vector<sp<AnomalyTracker>> oldAnomalyTrackers;
+std::vector<sp<AlarmTracker>> oldAlarmTrackers;
+unordered_map<int, std::vector<int>> conditionToMetricMap;
+unordered_map<int, std::vector<int>> trackerToMetricMap;
+unordered_map<int, std::vector<int>> trackerToConditionMap;
+unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
+unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
+unordered_map<int64_t, int> alertTrackerMap;
+vector<int> metricsWithActivation;
+map<int64_t, uint64_t> oldStateHashes;
+std::set<int64_t> noReportMetricIds;
+
+class ConfigUpdateTest : public ::testing::Test {
+public:
+ ConfigUpdateTest() {
+ }
+
+ void SetUp() override {
+ allTagIds.clear();
+ oldAtomMatchingTrackers.clear();
+ oldAtomMatchingTrackerMap.clear();
+ oldConditionTrackers.clear();
+ oldConditionTrackerMap.clear();
+ oldMetricProducers.clear();
+ oldMetricProducerMap.clear();
+ oldAnomalyTrackers.clear();
+ oldAlarmTrackers.clear();
+ conditionToMetricMap.clear();
+ trackerToMetricMap.clear();
+ trackerToConditionMap.clear();
+ activationAtomTrackerToMetricMap.clear();
+ deactivationAtomTrackerToMetricMap.clear();
+ alertTrackerMap.clear();
+ metricsWithActivation.clear();
+ oldStateHashes.clear();
+ noReportMetricIds.clear();
+ }
+};
+
+bool initConfig(const StatsdConfig& config) {
+ return initStatsdConfig(
+ key, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
+ timeBaseNs, timeBaseNs, allTagIds, oldAtomMatchingTrackers, oldAtomMatchingTrackerMap,
+ oldConditionTrackers, oldConditionTrackerMap, oldMetricProducers, oldMetricProducerMap,
+ oldAnomalyTrackers, oldAlarmTrackers, conditionToMetricMap, trackerToMetricMap,
+ trackerToConditionMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation,
+ oldStateHashes, noReportMetricIds);
+}
+
+} // anonymous namespace
+
+TEST_F(ConfigUpdateTest, TestSimpleMatcherPreserve) {
+ StatsdConfig config;
+ AtomMatcher matcher = CreateSimpleAtomMatcher("TEST", /*atom=*/10);
+ int64_t matcherId = matcher.id();
+ *config.add_atom_matcher() = matcher;
+
+ // Create an initial config.
+ EXPECT_TRUE(initConfig(config));
+
+ vector<UpdateStatus> matchersToUpdate(1, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(1, false);
+ unordered_map<int64_t, int> newAtomMatchingTrackerMap;
+ newAtomMatchingTrackerMap[matcherId] = 0;
+ EXPECT_TRUE(determineMatcherUpdateStatus(config, 0, oldAtomMatchingTrackerMap,
+ oldAtomMatchingTrackers, newAtomMatchingTrackerMap,
+ matchersToUpdate, cycleTracker));
+ EXPECT_EQ(matchersToUpdate[0], UPDATE_PRESERVE);
+}
+
+TEST_F(ConfigUpdateTest, TestSimpleMatcherReplace) {
+ StatsdConfig config;
+ AtomMatcher matcher = CreateSimpleAtomMatcher("TEST", /*atom=*/10);
+ *config.add_atom_matcher() = matcher;
+
+ EXPECT_TRUE(initConfig(config));
+
+ StatsdConfig newConfig;
+ // Same id, different atom, so should be replaced.
+ AtomMatcher newMatcher = CreateSimpleAtomMatcher("TEST", /*atom=*/11);
+ int64_t matcherId = newMatcher.id();
+ EXPECT_EQ(matcherId, matcher.id());
+ *newConfig.add_atom_matcher() = newMatcher;
+
+ vector<UpdateStatus> matchersToUpdate(1, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(1, false);
+ unordered_map<int64_t, int> newAtomMatchingTrackerMap;
+ newAtomMatchingTrackerMap[matcherId] = 0;
+ EXPECT_TRUE(determineMatcherUpdateStatus(newConfig, 0, oldAtomMatchingTrackerMap,
+ oldAtomMatchingTrackers, newAtomMatchingTrackerMap,
+ matchersToUpdate, cycleTracker));
+ EXPECT_EQ(matchersToUpdate[0], UPDATE_REPLACE);
+}
+
+TEST_F(ConfigUpdateTest, TestSimpleMatcherNew) {
+ StatsdConfig config;
+ AtomMatcher matcher = CreateSimpleAtomMatcher("TEST", /*atom=*/10);
+ *config.add_atom_matcher() = matcher;
+
+ EXPECT_TRUE(initConfig(config));
+
+ StatsdConfig newConfig;
+ // Different id, so should be a new matcher.
+ AtomMatcher newMatcher = CreateSimpleAtomMatcher("DIFFERENT_NAME", /*atom=*/10);
+ int64_t matcherId = newMatcher.id();
+ EXPECT_NE(matcherId, matcher.id());
+ *newConfig.add_atom_matcher() = newMatcher;
+
+ vector<UpdateStatus> matchersToUpdate(1, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(1, false);
+ unordered_map<int64_t, int> newAtomMatchingTrackerMap;
+ newAtomMatchingTrackerMap[matcherId] = 0;
+ EXPECT_TRUE(determineMatcherUpdateStatus(newConfig, 0, oldAtomMatchingTrackerMap,
+ oldAtomMatchingTrackers, newAtomMatchingTrackerMap,
+ matchersToUpdate, cycleTracker));
+ EXPECT_EQ(matchersToUpdate[0], UPDATE_NEW);
+}
+
+TEST_F(ConfigUpdateTest, TestCombinationMatcherPreserve) {
+ StatsdConfig config;
+ AtomMatcher matcher1 = CreateSimpleAtomMatcher("TEST1", /*atom=*/10);
+ int64_t matcher1Id = matcher1.id();
+ *config.add_atom_matcher() = matcher1;
+
+ AtomMatcher matcher2 = CreateSimpleAtomMatcher("TEST2", /*atom=*/11);
+ *config.add_atom_matcher() = matcher2;
+ int64_t matcher2Id = matcher2.id();
+
+ AtomMatcher matcher3;
+ matcher3.set_id(StringToId("TEST3"));
+ AtomMatcher_Combination* combination = matcher3.mutable_combination();
+ combination->set_operation(LogicalOperation::OR);
+ combination->add_matcher(matcher1Id);
+ combination->add_matcher(matcher2Id);
+ int64_t matcher3Id = matcher3.id();
+ *config.add_atom_matcher() = matcher3;
+
+ EXPECT_TRUE(initConfig(config));
+
+ StatsdConfig newConfig;
+ unordered_map<int64_t, int> newAtomMatchingTrackerMap;
+ // Same matchers, different order, all should be preserved.
+ *newConfig.add_atom_matcher() = matcher2;
+ newAtomMatchingTrackerMap[matcher2Id] = 0;
+ *newConfig.add_atom_matcher() = matcher3;
+ newAtomMatchingTrackerMap[matcher3Id] = 1;
+ *newConfig.add_atom_matcher() = matcher1;
+ newAtomMatchingTrackerMap[matcher1Id] = 2;
+
+ vector<UpdateStatus> matchersToUpdate(3, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(3, false);
+ // Only update the combination. It should recurse the two child matchers and preserve all 3.
+ EXPECT_TRUE(determineMatcherUpdateStatus(newConfig, 1, oldAtomMatchingTrackerMap,
+ oldAtomMatchingTrackers, newAtomMatchingTrackerMap,
+ matchersToUpdate, cycleTracker));
+ EXPECT_EQ(matchersToUpdate[0], UPDATE_PRESERVE);
+ EXPECT_EQ(matchersToUpdate[1], UPDATE_PRESERVE);
+ EXPECT_EQ(matchersToUpdate[2], UPDATE_PRESERVE);
+}
+
+TEST_F(ConfigUpdateTest, TestCombinationMatcherReplace) {
+ StatsdConfig config;
+ AtomMatcher matcher1 = CreateSimpleAtomMatcher("TEST1", /*atom=*/10);
+ int64_t matcher1Id = matcher1.id();
+ *config.add_atom_matcher() = matcher1;
+
+ AtomMatcher matcher2 = CreateSimpleAtomMatcher("TEST2", /*atom=*/11);
+ *config.add_atom_matcher() = matcher2;
+ int64_t matcher2Id = matcher2.id();
+
+ AtomMatcher matcher3;
+ matcher3.set_id(StringToId("TEST3"));
+ AtomMatcher_Combination* combination = matcher3.mutable_combination();
+ combination->set_operation(LogicalOperation::OR);
+ combination->add_matcher(matcher1Id);
+ combination->add_matcher(matcher2Id);
+ int64_t matcher3Id = matcher3.id();
+ *config.add_atom_matcher() = matcher3;
+
+ EXPECT_TRUE(initConfig(config));
+
+ // Change the logical operation of the combination matcher, causing a replacement.
+ matcher3.mutable_combination()->set_operation(LogicalOperation::AND);
+
+ StatsdConfig newConfig;
+ unordered_map<int64_t, int> newAtomMatchingTrackerMap;
+ *newConfig.add_atom_matcher() = matcher2;
+ newAtomMatchingTrackerMap[matcher2Id] = 0;
+ *newConfig.add_atom_matcher() = matcher3;
+ newAtomMatchingTrackerMap[matcher3Id] = 1;
+ *newConfig.add_atom_matcher() = matcher1;
+ newAtomMatchingTrackerMap[matcher1Id] = 2;
+
+ vector<UpdateStatus> matchersToUpdate(3, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(3, false);
+ // Only update the combination. The simple matchers should not be evaluated.
+ EXPECT_TRUE(determineMatcherUpdateStatus(newConfig, 1, oldAtomMatchingTrackerMap,
+ oldAtomMatchingTrackers, newAtomMatchingTrackerMap,
+ matchersToUpdate, cycleTracker));
+ EXPECT_EQ(matchersToUpdate[0], UPDATE_UNKNOWN);
+ EXPECT_EQ(matchersToUpdate[1], UPDATE_REPLACE);
+ EXPECT_EQ(matchersToUpdate[2], UPDATE_UNKNOWN);
+}
+
+TEST_F(ConfigUpdateTest, TestCombinationMatcherDepsChange) {
+ StatsdConfig config;
+ AtomMatcher matcher1 = CreateSimpleAtomMatcher("TEST1", /*atom=*/10);
+ int64_t matcher1Id = matcher1.id();
+ *config.add_atom_matcher() = matcher1;
+
+ AtomMatcher matcher2 = CreateSimpleAtomMatcher("TEST2", /*atom=*/11);
+ *config.add_atom_matcher() = matcher2;
+ int64_t matcher2Id = matcher2.id();
+
+ AtomMatcher matcher3;
+ matcher3.set_id(StringToId("TEST3"));
+ AtomMatcher_Combination* combination = matcher3.mutable_combination();
+ combination->set_operation(LogicalOperation::OR);
+ combination->add_matcher(matcher1Id);
+ combination->add_matcher(matcher2Id);
+ int64_t matcher3Id = matcher3.id();
+ *config.add_atom_matcher() = matcher3;
+
+ EXPECT_TRUE(initConfig(config));
+
+ // Change a dependency of matcher 3.
+ matcher2.mutable_simple_atom_matcher()->set_atom_id(12);
+
+ StatsdConfig newConfig;
+ unordered_map<int64_t, int> newAtomMatchingTrackerMap;
+ *newConfig.add_atom_matcher() = matcher2;
+ newAtomMatchingTrackerMap[matcher2Id] = 0;
+ *newConfig.add_atom_matcher() = matcher3;
+ newAtomMatchingTrackerMap[matcher3Id] = 1;
+ *newConfig.add_atom_matcher() = matcher1;
+ newAtomMatchingTrackerMap[matcher1Id] = 2;
+
+ vector<UpdateStatus> matchersToUpdate(3, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(3, false);
+ // Only update the combination.
+ EXPECT_TRUE(determineMatcherUpdateStatus(newConfig, 1, oldAtomMatchingTrackerMap,
+ oldAtomMatchingTrackers, newAtomMatchingTrackerMap,
+ matchersToUpdate, cycleTracker));
+ // Matcher 2 and matcher3 must be reevaluated. Matcher 1 might, but does not need to be.
+ EXPECT_EQ(matchersToUpdate[0], UPDATE_REPLACE);
+ EXPECT_EQ(matchersToUpdate[1], UPDATE_REPLACE);
+}
+
+TEST_F(ConfigUpdateTest, TestUpdateMatchers) {
+ StatsdConfig config;
+ // Will be preserved.
+ AtomMatcher simple1 = CreateSimpleAtomMatcher("SIMPLE1", /*atom=*/10);
+ int64_t simple1Id = simple1.id();
+ *config.add_atom_matcher() = simple1;
+
+ // Will be replaced.
+ AtomMatcher simple2 = CreateSimpleAtomMatcher("SIMPLE2", /*atom=*/11);
+ *config.add_atom_matcher() = simple2;
+ int64_t simple2Id = simple2.id();
+
+ // Will be removed.
+ AtomMatcher simple3 = CreateSimpleAtomMatcher("SIMPLE3", /*atom=*/12);
+ *config.add_atom_matcher() = simple3;
+ int64_t simple3Id = simple3.id();
+
+ // Will be preserved.
+ AtomMatcher combination1;
+ combination1.set_id(StringToId("combination1"));
+ AtomMatcher_Combination* combination = combination1.mutable_combination();
+ combination->set_operation(LogicalOperation::NOT);
+ combination->add_matcher(simple1Id);
+ int64_t combination1Id = combination1.id();
+ *config.add_atom_matcher() = combination1;
+
+ // Will be replaced since it depends on simple2.
+ AtomMatcher combination2;
+ combination2.set_id(StringToId("combination2"));
+ combination = combination2.mutable_combination();
+ combination->set_operation(LogicalOperation::AND);
+ combination->add_matcher(simple1Id);
+ combination->add_matcher(simple2Id);
+ int64_t combination2Id = combination2.id();
+ *config.add_atom_matcher() = combination2;
+
+ EXPECT_TRUE(initConfig(config));
+
+ // Change simple2, causing simple2 and combination2 to be replaced.
+ simple2.mutable_simple_atom_matcher()->set_atom_id(111);
+
+ // 2 new matchers: simple4 and combination3:
+ AtomMatcher simple4 = CreateSimpleAtomMatcher("SIMPLE4", /*atom=*/13);
+ int64_t simple4Id = simple4.id();
+
+ AtomMatcher combination3;
+ combination3.set_id(StringToId("combination3"));
+ combination = combination3.mutable_combination();
+ combination->set_operation(LogicalOperation::AND);
+ combination->add_matcher(simple4Id);
+ combination->add_matcher(simple2Id);
+ int64_t combination3Id = combination3.id();
+
+ StatsdConfig newConfig;
+ *newConfig.add_atom_matcher() = combination3;
+ *newConfig.add_atom_matcher() = simple2;
+ *newConfig.add_atom_matcher() = combination2;
+ *newConfig.add_atom_matcher() = simple1;
+ *newConfig.add_atom_matcher() = simple4;
+ *newConfig.add_atom_matcher() = combination1;
+
+ set<int> newTagIds;
+ unordered_map<int64_t, int> newAtomMatchingTrackerMap;
+ vector<sp<AtomMatchingTracker>> newAtomMatchingTrackers;
+ set<int64_t> replacedMatchers;
+ EXPECT_TRUE(updateAtomMatchingTrackers(
+ newConfig, uidMap, oldAtomMatchingTrackerMap, oldAtomMatchingTrackers, newTagIds,
+ newAtomMatchingTrackerMap, newAtomMatchingTrackers, replacedMatchers));
+
+ ASSERT_EQ(newTagIds.size(), 3);
+ EXPECT_EQ(newTagIds.count(10), 1);
+ EXPECT_EQ(newTagIds.count(111), 1);
+ EXPECT_EQ(newTagIds.count(13), 1);
+
+ ASSERT_EQ(newAtomMatchingTrackerMap.size(), 6);
+ EXPECT_EQ(newAtomMatchingTrackerMap.at(combination3Id), 0);
+ EXPECT_EQ(newAtomMatchingTrackerMap.at(simple2Id), 1);
+ EXPECT_EQ(newAtomMatchingTrackerMap.at(combination2Id), 2);
+ EXPECT_EQ(newAtomMatchingTrackerMap.at(simple1Id), 3);
+ EXPECT_EQ(newAtomMatchingTrackerMap.at(simple4Id), 4);
+ EXPECT_EQ(newAtomMatchingTrackerMap.at(combination1Id), 5);
+
+ ASSERT_EQ(newAtomMatchingTrackers.size(), 6);
+ // Make sure all atom matchers are initialized:
+ for (const sp<AtomMatchingTracker>& tracker : newAtomMatchingTrackers) {
+ EXPECT_TRUE(tracker->mInitialized);
+ }
+ // Make sure preserved atom matchers are the same.
+ EXPECT_EQ(oldAtomMatchingTrackers[oldAtomMatchingTrackerMap.at(simple1Id)],
+ newAtomMatchingTrackers[newAtomMatchingTrackerMap.at(simple1Id)]);
+ EXPECT_EQ(oldAtomMatchingTrackers[oldAtomMatchingTrackerMap.at(combination1Id)],
+ newAtomMatchingTrackers[newAtomMatchingTrackerMap.at(combination1Id)]);
+ // Make sure replaced matchers are different.
+ EXPECT_NE(oldAtomMatchingTrackers[oldAtomMatchingTrackerMap.at(simple2Id)],
+ newAtomMatchingTrackers[newAtomMatchingTrackerMap.at(simple2Id)]);
+ EXPECT_NE(oldAtomMatchingTrackers[oldAtomMatchingTrackerMap.at(combination2Id)],
+ newAtomMatchingTrackers[newAtomMatchingTrackerMap.at(combination2Id)]);
+
+ // Validation, make sure the matchers have the proper ids/indices. Could do more checks here.
+ EXPECT_EQ(newAtomMatchingTrackers[0]->getId(), combination3Id);
+ EXPECT_EQ(newAtomMatchingTrackers[0]->mIndex, 0);
+ EXPECT_EQ(newAtomMatchingTrackers[1]->getId(), simple2Id);
+ EXPECT_EQ(newAtomMatchingTrackers[1]->mIndex, 1);
+ EXPECT_EQ(newAtomMatchingTrackers[2]->getId(), combination2Id);
+ EXPECT_EQ(newAtomMatchingTrackers[2]->mIndex, 2);
+ EXPECT_EQ(newAtomMatchingTrackers[3]->getId(), simple1Id);
+ EXPECT_EQ(newAtomMatchingTrackers[3]->mIndex, 3);
+ EXPECT_EQ(newAtomMatchingTrackers[4]->getId(), simple4Id);
+ EXPECT_EQ(newAtomMatchingTrackers[4]->mIndex, 4);
+ EXPECT_EQ(newAtomMatchingTrackers[5]->getId(), combination1Id);
+ EXPECT_EQ(newAtomMatchingTrackers[5]->mIndex, 5);
+
+ // Verify child indices of Combination Matchers are correct.
+ CombinationAtomMatchingTracker* combinationTracker1 =
+ static_cast<CombinationAtomMatchingTracker*>(newAtomMatchingTrackers[5].get());
+ vector<int>* childMatchers = &combinationTracker1->mChildren;
+ EXPECT_EQ(childMatchers->size(), 1);
+ EXPECT_NE(std::find(childMatchers->begin(), childMatchers->end(), 3), childMatchers->end());
+
+ CombinationAtomMatchingTracker* combinationTracker2 =
+ static_cast<CombinationAtomMatchingTracker*>(newAtomMatchingTrackers[2].get());
+ childMatchers = &combinationTracker2->mChildren;
+ EXPECT_EQ(childMatchers->size(), 2);
+ EXPECT_NE(std::find(childMatchers->begin(), childMatchers->end(), 1), childMatchers->end());
+ EXPECT_NE(std::find(childMatchers->begin(), childMatchers->end(), 3), childMatchers->end());
+
+ CombinationAtomMatchingTracker* combinationTracker3 =
+ static_cast<CombinationAtomMatchingTracker*>(newAtomMatchingTrackers[0].get());
+ childMatchers = &combinationTracker3->mChildren;
+ EXPECT_EQ(childMatchers->size(), 2);
+ EXPECT_NE(std::find(childMatchers->begin(), childMatchers->end(), 1), childMatchers->end());
+ EXPECT_NE(std::find(childMatchers->begin(), childMatchers->end(), 4), childMatchers->end());
+
+ // Expect replacedMatchers to have simple2 and combination2
+ ASSERT_EQ(replacedMatchers.size(), 2);
+ EXPECT_NE(replacedMatchers.find(simple2Id), replacedMatchers.end());
+ EXPECT_NE(replacedMatchers.find(combination2Id), replacedMatchers.end());
+}
+
+TEST_F(ConfigUpdateTest, TestSimpleConditionPreserve) {
+ StatsdConfig config;
+ AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = startMatcher;
+ AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher();
+ *config.add_atom_matcher() = stopMatcher;
+
+ Predicate predicate = CreateScreenIsOnPredicate();
+ *config.add_predicate() = predicate;
+
+ // Create an initial config.
+ EXPECT_TRUE(initConfig(config));
+
+ set<int64_t> replacedMatchers;
+ vector<UpdateStatus> conditionsToUpdate(1, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(1, false);
+ unordered_map<int64_t, int> newConditionTrackerMap;
+ newConditionTrackerMap[predicate.id()] = 0;
+ EXPECT_TRUE(determineConditionUpdateStatus(config, 0, oldConditionTrackerMap,
+ oldConditionTrackers, newConditionTrackerMap,
+ replacedMatchers, conditionsToUpdate, cycleTracker));
+ EXPECT_EQ(conditionsToUpdate[0], UPDATE_PRESERVE);
+}
+
+TEST_F(ConfigUpdateTest, TestSimpleConditionReplace) {
+ StatsdConfig config;
+ AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = startMatcher;
+ AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher();
+ *config.add_atom_matcher() = stopMatcher;
+
+ Predicate predicate = CreateScreenIsOnPredicate();
+ *config.add_predicate() = predicate;
+
+ EXPECT_TRUE(initConfig(config));
+
+ // Modify the predicate.
+ config.mutable_predicate(0)->mutable_simple_predicate()->set_count_nesting(true);
+
+ set<int64_t> replacedMatchers;
+ vector<UpdateStatus> conditionsToUpdate(1, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(1, false);
+ unordered_map<int64_t, int> newConditionTrackerMap;
+ newConditionTrackerMap[predicate.id()] = 0;
+ EXPECT_TRUE(determineConditionUpdateStatus(config, 0, oldConditionTrackerMap,
+ oldConditionTrackers, newConditionTrackerMap,
+ replacedMatchers, conditionsToUpdate, cycleTracker));
+ EXPECT_EQ(conditionsToUpdate[0], UPDATE_REPLACE);
+}
+
+TEST_F(ConfigUpdateTest, TestSimpleConditionDepsChange) {
+ StatsdConfig config;
+ AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher();
+ int64_t startMatcherId = startMatcher.id();
+ *config.add_atom_matcher() = startMatcher;
+ AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher();
+ *config.add_atom_matcher() = stopMatcher;
+
+ Predicate predicate = CreateScreenIsOnPredicate();
+ *config.add_predicate() = predicate;
+
+ EXPECT_TRUE(initConfig(config));
+
+ // Start matcher was replaced.
+ set<int64_t> replacedMatchers;
+ replacedMatchers.insert(startMatcherId);
+
+ vector<UpdateStatus> conditionsToUpdate(1, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(1, false);
+ unordered_map<int64_t, int> newConditionTrackerMap;
+ newConditionTrackerMap[predicate.id()] = 0;
+ EXPECT_TRUE(determineConditionUpdateStatus(config, 0, oldConditionTrackerMap,
+ oldConditionTrackers, newConditionTrackerMap,
+ replacedMatchers, conditionsToUpdate, cycleTracker));
+ EXPECT_EQ(conditionsToUpdate[0], UPDATE_REPLACE);
+}
+
+TEST_F(ConfigUpdateTest, TestCombinationConditionPreserve) {
+ StatsdConfig config;
+ AtomMatcher screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = screenOnMatcher;
+ AtomMatcher screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
+ *config.add_atom_matcher() = screenOffMatcher;
+
+ Predicate simple1 = CreateScreenIsOnPredicate();
+ *config.add_predicate() = simple1;
+ Predicate simple2 = CreateScreenIsOffPredicate();
+ *config.add_predicate() = simple2;
+
+ Predicate combination1;
+ combination1.set_id(StringToId("COMBINATION1"));
+ Predicate_Combination* combinationInternal = combination1.mutable_combination();
+ combinationInternal->set_operation(LogicalOperation::NAND);
+ combinationInternal->add_predicate(simple1.id());
+ combinationInternal->add_predicate(simple2.id());
+ *config.add_predicate() = combination1;
+
+ EXPECT_TRUE(initConfig(config));
+
+ // Same predicates, different order
+ StatsdConfig newConfig;
+ unordered_map<int64_t, int> newConditionTrackerMap;
+ *newConfig.add_predicate() = combination1;
+ newConditionTrackerMap[combination1.id()] = 0;
+ *newConfig.add_predicate() = simple2;
+ newConditionTrackerMap[simple2.id()] = 1;
+ *newConfig.add_predicate() = simple1;
+ newConditionTrackerMap[simple1.id()] = 2;
+
+ set<int64_t> replacedMatchers;
+ vector<UpdateStatus> conditionsToUpdate(3, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(3, false);
+ // Only update the combination. It should recurse the two child predicates and preserve all 3.
+ EXPECT_TRUE(determineConditionUpdateStatus(newConfig, 0, oldConditionTrackerMap,
+ oldConditionTrackers, newConditionTrackerMap,
+ replacedMatchers, conditionsToUpdate, cycleTracker));
+ EXPECT_EQ(conditionsToUpdate[0], UPDATE_PRESERVE);
+ EXPECT_EQ(conditionsToUpdate[1], UPDATE_PRESERVE);
+ EXPECT_EQ(conditionsToUpdate[2], UPDATE_PRESERVE);
+}
+
+TEST_F(ConfigUpdateTest, TestCombinationConditionReplace) {
+ StatsdConfig config;
+ AtomMatcher screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = screenOnMatcher;
+ AtomMatcher screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
+ *config.add_atom_matcher() = screenOffMatcher;
+
+ Predicate simple1 = CreateScreenIsOnPredicate();
+ *config.add_predicate() = simple1;
+ Predicate simple2 = CreateScreenIsOffPredicate();
+ *config.add_predicate() = simple2;
+
+ Predicate combination1;
+ combination1.set_id(StringToId("COMBINATION1"));
+ Predicate_Combination* combinationInternal = combination1.mutable_combination();
+ combinationInternal->set_operation(LogicalOperation::NAND);
+ combinationInternal->add_predicate(simple1.id());
+ combinationInternal->add_predicate(simple2.id());
+ *config.add_predicate() = combination1;
+
+ EXPECT_TRUE(initConfig(config));
+
+ // Changing the logical operation changes the predicate definition, so it should be replaced.
+ combination1.mutable_combination()->set_operation(LogicalOperation::OR);
+
+ StatsdConfig newConfig;
+ unordered_map<int64_t, int> newConditionTrackerMap;
+ *newConfig.add_predicate() = combination1;
+ newConditionTrackerMap[combination1.id()] = 0;
+ *newConfig.add_predicate() = simple2;
+ newConditionTrackerMap[simple2.id()] = 1;
+ *newConfig.add_predicate() = simple1;
+ newConditionTrackerMap[simple1.id()] = 2;
+
+ set<int64_t> replacedMatchers;
+ vector<UpdateStatus> conditionsToUpdate(3, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(3, false);
+ // Only update the combination. The simple conditions should not be evaluated.
+ EXPECT_TRUE(determineConditionUpdateStatus(newConfig, 0, oldConditionTrackerMap,
+ oldConditionTrackers, newConditionTrackerMap,
+ replacedMatchers, conditionsToUpdate, cycleTracker));
+ EXPECT_EQ(conditionsToUpdate[0], UPDATE_REPLACE);
+ EXPECT_EQ(conditionsToUpdate[1], UPDATE_UNKNOWN);
+ EXPECT_EQ(conditionsToUpdate[2], UPDATE_UNKNOWN);
+}
+
+TEST_F(ConfigUpdateTest, TestCombinationConditionDepsChange) {
+ StatsdConfig config;
+ AtomMatcher screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = screenOnMatcher;
+ AtomMatcher screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
+ *config.add_atom_matcher() = screenOffMatcher;
+
+ Predicate simple1 = CreateScreenIsOnPredicate();
+ *config.add_predicate() = simple1;
+ Predicate simple2 = CreateScreenIsOffPredicate();
+ *config.add_predicate() = simple2;
+
+ Predicate combination1;
+ combination1.set_id(StringToId("COMBINATION1"));
+ Predicate_Combination* combinationInternal = combination1.mutable_combination();
+ combinationInternal->set_operation(LogicalOperation::NAND);
+ combinationInternal->add_predicate(simple1.id());
+ combinationInternal->add_predicate(simple2.id());
+ *config.add_predicate() = combination1;
+
+ EXPECT_TRUE(initConfig(config));
+
+ simple2.mutable_simple_predicate()->set_count_nesting(false);
+
+ StatsdConfig newConfig;
+ unordered_map<int64_t, int> newConditionTrackerMap;
+ *newConfig.add_predicate() = combination1;
+ newConditionTrackerMap[combination1.id()] = 0;
+ *newConfig.add_predicate() = simple2;
+ newConditionTrackerMap[simple2.id()] = 1;
+ *newConfig.add_predicate() = simple1;
+ newConditionTrackerMap[simple1.id()] = 2;
+
+ set<int64_t> replacedMatchers;
+ vector<UpdateStatus> conditionsToUpdate(3, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(3, false);
+ // Only update the combination. Simple2 and combination1 must be evaluated.
+ EXPECT_TRUE(determineConditionUpdateStatus(newConfig, 0, oldConditionTrackerMap,
+ oldConditionTrackers, newConditionTrackerMap,
+ replacedMatchers, conditionsToUpdate, cycleTracker));
+ EXPECT_EQ(conditionsToUpdate[0], UPDATE_REPLACE);
+ EXPECT_EQ(conditionsToUpdate[1], UPDATE_REPLACE);
+}
+
+TEST_F(ConfigUpdateTest, TestUpdateConditions) {
+ StatsdConfig config;
+
+ // Add atom matchers. These are mostly needed for initStatsdConfig
+ AtomMatcher matcher1 = CreateScreenTurnedOnAtomMatcher();
+ int64_t matcher1Id = matcher1.id();
+ *config.add_atom_matcher() = matcher1;
+
+ AtomMatcher matcher2 = CreateScreenTurnedOffAtomMatcher();
+ int64_t matcher2Id = matcher2.id();
+ *config.add_atom_matcher() = matcher2;
+
+ AtomMatcher matcher3 = CreateStartScheduledJobAtomMatcher();
+ int64_t matcher3Id = matcher3.id();
+ *config.add_atom_matcher() = matcher3;
+
+ AtomMatcher matcher4 = CreateFinishScheduledJobAtomMatcher();
+ int64_t matcher4Id = matcher4.id();
+ *config.add_atom_matcher() = matcher4;
+
+ AtomMatcher matcher5 = CreateBatterySaverModeStartAtomMatcher();
+ int64_t matcher5Id = matcher5.id();
+ *config.add_atom_matcher() = matcher5;
+
+ AtomMatcher matcher6 = CreateBatterySaverModeStopAtomMatcher();
+ int64_t matcher6Id = matcher6.id();
+ *config.add_atom_matcher() = matcher6;
+
+ // Add the predicates.
+ // Will be preserved.
+ Predicate simple1 = CreateScreenIsOnPredicate();
+ int64_t simple1Id = simple1.id();
+ *config.add_predicate() = simple1;
+
+ // Will be preserved.
+ Predicate simple2 = CreateScheduledJobPredicate();
+ int64_t simple2Id = simple2.id();
+ *config.add_predicate() = simple2;
+
+ // Will be replaced.
+ Predicate simple3 = CreateBatterySaverModePredicate();
+ int64_t simple3Id = simple3.id();
+ *config.add_predicate() = simple3;
+
+ // Will be preserved
+ Predicate combination1;
+ combination1.set_id(StringToId("COMBINATION1"));
+ combination1.mutable_combination()->set_operation(LogicalOperation::AND);
+ combination1.mutable_combination()->add_predicate(simple1Id);
+ combination1.mutable_combination()->add_predicate(simple2Id);
+ int64_t combination1Id = combination1.id();
+ *config.add_predicate() = combination1;
+
+ // Will be replaced since simple3 will be replaced.
+ Predicate combination2;
+ combination2.set_id(StringToId("COMBINATION2"));
+ combination2.mutable_combination()->set_operation(LogicalOperation::OR);
+ combination2.mutable_combination()->add_predicate(simple1Id);
+ combination2.mutable_combination()->add_predicate(simple3Id);
+ int64_t combination2Id = combination2.id();
+ *config.add_predicate() = combination2;
+
+ // Will be removed.
+ Predicate combination3;
+ combination3.set_id(StringToId("COMBINATION3"));
+ combination3.mutable_combination()->set_operation(LogicalOperation::NOT);
+ combination3.mutable_combination()->add_predicate(simple2Id);
+ int64_t combination3Id = combination3.id();
+ *config.add_predicate() = combination3;
+
+ EXPECT_TRUE(initConfig(config));
+
+ // Mark marcher 5 as replaced. Causes simple3, and therefore combination2 to be replaced.
+ set<int64_t> replacedMatchers;
+ replacedMatchers.insert(matcher6Id);
+
+ // Change the condition of simple1 to true.
+ ASSERT_EQ(oldConditionTrackers[0]->getConditionId(), simple1Id);
+ LogEvent event(/*uid=*/0, /*pid=*/0); // Empty event is fine since there are no dimensions.
+ // Mark the stop matcher as matched, condition should be false.
+ vector<MatchingState> eventMatcherValues(6, MatchingState::kNotMatched);
+ eventMatcherValues[1] = MatchingState::kMatched;
+ vector<ConditionState> tmpConditionCache(6, ConditionState::kNotEvaluated);
+ vector<bool> conditionChangeCache(6, false);
+ oldConditionTrackers[0]->evaluateCondition(event, eventMatcherValues, oldConditionTrackers,
+ tmpConditionCache, conditionChangeCache);
+ EXPECT_EQ(tmpConditionCache[0], ConditionState::kFalse);
+ EXPECT_EQ(conditionChangeCache[0], true);
+
+ // New combination matcher. Should have an initial condition of true since it is NOT(simple1).
+ Predicate combination4;
+ combination4.set_id(StringToId("COMBINATION4"));
+ combination4.mutable_combination()->set_operation(LogicalOperation::NOT);
+ combination4.mutable_combination()->add_predicate(simple1Id);
+ int64_t combination4Id = combination4.id();
+ *config.add_predicate() = combination4;
+
+ // Map the matchers in reverse order to force the indices to change.
+ std::unordered_map<int64_t, int> newAtomMatchingTrackerMap;
+ const int matcher6Index = 0;
+ newAtomMatchingTrackerMap[matcher6Id] = 0;
+ const int matcher5Index = 1;
+ newAtomMatchingTrackerMap[matcher5Id] = 1;
+ const int matcher4Index = 2;
+ newAtomMatchingTrackerMap[matcher4Id] = 2;
+ const int matcher3Index = 3;
+ newAtomMatchingTrackerMap[matcher3Id] = 3;
+ const int matcher2Index = 4;
+ newAtomMatchingTrackerMap[matcher2Id] = 4;
+ const int matcher1Index = 5;
+ newAtomMatchingTrackerMap[matcher1Id] = 5;
+
+ StatsdConfig newConfig;
+ *newConfig.add_predicate() = simple3;
+ const int simple3Index = 0;
+ *newConfig.add_predicate() = combination2;
+ const int combination2Index = 1;
+ *newConfig.add_predicate() = combination4;
+ const int combination4Index = 2;
+ *newConfig.add_predicate() = simple2;
+ const int simple2Index = 3;
+ *newConfig.add_predicate() = combination1;
+ const int combination1Index = 4;
+ *newConfig.add_predicate() = simple1;
+ const int simple1Index = 5;
+
+ unordered_map<int64_t, int> newConditionTrackerMap;
+ vector<sp<ConditionTracker>> newConditionTrackers;
+ unordered_map<int, vector<int>> trackerToConditionMap;
+ std::vector<ConditionState> conditionCache;
+ std::set<int64_t> replacedConditions;
+ EXPECT_TRUE(updateConditions(key, newConfig, newAtomMatchingTrackerMap, replacedMatchers,
+ oldConditionTrackerMap, oldConditionTrackers,
+ newConditionTrackerMap, newConditionTrackers,
+ trackerToConditionMap, conditionCache, replacedConditions));
+
+ unordered_map<int64_t, int> expectedConditionTrackerMap = {
+ {simple1Id, simple1Index}, {simple2Id, simple2Index},
+ {simple3Id, simple3Index}, {combination1Id, combination1Index},
+ {combination2Id, combination2Index}, {combination4Id, combination4Index},
+ };
+ EXPECT_THAT(newConditionTrackerMap, ContainerEq(expectedConditionTrackerMap));
+
+ ASSERT_EQ(newConditionTrackers.size(), 6);
+ // Make sure all conditions are initialized:
+ for (const sp<ConditionTracker>& tracker : newConditionTrackers) {
+ EXPECT_TRUE(tracker->mInitialized);
+ }
+
+ // Make sure preserved conditions are the same.
+ EXPECT_EQ(oldConditionTrackers[oldConditionTrackerMap.at(simple1Id)],
+ newConditionTrackers[newConditionTrackerMap.at(simple1Id)]);
+ EXPECT_EQ(oldConditionTrackers[oldConditionTrackerMap.at(simple2Id)],
+ newConditionTrackers[newConditionTrackerMap.at(simple2Id)]);
+ EXPECT_EQ(oldConditionTrackers[oldConditionTrackerMap.at(combination1Id)],
+ newConditionTrackers[newConditionTrackerMap.at(combination1Id)]);
+
+ // Make sure replaced conditions are different and included in replacedConditions.
+ EXPECT_NE(oldConditionTrackers[oldConditionTrackerMap.at(simple3Id)],
+ newConditionTrackers[newConditionTrackerMap.at(simple3Id)]);
+ EXPECT_NE(oldConditionTrackers[oldConditionTrackerMap.at(combination2Id)],
+ newConditionTrackers[newConditionTrackerMap.at(combination2Id)]);
+ EXPECT_THAT(replacedConditions, ContainerEq(set({simple3Id, combination2Id})));
+
+ // Verify the trackerToConditionMap
+ ASSERT_EQ(trackerToConditionMap.size(), 6);
+ const vector<int>& matcher1Conditions = trackerToConditionMap[matcher1Index];
+ EXPECT_THAT(matcher1Conditions, UnorderedElementsAre(simple1Index, combination1Index,
+ combination2Index, combination4Index));
+ const vector<int>& matcher2Conditions = trackerToConditionMap[matcher2Index];
+ EXPECT_THAT(matcher2Conditions, UnorderedElementsAre(simple1Index, combination1Index,
+ combination2Index, combination4Index));
+ const vector<int>& matcher3Conditions = trackerToConditionMap[matcher3Index];
+ EXPECT_THAT(matcher3Conditions, UnorderedElementsAre(simple2Index, combination1Index));
+ const vector<int>& matcher4Conditions = trackerToConditionMap[matcher4Index];
+ EXPECT_THAT(matcher4Conditions, UnorderedElementsAre(simple2Index, combination1Index));
+ const vector<int>& matcher5Conditions = trackerToConditionMap[matcher5Index];
+ EXPECT_THAT(matcher5Conditions, UnorderedElementsAre(simple3Index, combination2Index));
+ const vector<int>& matcher6Conditions = trackerToConditionMap[matcher6Index];
+ EXPECT_THAT(matcher6Conditions, UnorderedElementsAre(simple3Index, combination2Index));
+
+ // Verify the conditionCache. Specifically, simple1 is false and combination4 is true.
+ ASSERT_EQ(conditionCache.size(), 6);
+ EXPECT_EQ(conditionCache[simple1Index], ConditionState::kFalse);
+ EXPECT_EQ(conditionCache[simple2Index], ConditionState::kUnknown);
+ EXPECT_EQ(conditionCache[simple3Index], ConditionState::kUnknown);
+ EXPECT_EQ(conditionCache[combination1Index], ConditionState::kUnknown);
+ EXPECT_EQ(conditionCache[combination2Index], ConditionState::kUnknown);
+ EXPECT_EQ(conditionCache[combination4Index], ConditionState::kTrue);
+
+ // Verify tracker indices/ids are correct.
+ EXPECT_EQ(newConditionTrackers[simple1Index]->getConditionId(), simple1Id);
+ EXPECT_EQ(newConditionTrackers[simple1Index]->mIndex, simple1Index);
+ EXPECT_TRUE(newConditionTrackers[simple1Index]->IsSimpleCondition());
+ EXPECT_EQ(newConditionTrackers[simple2Index]->getConditionId(), simple2Id);
+ EXPECT_EQ(newConditionTrackers[simple2Index]->mIndex, simple2Index);
+ EXPECT_TRUE(newConditionTrackers[simple2Index]->IsSimpleCondition());
+ EXPECT_EQ(newConditionTrackers[simple3Index]->getConditionId(), simple3Id);
+ EXPECT_EQ(newConditionTrackers[simple3Index]->mIndex, simple3Index);
+ EXPECT_TRUE(newConditionTrackers[simple3Index]->IsSimpleCondition());
+ EXPECT_EQ(newConditionTrackers[combination1Index]->getConditionId(), combination1Id);
+ EXPECT_EQ(newConditionTrackers[combination1Index]->mIndex, combination1Index);
+ EXPECT_FALSE(newConditionTrackers[combination1Index]->IsSimpleCondition());
+ EXPECT_EQ(newConditionTrackers[combination2Index]->getConditionId(), combination2Id);
+ EXPECT_EQ(newConditionTrackers[combination2Index]->mIndex, combination2Index);
+ EXPECT_FALSE(newConditionTrackers[combination2Index]->IsSimpleCondition());
+ EXPECT_EQ(newConditionTrackers[combination4Index]->getConditionId(), combination4Id);
+ EXPECT_EQ(newConditionTrackers[combination4Index]->mIndex, combination4Index);
+ EXPECT_FALSE(newConditionTrackers[combination4Index]->IsSimpleCondition());
+
+ // Verify preserved trackers have indices updated.
+ SimpleConditionTracker* simpleTracker1 =
+ static_cast<SimpleConditionTracker*>(newConditionTrackers[simple1Index].get());
+ EXPECT_EQ(simpleTracker1->mStartLogMatcherIndex, matcher1Index);
+ EXPECT_EQ(simpleTracker1->mStopLogMatcherIndex, matcher2Index);
+ EXPECT_EQ(simpleTracker1->mStopAllLogMatcherIndex, -1);
+
+ SimpleConditionTracker* simpleTracker2 =
+ static_cast<SimpleConditionTracker*>(newConditionTrackers[simple2Index].get());
+ EXPECT_EQ(simpleTracker2->mStartLogMatcherIndex, matcher3Index);
+ EXPECT_EQ(simpleTracker2->mStopLogMatcherIndex, matcher4Index);
+ EXPECT_EQ(simpleTracker2->mStopAllLogMatcherIndex, -1);
+
+ CombinationConditionTracker* combinationTracker1 = static_cast<CombinationConditionTracker*>(
+ newConditionTrackers[combination1Index].get());
+ EXPECT_THAT(combinationTracker1->mChildren, UnorderedElementsAre(simple1Index, simple2Index));
+ EXPECT_THAT(combinationTracker1->mUnSlicedChildren,
+ UnorderedElementsAre(simple1Index, simple2Index));
+ EXPECT_THAT(combinationTracker1->mSlicedChildren, IsEmpty());
+}
+} // namespace statsd
+} // namespace os
+} // namespace android
+
+#else
+GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
diff --git a/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp b/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp
new file mode 100644
index 000000000000..0d0a8960043e
--- /dev/null
+++ b/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp
@@ -0,0 +1,802 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/metrics/parsing_utils/metrics_manager_util.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <private/android_filesystem_config.h>
+#include <stdio.h>
+
+#include <set>
+#include <unordered_map>
+#include <vector>
+
+#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
+#include "src/condition/ConditionTracker.h"
+#include "src/matchers/AtomMatchingTracker.h"
+#include "src/metrics/CountMetricProducer.h"
+#include "src/metrics/GaugeMetricProducer.h"
+#include "src/metrics/MetricProducer.h"
+#include "src/metrics/ValueMetricProducer.h"
+#include "src/state/StateManager.h"
+#include "tests/metrics/metrics_test_helper.h"
+#include "tests/statsd_test_util.h"
+
+using namespace testing;
+using android::sp;
+using android::os::statsd::Predicate;
+using std::map;
+using std::set;
+using std::unordered_map;
+using std::vector;
+
+#ifdef __ANDROID__
+
+namespace android {
+namespace os {
+namespace statsd {
+
+namespace {
+const ConfigKey kConfigKey(0, 12345);
+const long kAlertId = 3;
+
+const long timeBaseSec = 1000;
+
+StatsdConfig buildGoodConfig() {
+ StatsdConfig config;
+ config.set_id(12345);
+
+ AtomMatcher* eventMatcher = config.add_atom_matcher();
+ eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
+
+ SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
+ simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
+ simpleAtomMatcher->add_field_value_matcher()->set_field(
+ 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
+ simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
+ 2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
+
+ eventMatcher = config.add_atom_matcher();
+ eventMatcher->set_id(StringToId("SCREEN_IS_OFF"));
+
+ simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
+ simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
+ simpleAtomMatcher->add_field_value_matcher()->set_field(
+ 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
+ simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
+ 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_OFF*/);
+
+ eventMatcher = config.add_atom_matcher();
+ eventMatcher->set_id(StringToId("SCREEN_ON_OR_OFF"));
+
+ AtomMatcher_Combination* combination = eventMatcher->mutable_combination();
+ combination->set_operation(LogicalOperation::OR);
+ combination->add_matcher(StringToId("SCREEN_IS_ON"));
+ combination->add_matcher(StringToId("SCREEN_IS_OFF"));
+
+ CountMetric* metric = config.add_count_metric();
+ metric->set_id(3);
+ metric->set_what(StringToId("SCREEN_IS_ON"));
+ metric->set_bucket(ONE_MINUTE);
+ metric->mutable_dimensions_in_what()->set_field(2 /*SCREEN_STATE_CHANGE*/);
+ metric->mutable_dimensions_in_what()->add_child()->set_field(1);
+
+ config.add_no_report_metric(3);
+
+ auto alert = config.add_alert();
+ alert->set_id(kAlertId);
+ alert->set_metric_id(3);
+ alert->set_num_buckets(10);
+ alert->set_refractory_period_secs(100);
+ alert->set_trigger_if_sum_gt(100);
+ return config;
+}
+
+StatsdConfig buildCircleMatchers() {
+ StatsdConfig config;
+ config.set_id(12345);
+
+ AtomMatcher* eventMatcher = config.add_atom_matcher();
+ eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
+
+ SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
+ simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
+ simpleAtomMatcher->add_field_value_matcher()->set_field(
+ 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
+ simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
+ 2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
+
+ eventMatcher = config.add_atom_matcher();
+ eventMatcher->set_id(StringToId("SCREEN_ON_OR_OFF"));
+
+ AtomMatcher_Combination* combination = eventMatcher->mutable_combination();
+ combination->set_operation(LogicalOperation::OR);
+ combination->add_matcher(StringToId("SCREEN_IS_ON"));
+ // Circle dependency
+ combination->add_matcher(StringToId("SCREEN_ON_OR_OFF"));
+
+ return config;
+}
+
+StatsdConfig buildAlertWithUnknownMetric() {
+ StatsdConfig config;
+ config.set_id(12345);
+
+ AtomMatcher* eventMatcher = config.add_atom_matcher();
+ eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
+
+ CountMetric* metric = config.add_count_metric();
+ metric->set_id(3);
+ metric->set_what(StringToId("SCREEN_IS_ON"));
+ metric->set_bucket(ONE_MINUTE);
+ metric->mutable_dimensions_in_what()->set_field(2 /*SCREEN_STATE_CHANGE*/);
+ metric->mutable_dimensions_in_what()->add_child()->set_field(1);
+
+ auto alert = config.add_alert();
+ alert->set_id(3);
+ alert->set_metric_id(2);
+ alert->set_num_buckets(10);
+ alert->set_refractory_period_secs(100);
+ alert->set_trigger_if_sum_gt(100);
+ return config;
+}
+
+StatsdConfig buildMissingMatchers() {
+ StatsdConfig config;
+ config.set_id(12345);
+
+ AtomMatcher* eventMatcher = config.add_atom_matcher();
+ eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
+
+ SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
+ simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
+ simpleAtomMatcher->add_field_value_matcher()->set_field(
+ 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
+ simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
+ 2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
+
+ eventMatcher = config.add_atom_matcher();
+ eventMatcher->set_id(StringToId("SCREEN_ON_OR_OFF"));
+
+ AtomMatcher_Combination* combination = eventMatcher->mutable_combination();
+ combination->set_operation(LogicalOperation::OR);
+ combination->add_matcher(StringToId("SCREEN_IS_ON"));
+ // undefined matcher
+ combination->add_matcher(StringToId("ABC"));
+
+ return config;
+}
+
+StatsdConfig buildMissingPredicate() {
+ StatsdConfig config;
+ config.set_id(12345);
+
+ CountMetric* metric = config.add_count_metric();
+ metric->set_id(3);
+ metric->set_what(StringToId("SCREEN_EVENT"));
+ metric->set_bucket(ONE_MINUTE);
+ metric->set_condition(StringToId("SOME_CONDITION"));
+
+ AtomMatcher* eventMatcher = config.add_atom_matcher();
+ eventMatcher->set_id(StringToId("SCREEN_EVENT"));
+
+ SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
+ simpleAtomMatcher->set_atom_id(2);
+
+ return config;
+}
+
+StatsdConfig buildDimensionMetricsWithMultiTags() {
+ StatsdConfig config;
+ config.set_id(12345);
+
+ AtomMatcher* eventMatcher = config.add_atom_matcher();
+ eventMatcher->set_id(StringToId("BATTERY_VERY_LOW"));
+ SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
+ simpleAtomMatcher->set_atom_id(2);
+
+ eventMatcher = config.add_atom_matcher();
+ eventMatcher->set_id(StringToId("BATTERY_VERY_VERY_LOW"));
+ simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
+ simpleAtomMatcher->set_atom_id(3);
+
+ eventMatcher = config.add_atom_matcher();
+ eventMatcher->set_id(StringToId("BATTERY_LOW"));
+
+ AtomMatcher_Combination* combination = eventMatcher->mutable_combination();
+ combination->set_operation(LogicalOperation::OR);
+ combination->add_matcher(StringToId("BATTERY_VERY_LOW"));
+ combination->add_matcher(StringToId("BATTERY_VERY_VERY_LOW"));
+
+ // Count process state changes, slice by uid, while SCREEN_IS_OFF
+ CountMetric* metric = config.add_count_metric();
+ metric->set_id(3);
+ metric->set_what(StringToId("BATTERY_LOW"));
+ metric->set_bucket(ONE_MINUTE);
+ // This case is interesting. We want to dimension across two atoms.
+ metric->mutable_dimensions_in_what()->add_child()->set_field(1);
+
+ auto alert = config.add_alert();
+ alert->set_id(kAlertId);
+ alert->set_metric_id(3);
+ alert->set_num_buckets(10);
+ alert->set_refractory_period_secs(100);
+ alert->set_trigger_if_sum_gt(100);
+ return config;
+}
+
+StatsdConfig buildCirclePredicates() {
+ StatsdConfig config;
+ config.set_id(12345);
+
+ AtomMatcher* eventMatcher = config.add_atom_matcher();
+ eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
+
+ SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
+ simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
+ simpleAtomMatcher->add_field_value_matcher()->set_field(
+ 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
+ simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
+ 2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
+
+ eventMatcher = config.add_atom_matcher();
+ eventMatcher->set_id(StringToId("SCREEN_IS_OFF"));
+
+ simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
+ simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
+ simpleAtomMatcher->add_field_value_matcher()->set_field(
+ 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
+ simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
+ 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_OFF*/);
+
+ auto condition = config.add_predicate();
+ condition->set_id(StringToId("SCREEN_IS_ON"));
+ SimplePredicate* simplePredicate = condition->mutable_simple_predicate();
+ simplePredicate->set_start(StringToId("SCREEN_IS_ON"));
+ simplePredicate->set_stop(StringToId("SCREEN_IS_OFF"));
+
+ condition = config.add_predicate();
+ condition->set_id(StringToId("SCREEN_IS_EITHER_ON_OFF"));
+
+ Predicate_Combination* combination = condition->mutable_combination();
+ combination->set_operation(LogicalOperation::OR);
+ combination->add_predicate(StringToId("SCREEN_IS_ON"));
+ combination->add_predicate(StringToId("SCREEN_IS_EITHER_ON_OFF"));
+
+ return config;
+}
+
+StatsdConfig buildConfigWithDifferentPredicates() {
+ StatsdConfig config;
+ config.set_id(12345);
+
+ auto pulledAtomMatcher =
+ CreateSimpleAtomMatcher("SUBSYSTEM_SLEEP", util::SUBSYSTEM_SLEEP_STATE);
+ *config.add_atom_matcher() = pulledAtomMatcher;
+ auto screenOnAtomMatcher = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = screenOnAtomMatcher;
+ auto screenOffAtomMatcher = CreateScreenTurnedOffAtomMatcher();
+ *config.add_atom_matcher() = screenOffAtomMatcher;
+ auto batteryNoneAtomMatcher = CreateBatteryStateNoneMatcher();
+ *config.add_atom_matcher() = batteryNoneAtomMatcher;
+ auto batteryUsbAtomMatcher = CreateBatteryStateUsbMatcher();
+ *config.add_atom_matcher() = batteryUsbAtomMatcher;
+
+ // Simple condition with InitialValue set to default (unknown).
+ auto screenOnUnknownPredicate = CreateScreenIsOnPredicate();
+ *config.add_predicate() = screenOnUnknownPredicate;
+
+ // Simple condition with InitialValue set to false.
+ auto screenOnFalsePredicate = config.add_predicate();
+ screenOnFalsePredicate->set_id(StringToId("ScreenIsOnInitialFalse"));
+ SimplePredicate* simpleScreenOnFalsePredicate =
+ screenOnFalsePredicate->mutable_simple_predicate();
+ simpleScreenOnFalsePredicate->set_start(screenOnAtomMatcher.id());
+ simpleScreenOnFalsePredicate->set_stop(screenOffAtomMatcher.id());
+ simpleScreenOnFalsePredicate->set_initial_value(SimplePredicate_InitialValue_FALSE);
+
+ // Simple condition with InitialValue set to false.
+ auto onBatteryFalsePredicate = config.add_predicate();
+ onBatteryFalsePredicate->set_id(StringToId("OnBatteryInitialFalse"));
+ SimplePredicate* simpleOnBatteryFalsePredicate =
+ onBatteryFalsePredicate->mutable_simple_predicate();
+ simpleOnBatteryFalsePredicate->set_start(batteryNoneAtomMatcher.id());
+ simpleOnBatteryFalsePredicate->set_stop(batteryUsbAtomMatcher.id());
+ simpleOnBatteryFalsePredicate->set_initial_value(SimplePredicate_InitialValue_FALSE);
+
+ // Combination condition with both simple condition InitialValues set to false.
+ auto screenOnFalseOnBatteryFalsePredicate = config.add_predicate();
+ screenOnFalseOnBatteryFalsePredicate->set_id(StringToId("ScreenOnFalseOnBatteryFalse"));
+ screenOnFalseOnBatteryFalsePredicate->mutable_combination()->set_operation(
+ LogicalOperation::AND);
+ addPredicateToPredicateCombination(*screenOnFalsePredicate,
+ screenOnFalseOnBatteryFalsePredicate);
+ addPredicateToPredicateCombination(*onBatteryFalsePredicate,
+ screenOnFalseOnBatteryFalsePredicate);
+
+ // Combination condition with one simple condition InitialValue set to unknown and one set to
+ // false.
+ auto screenOnUnknownOnBatteryFalsePredicate = config.add_predicate();
+ screenOnUnknownOnBatteryFalsePredicate->set_id(StringToId("ScreenOnUnknowneOnBatteryFalse"));
+ screenOnUnknownOnBatteryFalsePredicate->mutable_combination()->set_operation(
+ LogicalOperation::AND);
+ addPredicateToPredicateCombination(screenOnUnknownPredicate,
+ screenOnUnknownOnBatteryFalsePredicate);
+ addPredicateToPredicateCombination(*onBatteryFalsePredicate,
+ screenOnUnknownOnBatteryFalsePredicate);
+
+ // Simple condition metric with initial value false.
+ ValueMetric* metric1 = config.add_value_metric();
+ metric1->set_id(StringToId("ValueSubsystemSleepWhileScreenOnInitialFalse"));
+ metric1->set_what(pulledAtomMatcher.id());
+ *metric1->mutable_value_field() =
+ CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
+ metric1->set_bucket(FIVE_MINUTES);
+ metric1->set_condition(screenOnFalsePredicate->id());
+
+ // Simple condition metric with initial value unknown.
+ ValueMetric* metric2 = config.add_value_metric();
+ metric2->set_id(StringToId("ValueSubsystemSleepWhileScreenOnInitialUnknown"));
+ metric2->set_what(pulledAtomMatcher.id());
+ *metric2->mutable_value_field() =
+ CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
+ metric2->set_bucket(FIVE_MINUTES);
+ metric2->set_condition(screenOnUnknownPredicate.id());
+
+ // Combination condition metric with initial values false and false.
+ ValueMetric* metric3 = config.add_value_metric();
+ metric3->set_id(StringToId("ValueSubsystemSleepWhileScreenOnFalseDeviceUnpluggedFalse"));
+ metric3->set_what(pulledAtomMatcher.id());
+ *metric3->mutable_value_field() =
+ CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
+ metric3->set_bucket(FIVE_MINUTES);
+ metric3->set_condition(screenOnFalseOnBatteryFalsePredicate->id());
+
+ // Combination condition metric with initial values unknown and false.
+ ValueMetric* metric4 = config.add_value_metric();
+ metric4->set_id(StringToId("ValueSubsystemSleepWhileScreenOnUnknownDeviceUnpluggedFalse"));
+ metric4->set_what(pulledAtomMatcher.id());
+ *metric4->mutable_value_field() =
+ CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
+ metric4->set_bucket(FIVE_MINUTES);
+ metric4->set_condition(screenOnUnknownOnBatteryFalsePredicate->id());
+
+ return config;
+}
+} // anonymous namespace
+
+TEST(MetricsManagerTest, TestInitialConditions) {
+ sp<UidMap> uidMap = new UidMap();
+ sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+ sp<AlarmMonitor> anomalyAlarmMonitor;
+ sp<AlarmMonitor> periodicAlarmMonitor;
+ StatsdConfig config = buildConfigWithDifferentPredicates();
+ set<int> allTagIds;
+ vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers;
+ unordered_map<int64_t, int> atomMatchingTrackerMap;
+ vector<sp<ConditionTracker>> allConditionTrackers;
+ unordered_map<int64_t, int> conditionTrackerMap;
+ vector<sp<MetricProducer>> allMetricProducers;
+ unordered_map<int64_t, int> metricProducerMap;
+ std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
+ std::vector<sp<AlarmTracker>> allAlarmTrackers;
+ unordered_map<int, std::vector<int>> conditionToMetricMap;
+ unordered_map<int, std::vector<int>> trackerToMetricMap;
+ unordered_map<int, std::vector<int>> trackerToConditionMap;
+ unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
+ unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
+ unordered_map<int64_t, int> alertTrackerMap;
+ vector<int> metricsWithActivation;
+ map<int64_t, uint64_t> stateProtoHashes;
+ std::set<int64_t> noReportMetricIds;
+
+ EXPECT_TRUE(initStatsdConfig(
+ kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
+ timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, atomMatchingTrackerMap,
+ allConditionTrackers, conditionTrackerMap, allMetricProducers, metricProducerMap,
+ allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap, trackerToMetricMap,
+ trackerToConditionMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation,
+ stateProtoHashes, noReportMetricIds));
+ ASSERT_EQ(4u, allMetricProducers.size());
+ ASSERT_EQ(5u, allConditionTrackers.size());
+
+ ConditionKey queryKey;
+ vector<ConditionState> conditionCache(5, ConditionState::kNotEvaluated);
+
+ allConditionTrackers[3]->isConditionMet(queryKey, allConditionTrackers, false, conditionCache);
+ allConditionTrackers[4]->isConditionMet(queryKey, allConditionTrackers, false, conditionCache);
+ EXPECT_EQ(ConditionState::kUnknown, conditionCache[0]);
+ EXPECT_EQ(ConditionState::kFalse, conditionCache[1]);
+ EXPECT_EQ(ConditionState::kFalse, conditionCache[2]);
+ EXPECT_EQ(ConditionState::kFalse, conditionCache[3]);
+ EXPECT_EQ(ConditionState::kUnknown, conditionCache[4]);
+
+ EXPECT_EQ(ConditionState::kFalse, allMetricProducers[0]->mCondition);
+ EXPECT_EQ(ConditionState::kUnknown, allMetricProducers[1]->mCondition);
+ EXPECT_EQ(ConditionState::kFalse, allMetricProducers[2]->mCondition);
+ EXPECT_EQ(ConditionState::kUnknown, allMetricProducers[3]->mCondition);
+}
+
+TEST(MetricsManagerTest, TestGoodConfig) {
+ sp<UidMap> uidMap = new UidMap();
+ sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+ sp<AlarmMonitor> anomalyAlarmMonitor;
+ sp<AlarmMonitor> periodicAlarmMonitor;
+ StatsdConfig config = buildGoodConfig();
+ set<int> allTagIds;
+ vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers;
+ unordered_map<int64_t, int> atomMatchingTrackerMap;
+ vector<sp<ConditionTracker>> allConditionTrackers;
+ unordered_map<int64_t, int> conditionTrackerMap;
+ vector<sp<MetricProducer>> allMetricProducers;
+ unordered_map<int64_t, int> metricProducerMap;
+ std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
+ std::vector<sp<AlarmTracker>> allAlarmTrackers;
+ unordered_map<int, std::vector<int>> conditionToMetricMap;
+ unordered_map<int, std::vector<int>> trackerToMetricMap;
+ unordered_map<int, std::vector<int>> trackerToConditionMap;
+ unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
+ unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
+ unordered_map<int64_t, int> alertTrackerMap;
+ vector<int> metricsWithActivation;
+ map<int64_t, uint64_t> stateProtoHashes;
+ std::set<int64_t> noReportMetricIds;
+
+ EXPECT_TRUE(initStatsdConfig(
+ kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
+ timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, atomMatchingTrackerMap,
+ allConditionTrackers, conditionTrackerMap, allMetricProducers, metricProducerMap,
+ allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap, trackerToMetricMap,
+ trackerToConditionMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation,
+ stateProtoHashes, noReportMetricIds));
+ ASSERT_EQ(1u, allMetricProducers.size());
+ EXPECT_THAT(metricProducerMap, UnorderedElementsAre(Pair(config.count_metric(0).id(), 0)));
+ ASSERT_EQ(1u, allAnomalyTrackers.size());
+ ASSERT_EQ(1u, noReportMetricIds.size());
+ ASSERT_EQ(1u, alertTrackerMap.size());
+ EXPECT_NE(alertTrackerMap.find(kAlertId), alertTrackerMap.end());
+ EXPECT_EQ(alertTrackerMap.find(kAlertId)->second, 0);
+}
+
+TEST(MetricsManagerTest, TestDimensionMetricsWithMultiTags) {
+ sp<UidMap> uidMap = new UidMap();
+ sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+ sp<AlarmMonitor> anomalyAlarmMonitor;
+ sp<AlarmMonitor> periodicAlarmMonitor;
+ StatsdConfig config = buildDimensionMetricsWithMultiTags();
+ set<int> allTagIds;
+ vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers;
+ unordered_map<int64_t, int> atomMatchingTrackerMap;
+ vector<sp<ConditionTracker>> allConditionTrackers;
+ unordered_map<int64_t, int> conditionTrackerMap;
+ vector<sp<MetricProducer>> allMetricProducers;
+ unordered_map<int64_t, int> metricProducerMap;
+ std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
+ std::vector<sp<AlarmTracker>> allAlarmTrackers;
+ unordered_map<int, std::vector<int>> conditionToMetricMap;
+ unordered_map<int, std::vector<int>> trackerToMetricMap;
+ unordered_map<int, std::vector<int>> trackerToConditionMap;
+ unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
+ unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
+ unordered_map<int64_t, int> alertTrackerMap;
+ vector<int> metricsWithActivation;
+ map<int64_t, uint64_t> stateProtoHashes;
+ std::set<int64_t> noReportMetricIds;
+
+ EXPECT_FALSE(initStatsdConfig(
+ kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
+ timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, atomMatchingTrackerMap,
+ allConditionTrackers, conditionTrackerMap, allMetricProducers, metricProducerMap,
+ allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap, trackerToMetricMap,
+ trackerToConditionMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation,
+ stateProtoHashes, noReportMetricIds));
+}
+
+TEST(MetricsManagerTest, TestCircleLogMatcherDependency) {
+ sp<UidMap> uidMap = new UidMap();
+ sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+ sp<AlarmMonitor> anomalyAlarmMonitor;
+ sp<AlarmMonitor> periodicAlarmMonitor;
+ StatsdConfig config = buildCircleMatchers();
+ set<int> allTagIds;
+ vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers;
+ unordered_map<int64_t, int> atomMatchingTrackerMap;
+ vector<sp<ConditionTracker>> allConditionTrackers;
+ unordered_map<int64_t, int> conditionTrackerMap;
+ vector<sp<MetricProducer>> allMetricProducers;
+ unordered_map<int64_t, int> metricProducerMap;
+ std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
+ std::vector<sp<AlarmTracker>> allAlarmTrackers;
+ unordered_map<int, std::vector<int>> conditionToMetricMap;
+ unordered_map<int, std::vector<int>> trackerToMetricMap;
+ unordered_map<int, std::vector<int>> trackerToConditionMap;
+ unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
+ unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
+ unordered_map<int64_t, int> alertTrackerMap;
+ vector<int> metricsWithActivation;
+ map<int64_t, uint64_t> stateProtoHashes;
+ std::set<int64_t> noReportMetricIds;
+
+ EXPECT_FALSE(initStatsdConfig(
+ kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
+ timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, atomMatchingTrackerMap,
+ allConditionTrackers, conditionTrackerMap, allMetricProducers, metricProducerMap,
+ allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap, trackerToMetricMap,
+ trackerToConditionMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation,
+ stateProtoHashes, noReportMetricIds));
+}
+
+TEST(MetricsManagerTest, TestMissingMatchers) {
+ sp<UidMap> uidMap = new UidMap();
+ sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+ sp<AlarmMonitor> anomalyAlarmMonitor;
+ sp<AlarmMonitor> periodicAlarmMonitor;
+ StatsdConfig config = buildMissingMatchers();
+ set<int> allTagIds;
+ vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers;
+ unordered_map<int64_t, int> atomMatchingTrackerMap;
+ vector<sp<ConditionTracker>> allConditionTrackers;
+ unordered_map<int64_t, int> conditionTrackerMap;
+ vector<sp<MetricProducer>> allMetricProducers;
+ unordered_map<int64_t, int> metricProducerMap;
+ std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
+ std::vector<sp<AlarmTracker>> allAlarmTrackers;
+ unordered_map<int, std::vector<int>> conditionToMetricMap;
+ unordered_map<int, std::vector<int>> trackerToMetricMap;
+ unordered_map<int, std::vector<int>> trackerToConditionMap;
+ unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
+ unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
+ unordered_map<int64_t, int> alertTrackerMap;
+ vector<int> metricsWithActivation;
+ map<int64_t, uint64_t> stateProtoHashes;
+ std::set<int64_t> noReportMetricIds;
+ EXPECT_FALSE(initStatsdConfig(
+ kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
+ timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, atomMatchingTrackerMap,
+ allConditionTrackers, conditionTrackerMap, allMetricProducers, metricProducerMap,
+ allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap, trackerToMetricMap,
+ trackerToConditionMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation,
+ stateProtoHashes, noReportMetricIds));
+}
+
+TEST(MetricsManagerTest, TestMissingPredicate) {
+ sp<UidMap> uidMap = new UidMap();
+ sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+ sp<AlarmMonitor> anomalyAlarmMonitor;
+ sp<AlarmMonitor> periodicAlarmMonitor;
+ StatsdConfig config = buildMissingPredicate();
+ set<int> allTagIds;
+ vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers;
+ unordered_map<int64_t, int> atomMatchingTrackerMap;
+ vector<sp<ConditionTracker>> allConditionTrackers;
+ unordered_map<int64_t, int> conditionTrackerMap;
+ vector<sp<MetricProducer>> allMetricProducers;
+ unordered_map<int64_t, int> metricProducerMap;
+ std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
+ std::vector<sp<AlarmTracker>> allAlarmTrackers;
+ unordered_map<int, std::vector<int>> conditionToMetricMap;
+ unordered_map<int, std::vector<int>> trackerToMetricMap;
+ unordered_map<int, std::vector<int>> trackerToConditionMap;
+ unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
+ unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
+ unordered_map<int64_t, int> alertTrackerMap;
+ vector<int> metricsWithActivation;
+ map<int64_t, uint64_t> stateProtoHashes;
+ std::set<int64_t> noReportMetricIds;
+ EXPECT_FALSE(initStatsdConfig(
+ kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
+ timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, atomMatchingTrackerMap,
+ allConditionTrackers, conditionTrackerMap, allMetricProducers, metricProducerMap,
+ allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap, trackerToMetricMap,
+ trackerToConditionMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation,
+ stateProtoHashes, noReportMetricIds));
+}
+
+TEST(MetricsManagerTest, TestCirclePredicateDependency) {
+ sp<UidMap> uidMap = new UidMap();
+ sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+ sp<AlarmMonitor> anomalyAlarmMonitor;
+ sp<AlarmMonitor> periodicAlarmMonitor;
+ StatsdConfig config = buildCirclePredicates();
+ set<int> allTagIds;
+ vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers;
+ unordered_map<int64_t, int> atomMatchingTrackerMap;
+ vector<sp<ConditionTracker>> allConditionTrackers;
+ unordered_map<int64_t, int> conditionTrackerMap;
+ vector<sp<MetricProducer>> allMetricProducers;
+ unordered_map<int64_t, int> metricProducerMap;
+ std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
+ std::vector<sp<AlarmTracker>> allAlarmTrackers;
+ unordered_map<int, std::vector<int>> conditionToMetricMap;
+ unordered_map<int, std::vector<int>> trackerToMetricMap;
+ unordered_map<int, std::vector<int>> trackerToConditionMap;
+ unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
+ unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
+ unordered_map<int64_t, int> alertTrackerMap;
+ vector<int> metricsWithActivation;
+ map<int64_t, uint64_t> stateProtoHashes;
+ std::set<int64_t> noReportMetricIds;
+
+ EXPECT_FALSE(initStatsdConfig(
+ kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
+ timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, atomMatchingTrackerMap,
+ allConditionTrackers, conditionTrackerMap, allMetricProducers, metricProducerMap,
+ allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap, trackerToMetricMap,
+ trackerToConditionMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation,
+ stateProtoHashes, noReportMetricIds));
+}
+
+TEST(MetricsManagerTest, testAlertWithUnknownMetric) {
+ sp<UidMap> uidMap = new UidMap();
+ sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+ sp<AlarmMonitor> anomalyAlarmMonitor;
+ sp<AlarmMonitor> periodicAlarmMonitor;
+ StatsdConfig config = buildAlertWithUnknownMetric();
+ set<int> allTagIds;
+ vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers;
+ unordered_map<int64_t, int> atomMatchingTrackerMap;
+ vector<sp<ConditionTracker>> allConditionTrackers;
+ unordered_map<int64_t, int> conditionTrackerMap;
+ vector<sp<MetricProducer>> allMetricProducers;
+ unordered_map<int64_t, int> metricProducerMap;
+ std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
+ std::vector<sp<AlarmTracker>> allAlarmTrackers;
+ unordered_map<int, std::vector<int>> conditionToMetricMap;
+ unordered_map<int, std::vector<int>> trackerToMetricMap;
+ unordered_map<int, std::vector<int>> trackerToConditionMap;
+ unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
+ unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
+ unordered_map<int64_t, int> alertTrackerMap;
+ vector<int> metricsWithActivation;
+ map<int64_t, uint64_t> stateProtoHashes;
+ std::set<int64_t> noReportMetricIds;
+
+ EXPECT_FALSE(initStatsdConfig(
+ kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
+ timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, atomMatchingTrackerMap,
+ allConditionTrackers, conditionTrackerMap, allMetricProducers, metricProducerMap,
+ allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap, trackerToMetricMap,
+ trackerToConditionMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation,
+ stateProtoHashes, noReportMetricIds));
+}
+
+TEST(MetricsManagerTest, TestCreateAtomMatchingTrackerInvalidMatcher) {
+ sp<UidMap> uidMap = new UidMap();
+ AtomMatcher matcher;
+ // Matcher has no contents_case (simple/combination), so it is invalid.
+ matcher.set_id(21);
+ EXPECT_EQ(createAtomMatchingTracker(matcher, 0, uidMap), nullptr);
+}
+
+TEST(MetricsManagerTest, TestCreateAtomMatchingTrackerSimple) {
+ int index = 1;
+ int64_t id = 123;
+ sp<UidMap> uidMap = new UidMap();
+ AtomMatcher matcher;
+ matcher.set_id(id);
+ SimpleAtomMatcher* simpleAtomMatcher = matcher.mutable_simple_atom_matcher();
+ simpleAtomMatcher->set_atom_id(util::SCREEN_STATE_CHANGED);
+ simpleAtomMatcher->add_field_value_matcher()->set_field(
+ 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
+ simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
+ android::view::DisplayStateEnum::DISPLAY_STATE_ON);
+
+ sp<AtomMatchingTracker> tracker = createAtomMatchingTracker(matcher, index, uidMap);
+ EXPECT_NE(tracker, nullptr);
+
+ EXPECT_TRUE(tracker->mInitialized);
+ EXPECT_EQ(tracker->getId(), id);
+ EXPECT_EQ(tracker->mIndex, index);
+ const set<int>& atomIds = tracker->getAtomIds();
+ ASSERT_EQ(atomIds.size(), 1);
+ EXPECT_EQ(atomIds.count(util::SCREEN_STATE_CHANGED), 1);
+}
+
+TEST(MetricsManagerTest, TestCreateAtomMatchingTrackerCombination) {
+ int index = 1;
+ int64_t id = 123;
+ sp<UidMap> uidMap = new UidMap();
+ AtomMatcher matcher;
+ matcher.set_id(id);
+ AtomMatcher_Combination* combination = matcher.mutable_combination();
+ combination->set_operation(LogicalOperation::OR);
+ combination->add_matcher(123);
+ combination->add_matcher(223);
+
+ sp<AtomMatchingTracker> tracker = createAtomMatchingTracker(matcher, index, uidMap);
+ EXPECT_NE(tracker, nullptr);
+
+ // Combination matchers need to be initialized first.
+ EXPECT_FALSE(tracker->mInitialized);
+ EXPECT_EQ(tracker->getId(), id);
+ EXPECT_EQ(tracker->mIndex, index);
+ const set<int>& atomIds = tracker->getAtomIds();
+ ASSERT_EQ(atomIds.size(), 0);
+}
+
+TEST(MetricsManagerTest, TestCreateConditionTrackerInvalid) {
+ const ConfigKey key(123, 456);
+ // Predicate has no contents_case (simple/combination), so it is invalid.
+ Predicate predicate;
+ predicate.set_id(21);
+ unordered_map<int64_t, int> atomTrackerMap;
+ EXPECT_EQ(createConditionTracker(key, predicate, 0, atomTrackerMap), nullptr);
+}
+
+TEST(MetricsManagerTest, TestCreateConditionTrackerSimple) {
+ int index = 1;
+ int64_t id = 987;
+ const ConfigKey key(123, 456);
+
+ int startMatcherIndex = 2, stopMatcherIndex = 0, stopAllMatcherIndex = 1;
+ int64_t startMatcherId = 246, stopMatcherId = 153, stopAllMatcherId = 975;
+
+ Predicate predicate;
+ predicate.set_id(id);
+ SimplePredicate* simplePredicate = predicate.mutable_simple_predicate();
+ simplePredicate->set_start(startMatcherId);
+ simplePredicate->set_stop(stopMatcherId);
+ simplePredicate->set_stop_all(stopAllMatcherId);
+
+ unordered_map<int64_t, int> atomTrackerMap;
+ atomTrackerMap[startMatcherId] = startMatcherIndex;
+ atomTrackerMap[stopMatcherId] = stopMatcherIndex;
+ atomTrackerMap[stopAllMatcherId] = stopAllMatcherIndex;
+
+ sp<ConditionTracker> tracker = createConditionTracker(key, predicate, index, atomTrackerMap);
+ EXPECT_EQ(tracker->getConditionId(), id);
+ EXPECT_EQ(tracker->isSliced(), false);
+ EXPECT_TRUE(tracker->IsSimpleCondition());
+ const set<int>& interestedMatchers = tracker->getAtomMatchingTrackerIndex();
+ ASSERT_EQ(interestedMatchers.size(), 3);
+ ASSERT_EQ(interestedMatchers.count(startMatcherIndex), 1);
+ ASSERT_EQ(interestedMatchers.count(stopMatcherIndex), 1);
+ ASSERT_EQ(interestedMatchers.count(stopAllMatcherIndex), 1);
+}
+
+TEST(MetricsManagerTest, TestCreateConditionTrackerCombination) {
+ int index = 1;
+ int64_t id = 987;
+ const ConfigKey key(123, 456);
+
+ Predicate predicate;
+ predicate.set_id(id);
+ Predicate_Combination* combinationPredicate = predicate.mutable_combination();
+ combinationPredicate->set_operation(LogicalOperation::AND);
+ combinationPredicate->add_predicate(888);
+ combinationPredicate->add_predicate(777);
+
+ // Combination conditions must be initialized to set most state.
+ unordered_map<int64_t, int> atomTrackerMap;
+ sp<ConditionTracker> tracker = createConditionTracker(key, predicate, index, atomTrackerMap);
+ EXPECT_EQ(tracker->getConditionId(), id);
+ EXPECT_FALSE(tracker->IsSimpleCondition());
+}
+
+} // namespace statsd
+} // namespace os
+} // namespace android
+
+#else
+GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
diff --git a/cmds/statsd/tests/shell/ShellSubscriber_test.cpp b/cmds/statsd/tests/shell/ShellSubscriber_test.cpp
index e384b6ac7c84..4fa4135e983f 100644
--- a/cmds/statsd/tests/shell/ShellSubscriber_test.cpp
+++ b/cmds/statsd/tests/shell/ShellSubscriber_test.cpp
@@ -190,9 +190,9 @@ TEST(ShellSubscriberTest, testPulledSubscription) {
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
const vector<int32_t> uids = {AID_SYSTEM};
- EXPECT_CALL(*pullerManager, Pull(10016, uids, _, _, _))
+ EXPECT_CALL(*pullerManager, Pull(10016, uids, _, _))
.WillRepeatedly(Invoke([](int tagId, const vector<int32_t>&, const int64_t,
- vector<std::shared_ptr<LogEvent>>* data, bool) {
+ vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
data->push_back(makeCpuActiveTimeAtom(/*uid=*/kUid1, /*timeMillis=*/kCpuTime1));
data->push_back(makeCpuActiveTimeAtom(/*uid=*/kUid2, /*timeMillis=*/kCpuTime2));
diff --git a/cmds/statsd/tests/statsd_test_util.cpp b/cmds/statsd/tests/statsd_test_util.cpp
index cee83725d075..1761d5d9e1fa 100644
--- a/cmds/statsd/tests/statsd_test_util.cpp
+++ b/cmds/statsd/tests/statsd_test_util.cpp
@@ -15,6 +15,8 @@
#include "statsd_test_util.h"
#include <aidl/android/util/StatsEventParcel.h>
+
+#include "matchers/SimpleAtomMatchingTracker.h"
#include "stats_event.h"
using aidl::android::util::StatsEventParcel;
@@ -996,6 +998,20 @@ int64_t StringToId(const string& str) {
return static_cast<int64_t>(std::hash<std::string>()(str));
}
+sp<EventMatcherWizard> createEventMatcherWizard(
+ int tagId, int matcherIndex, const vector<FieldValueMatcher>& fieldValueMatchers) {
+ sp<UidMap> uidMap = new UidMap();
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ for (const FieldValueMatcher& fvm : fieldValueMatchers) {
+ *atomMatcher.add_field_value_matcher() = fvm;
+ }
+ uint64_t matcherHash = 0x12345678;
+ int64_t matcherId = 678;
+ return new EventMatcherWizard({new SimpleAtomMatchingTracker(
+ matcherId, matcherIndex, matcherHash, atomMatcher, uidMap)});
+}
+
void ValidateWakelockAttributionUidAndTagDimension(const DimensionsValue& value, const int atomId,
const int uid, const string& tag) {
EXPECT_EQ(value.field(), atomId);
diff --git a/cmds/statsd/tests/statsd_test_util.h b/cmds/statsd/tests/statsd_test_util.h
index 3dcf4ecce054..1220019e2353 100644
--- a/cmds/statsd/tests/statsd_test_util.h
+++ b/cmds/statsd/tests/statsd_test_util.h
@@ -25,6 +25,7 @@
#include "src/StatsLogProcessor.h"
#include "src/hash.h"
#include "src/logd/LogEvent.h"
+#include "src/matchers/EventMatcherWizard.h"
#include "src/packages/UidMap.h"
#include "src/stats_log_util.h"
#include "stats_event.h"
@@ -335,6 +336,9 @@ void sortLogEventsByTimestamp(std::vector<std::unique_ptr<LogEvent>> *events);
int64_t StringToId(const string& str);
+sp<EventMatcherWizard> createEventMatcherWizard(
+ int tagId, int matcherIndex, const std::vector<FieldValueMatcher>& fieldValueMatchers = {});
+
void ValidateWakelockAttributionUidAndTagDimension(const DimensionsValue& value, const int atomId,
const int uid, const string& tag);
void ValidateUidDimension(const DimensionsValue& value, int node_idx, int atomId, int uid);
diff --git a/cmds/uinput/Android.bp b/cmds/uinput/Android.bp
new file mode 100644
index 000000000000..0d7fed2a15c7
--- /dev/null
+++ b/cmds/uinput/Android.bp
@@ -0,0 +1,18 @@
+// Copyright 2020 The Android Open Source Project
+//
+
+java_binary {
+ name: "uinput",
+ wrapper: "uinput",
+ srcs: ["**/*.java",
+ ":uinputcommand_aidl"
+ ],
+ required: ["libuinputcommand_jni"],
+}
+
+filegroup {
+ name: "uinputcommand_aidl",
+ srcs: [
+ "src/com/android/commands/uinput/InputAbsInfo.aidl",
+ ],
+} \ No newline at end of file
diff --git a/cmds/uinput/MODULE_LICENSE_APACHE2 b/cmds/uinput/MODULE_LICENSE_APACHE2
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/cmds/uinput/MODULE_LICENSE_APACHE2
diff --git a/cmds/uinput/NOTICE b/cmds/uinput/NOTICE
new file mode 100644
index 000000000000..c5b1efa7aac7
--- /dev/null
+++ b/cmds/uinput/NOTICE
@@ -0,0 +1,190 @@
+
+ Copyright (c) 2005-2008, The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
diff --git a/cmds/uinput/README.md b/cmds/uinput/README.md
new file mode 100644
index 000000000000..47e1dad9ccd6
--- /dev/null
+++ b/cmds/uinput/README.md
@@ -0,0 +1,166 @@
+# Usage
+## Two options to use the uinput command:
+### 1. Interactive through stdin:
+type `uinput -` into the terminal, then type/paste commands to send to the binary.
+Use Ctrl+D to signal end of stream to the binary (EOF).
+
+This mode can be also used from an app to send uinput events.
+For an example, see the cts test case at: [InputTestCase.java][2]
+
+When using another program to control uinput in interactive mode, registering a
+new input device (for example, a bluetooth joystick) should be the first step.
+After the device is added, you need to wait for the _onInputDeviceAdded_
+(see [InputDeviceListener][1]) notification before issuing commands
+to the device.
+Failure to do so will cause missed events and inconsistent behavior.
+
+### 2. Using a file as an input:
+type `uinput <filename>`, and the file will be used an an input to the binary.
+You must add a sufficient delay after a "register" command to ensure device
+is ready. The interactive mode is the recommended method of communicating
+with the uinput binary.
+
+All of the input commands should be in pseudo-JSON format as documented below.
+See examples [here][3].
+
+The file can have multiple commands one after the other (which is not strictly
+legal JSON format, as this would imply multiple root elements).
+
+## Command description
+
+1. `register`
+Register a new uinput device
+
+| Field | Type | Description |
+|:-------------:|:-------------:|:-------------------------- |
+| id | integer | Device id |
+| command | string | Must be set to "register" |
+| name | string | Device name |
+| vid | 16-bit integer| Vendor id |
+| pid | 16-bit integer| Product id |
+| bus | string | Bus that device should use |
+| configuration | int array | uinput device configuration|
+| ff_effects_max| integer | ff_effects_max value |
+| abs_info | array | ABS axes information |
+
+Device ID is used for matching the subsequent commands to a specific device
+to avoid ambiguity when multiple devices are registered.
+
+Device bus is used to determine how the uinput device is connected to the host.
+The options are "usb" and "bluetooth".
+
+Device configuration is used to configure uinput device. "type" field provides the UI_SET_*
+control code, and data is a vector of control values to be sent to uinput device, depends on
+the control code.
+
+| Field | Type | Description |
+|:-------------:|:-------------:|:-------------------------- |
+| type | integer | UI_SET_ control type |
+| data | int array | control values |
+
+Device ff_effects_max must be provided if FFBIT is set.
+
+Device abs_info fields are provided to set the device axes information. It is an array of below
+objects:
+| Field | Type | Description |
+|:-------------:|:-------------:|:-------------------------- |
+| code | integer | Axis code |
+| info | object | ABS information object |
+
+ABS information object is defined as below:
+| Field | Type | Description |
+|:-------------:|:-------------:|:-------------------------- |
+| value | integer | Latest reported value |
+| minimum | integer | Minimum value for the axis |
+| maximum | integer | Maximum value for the axis |
+| fuzz | integer | fuzz value for noise filter|
+| flat | integer | values to be discarded |
+| resolution | integer | resolution of axis |
+
+See [struct input_absinfo][4]) definitions.
+
+Example:
+```json
+
+{
+ "id": 1,
+ "command": "register",
+ "name": "Keyboard (Test)",
+ "vid": 0x18d2,
+ "pid": 0x2c42,
+ "bus": "usb",
+ "configuration":[
+ {"type":100, "data":[1, 21]}, // UI_SET_EVBIT : EV_KEY and EV_FF
+ {"type":101, "data":[11, 2, 3, 4]}, // UI_SET_KEYBIT : KEY_0 KEY_1 KEY_2 KEY_3
+ {"type":107, "data":[80]} // UI_SET_FFBIT : FF_RUMBLE
+ ],
+ "ff_effects_max" : 1,
+ "abs_info": [
+ {"code":1, "info": {"value":20, "minimum":-255,
+ "maximum":255, "fuzz":0, "flat":0, "resolution":1}
+ },
+ {"code":8, "info": {"value":-50, "minimum":-255,
+ "maximum":255, "fuzz":0, "flat":0, "resolution":1}
+ }
+ ]
+}
+
+```
+2. `delay`
+Add a delay to command processing
+
+| Field | Type | Description |
+|:-------------:|:-------------:|:-------------------------- |
+| id | integer | Device id |
+| command | string | Must be set to "delay" |
+| duration | integer | Delay in milliseconds |
+
+Example:
+```json
+{
+ "id": 1,
+ "command": "delay",
+ "duration": 10
+}
+```
+
+3. `inject`
+Send an array of uinput event packets [type, code, value] to the uinput device
+
+| Field | Type | Description |
+|:-------------:|:-------------:|:-------------------------- |
+| id | integer | Device id |
+| command | string | Must be set to "inject" |
+| events | integer array | events to inject |
+
+The "events" parameter is an array of integers, encapsulates evdev input_event type, code and value,
+see the example below.
+
+Example:
+```json
+{
+ "id": 1,
+ "command": "inject",
+ "events": [0x01, 0xb, 0x1, // EV_KEY, KEY_0, DOWN
+ 0x00, 0x00, 0x00, // EV_SYN, SYN_REPORT, 0
+ 0x01, 0x0b, 0x00, // EV_KEY, KEY_0, UP
+ 0x00, 0x00, 0x00, // EV_SYN, SYN_REPORT, 0
+ 0x01, 0x2, 0x1, // EV_KEY, KEY_1, DOWN
+ 0x00, 0x00, 0x01, // EV_SYN, SYN_REPORT, 0
+ 0x01, 0x02, 0x00, // EV_KEY, KEY_1, UP
+ 0x00, 0x00, 0x01 // EV_SYN, SYN_REPORT, 0
+ ]
+}
+```
+
+### Notes
+1. As soon as EOF is reached (either in interactive mode, or in file mode),
+the device that was created will be unregistered. There is no
+explicit command for unregistering a device.
+2. The `getevent` utility can used to print out the key events
+for debugging purposes.
+
+[1]: https://developer.android.com/reference/android/hardware/input/InputManager.InputDeviceListener.html
+[2]: ../../../../cts/tests/tests/hardware/src/android/hardware/input/cts/tests/InputTestCase.java
+[3]: ../../../../cts/tests/tests/hardware/res/raw/
+[4]: ../../../../bionic/libc/kernel/uapi/linux/input.h
diff --git a/cmds/uinput/jni/Android.bp b/cmds/uinput/jni/Android.bp
new file mode 100644
index 000000000000..199bbbd35274
--- /dev/null
+++ b/cmds/uinput/jni/Android.bp
@@ -0,0 +1,23 @@
+cc_library_shared {
+ name: "libuinputcommand_jni",
+
+ srcs: [
+ "com_android_commands_uinput_Device.cpp",
+ ":uinputcommand_aidl",
+ ],
+
+ shared_libs: [
+ "libandroid",
+ "libandroid_runtime_lazy",
+ "libbase",
+ "libbinder",
+ "liblog",
+ "libnativehelper",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ ],
+}
diff --git a/cmds/uinput/jni/com_android_commands_uinput_Device.cpp b/cmds/uinput/jni/com_android_commands_uinput_Device.cpp
new file mode 100644
index 000000000000..06fa2aac2c7e
--- /dev/null
+++ b/cmds/uinput/jni/com_android_commands_uinput_Device.cpp
@@ -0,0 +1,351 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "UinputCommandDevice"
+
+#include <linux/uinput.h>
+
+#include <fcntl.h>
+#include <inttypes.h>
+#include <time.h>
+#include <unistd.h>
+#include <algorithm>
+#include <array>
+#include <cstdio>
+#include <cstring>
+#include <iterator>
+#include <memory>
+#include <vector>
+
+#include <android/looper.h>
+#include <android_os_Parcel.h>
+#include <jni.h>
+#include <log/log.h>
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedLocalRef.h>
+#include <nativehelper/ScopedPrimitiveArray.h>
+#include <nativehelper/ScopedUtfChars.h>
+
+#include <android-base/stringprintf.h>
+
+#include "com_android_commands_uinput_Device.h"
+
+namespace android {
+namespace uinput {
+
+using src::com::android::commands::uinput::InputAbsInfo;
+
+static constexpr const char* UINPUT_PATH = "/dev/uinput";
+
+static struct {
+ jmethodID onDeviceConfigure;
+ jmethodID onDeviceVibrating;
+ jmethodID onDeviceError;
+} gDeviceCallbackClassInfo;
+
+static void checkAndClearException(JNIEnv* env, const char* methodName) {
+ if (env->ExceptionCheck()) {
+ ALOGE("An exception was thrown by callback '%s'.", methodName);
+ env->ExceptionClear();
+ }
+}
+
+DeviceCallback::DeviceCallback(JNIEnv* env, jobject callback)
+ : mCallbackObject(env->NewGlobalRef(callback)) {
+ env->GetJavaVM(&mJavaVM);
+}
+
+DeviceCallback::~DeviceCallback() {
+ JNIEnv* env = getJNIEnv();
+ env->DeleteGlobalRef(mCallbackObject);
+}
+
+void DeviceCallback::onDeviceError() {
+ JNIEnv* env = getJNIEnv();
+ env->CallVoidMethod(mCallbackObject, gDeviceCallbackClassInfo.onDeviceError);
+ checkAndClearException(env, "onDeviceError");
+}
+
+void DeviceCallback::onDeviceConfigure(int handle) {
+ JNIEnv* env = getJNIEnv();
+ env->CallVoidMethod(mCallbackObject, gDeviceCallbackClassInfo.onDeviceConfigure, handle);
+ checkAndClearException(env, "onDeviceConfigure");
+}
+
+void DeviceCallback::onDeviceVibrating(int value) {
+ JNIEnv* env = getJNIEnv();
+ env->CallVoidMethod(mCallbackObject, gDeviceCallbackClassInfo.onDeviceVibrating, value);
+ checkAndClearException(env, "onDeviceVibrating");
+}
+
+JNIEnv* DeviceCallback::getJNIEnv() {
+ JNIEnv* env;
+ mJavaVM->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
+ return env;
+}
+
+std::unique_ptr<UinputDevice> UinputDevice::open(int32_t id, const char* name, int32_t vid,
+ int32_t pid, uint16_t bus, uint32_t ffEffectsMax,
+ std::unique_ptr<DeviceCallback> callback) {
+ android::base::unique_fd fd(::open(UINPUT_PATH, O_RDWR | O_NONBLOCK | O_CLOEXEC));
+ if (!fd.ok()) {
+ ALOGE("Failed to open uinput: %s", strerror(errno));
+ return nullptr;
+ }
+
+ int32_t version;
+ ::ioctl(fd, UI_GET_VERSION, &version);
+ if (version < 5) {
+ ALOGE("Kernel version %d older than 5 is not supported", version);
+ return nullptr;
+ }
+
+ struct uinput_setup setupDescriptor;
+ memset(&setupDescriptor, 0, sizeof(setupDescriptor));
+ strlcpy(setupDescriptor.name, name, UINPUT_MAX_NAME_SIZE);
+ setupDescriptor.id.version = 1;
+ setupDescriptor.id.bustype = bus;
+ setupDescriptor.id.vendor = vid;
+ setupDescriptor.id.product = pid;
+ setupDescriptor.ff_effects_max = ffEffectsMax;
+
+ // Request device configuration.
+ callback->onDeviceConfigure(fd.get());
+
+ // register the input device
+ if (::ioctl(fd, UI_DEV_SETUP, &setupDescriptor)) {
+ ALOGE("UI_DEV_SETUP ioctl failed on fd %d: %s.", fd.get(), strerror(errno));
+ return nullptr;
+ }
+
+ if (::ioctl(fd, UI_DEV_CREATE) != 0) {
+ ALOGE("Unable to create uinput device: %s.", strerror(errno));
+ return nullptr;
+ }
+
+ // using 'new' to access non-public constructor
+ return std::unique_ptr<UinputDevice>(new UinputDevice(id, std::move(fd), std::move(callback)));
+}
+
+UinputDevice::UinputDevice(int32_t id, android::base::unique_fd fd,
+ std::unique_ptr<DeviceCallback> callback)
+ : mId(id), mFd(std::move(fd)), mDeviceCallback(std::move(callback)) {
+ ALooper* aLooper = ALooper_forThread();
+ if (aLooper == nullptr) {
+ ALOGE("Could not get ALooper, ALooper_forThread returned NULL");
+ aLooper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
+ }
+ ALooper_addFd(
+ aLooper, mFd, 0, ALOOPER_EVENT_INPUT,
+ [](int, int events, void* data) {
+ UinputDevice* d = reinterpret_cast<UinputDevice*>(data);
+ return d->handleEvents(events);
+ },
+ reinterpret_cast<void*>(this));
+ ALOGI("uinput device %d created: version = %d, fd = %d", mId, UINPUT_VERSION, mFd.get());
+}
+
+UinputDevice::~UinputDevice() {
+ ::ioctl(mFd, UI_DEV_DESTROY);
+}
+
+void UinputDevice::injectEvent(uint16_t type, uint16_t code, int32_t value) {
+ struct input_event event = {};
+ event.type = type;
+ event.code = code;
+ event.value = value;
+ timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ TIMESPEC_TO_TIMEVAL(&event.time, &ts);
+
+ if (::write(mFd, &event, sizeof(input_event)) < 0) {
+ ALOGE("Could not write event %" PRIu16 " %" PRIu16 " with value %" PRId32 " : %s", type,
+ code, value, strerror(errno));
+ }
+}
+
+int UinputDevice::handleEvents(int events) {
+ if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
+ ALOGE("uinput node was closed or an error occurred. events=0x%x", events);
+ mDeviceCallback->onDeviceError();
+ return 0;
+ }
+ struct input_event ev;
+ ssize_t ret = ::read(mFd, &ev, sizeof(ev));
+ if (ret < 0) {
+ ALOGE("Failed to read from uinput node: %s", strerror(errno));
+ mDeviceCallback->onDeviceError();
+ return 0;
+ }
+
+ switch (ev.type) {
+ case EV_UINPUT: {
+ if (ev.code == UI_FF_UPLOAD) {
+ struct uinput_ff_upload ff_upload;
+ ff_upload.request_id = ev.value;
+ ::ioctl(mFd, UI_BEGIN_FF_UPLOAD, &ff_upload);
+ ff_upload.retval = 0;
+ ::ioctl(mFd, UI_END_FF_UPLOAD, &ff_upload);
+ } else if (ev.code == UI_FF_ERASE) {
+ struct uinput_ff_erase ff_erase;
+ ff_erase.request_id = ev.value;
+ ::ioctl(mFd, UI_BEGIN_FF_ERASE, &ff_erase);
+ ff_erase.retval = 0;
+ ::ioctl(mFd, UI_END_FF_ERASE, &ff_erase);
+ }
+ break;
+ }
+ case EV_FF: {
+ ALOGI("EV_FF effect = %d value = %d", ev.code, ev.value);
+ mDeviceCallback->onDeviceVibrating(ev.value);
+ break;
+ }
+ default: {
+ ALOGI("Unhandled event type: %" PRIu32, ev.type);
+ break;
+ }
+ }
+
+ return 1;
+}
+
+} // namespace uinput
+
+std::vector<int32_t> toVector(JNIEnv* env, jintArray javaArray) {
+ std::vector<int32_t> data;
+ if (javaArray == nullptr) {
+ return data;
+ }
+
+ ScopedIntArrayRO scopedArray(env, javaArray);
+ size_t size = scopedArray.size();
+ data.reserve(size);
+ for (size_t i = 0; i < size; i++) {
+ data.push_back(static_cast<int32_t>(scopedArray[i]));
+ }
+ return data;
+}
+
+static jlong openUinputDevice(JNIEnv* env, jclass /* clazz */, jstring rawName, jint id, jint vid,
+ jint pid, jint bus, jint ffEffectsMax, jobject callback) {
+ ScopedUtfChars name(env, rawName);
+ if (name.c_str() == nullptr) {
+ return 0;
+ }
+
+ std::unique_ptr<uinput::DeviceCallback> cb =
+ std::make_unique<uinput::DeviceCallback>(env, callback);
+
+ std::unique_ptr<uinput::UinputDevice> d =
+ uinput::UinputDevice::open(id, name.c_str(), vid, pid, bus, ffEffectsMax,
+ std::move(cb));
+ return reinterpret_cast<jlong>(d.release());
+}
+
+static void closeUinputDevice(JNIEnv* /* env */, jclass /* clazz */, jlong ptr) {
+ uinput::UinputDevice* d = reinterpret_cast<uinput::UinputDevice*>(ptr);
+ if (d != nullptr) {
+ delete d;
+ }
+}
+
+static void injectEvent(JNIEnv* /* env */, jclass /* clazz */, jlong ptr, jint type, jint code,
+ jint value) {
+ uinput::UinputDevice* d = reinterpret_cast<uinput::UinputDevice*>(ptr);
+ if (d != nullptr) {
+ d->injectEvent(static_cast<uint16_t>(type), static_cast<uint16_t>(code),
+ static_cast<int32_t>(value));
+ } else {
+ ALOGE("Could not inject event, Device* is null!");
+ }
+}
+
+static void configure(JNIEnv* env, jclass /* clazz */, jint handle, jint code,
+ jintArray rawConfigs) {
+ std::vector<int32_t> configs = toVector(env, rawConfigs);
+ // Configure uinput device, with user specified code and value.
+ for (auto& config : configs) {
+ ::ioctl(static_cast<int>(handle), _IOW(UINPUT_IOCTL_BASE, code, int), config);
+ }
+}
+
+static void setAbsInfo(JNIEnv* env, jclass /* clazz */, jint handle, jint axisCode,
+ jobject infoObj) {
+ Parcel* parcel = parcelForJavaObject(env, infoObj);
+ uinput::InputAbsInfo info;
+
+ info.readFromParcel(parcel);
+
+ struct uinput_abs_setup absSetup;
+ absSetup.code = axisCode;
+ absSetup.absinfo.maximum = info.maximum;
+ absSetup.absinfo.minimum = info.minimum;
+ absSetup.absinfo.value = info.value;
+ absSetup.absinfo.fuzz = info.fuzz;
+ absSetup.absinfo.flat = info.flat;
+ absSetup.absinfo.resolution = info.resolution;
+
+ ::ioctl(static_cast<int>(handle), UI_ABS_SETUP, &absSetup);
+}
+
+static JNINativeMethod sMethods[] = {
+ {"nativeOpenUinputDevice",
+ "(Ljava/lang/String;IIIII"
+ "Lcom/android/commands/uinput/Device$DeviceCallback;)J",
+ reinterpret_cast<void*>(openUinputDevice)},
+ {"nativeInjectEvent", "(JIII)V", reinterpret_cast<void*>(injectEvent)},
+ {"nativeConfigure", "(II[I)V", reinterpret_cast<void*>(configure)},
+ {"nativeSetAbsInfo", "(IILandroid/os/Parcel;)V", reinterpret_cast<void*>(setAbsInfo)},
+ {"nativeCloseUinputDevice", "(J)V", reinterpret_cast<void*>(closeUinputDevice)},
+};
+
+int register_com_android_commands_uinput_Device(JNIEnv* env) {
+ jclass clazz = env->FindClass("com/android/commands/uinput/Device$DeviceCallback");
+ if (clazz == nullptr) {
+ ALOGE("Unable to find class 'DeviceCallback'");
+ return JNI_ERR;
+ }
+
+ uinput::gDeviceCallbackClassInfo.onDeviceConfigure =
+ env->GetMethodID(clazz, "onDeviceConfigure", "(I)V");
+ uinput::gDeviceCallbackClassInfo.onDeviceVibrating =
+ env->GetMethodID(clazz, "onDeviceVibrating", "(I)V");
+ uinput::gDeviceCallbackClassInfo.onDeviceError =
+ env->GetMethodID(clazz, "onDeviceError", "()V");
+ if (uinput::gDeviceCallbackClassInfo.onDeviceConfigure == nullptr ||
+ uinput::gDeviceCallbackClassInfo.onDeviceError == nullptr ||
+ uinput::gDeviceCallbackClassInfo.onDeviceVibrating == nullptr) {
+ ALOGE("Unable to obtain onDeviceConfigure or onDeviceError or onDeviceVibrating methods");
+ return JNI_ERR;
+ }
+ return jniRegisterNativeMethods(env, "com/android/commands/uinput/Device", sMethods,
+ NELEM(sMethods));
+}
+
+} // namespace android
+
+jint JNI_OnLoad(JavaVM* jvm, void*) {
+ JNIEnv* env = nullptr;
+ if (jvm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6)) {
+ return JNI_ERR;
+ }
+
+ if (android::register_com_android_commands_uinput_Device(env) < 0) {
+ return JNI_ERR;
+ }
+
+ return JNI_VERSION_1_6;
+}
diff --git a/cmds/uinput/jni/com_android_commands_uinput_Device.h b/cmds/uinput/jni/com_android_commands_uinput_Device.h
new file mode 100644
index 000000000000..5a9a06cfb32e
--- /dev/null
+++ b/cmds/uinput/jni/com_android_commands_uinput_Device.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <memory>
+#include <vector>
+
+#include <jni.h>
+#include <linux/input.h>
+
+#include <android-base/unique_fd.h>
+#include "src/com/android/commands/uinput/InputAbsInfo.h"
+
+namespace android {
+namespace uinput {
+
+class DeviceCallback {
+public:
+ DeviceCallback(JNIEnv* env, jobject callback);
+ ~DeviceCallback();
+
+ void onDeviceOpen();
+ void onDeviceGetReport(uint32_t requestId, uint8_t reportId);
+ void onDeviceOutput(const std::vector<uint8_t>& data);
+ void onDeviceConfigure(int handle);
+ void onDeviceVibrating(int value);
+ void onDeviceError();
+
+private:
+ JNIEnv* getJNIEnv();
+ jobject mCallbackObject;
+ JavaVM* mJavaVM;
+};
+
+class UinputDevice {
+public:
+ static std::unique_ptr<UinputDevice> open(int32_t id, const char* name, int32_t vid,
+ int32_t pid, uint16_t bus, uint32_t ff_effects_max,
+ std::unique_ptr<DeviceCallback> callback);
+
+ virtual ~UinputDevice();
+
+ void injectEvent(uint16_t type, uint16_t code, int32_t value);
+ int handleEvents(int events);
+
+private:
+ UinputDevice(int32_t id, android::base::unique_fd fd, std::unique_ptr<DeviceCallback> callback);
+
+ int32_t mId;
+ android::base::unique_fd mFd;
+ std::unique_ptr<DeviceCallback> mDeviceCallback;
+};
+
+} // namespace uinput
+} // namespace android
diff --git a/cmds/uinput/src/com/android/commands/uinput/Device.java b/cmds/uinput/src/com/android/commands/uinput/Device.java
new file mode 100644
index 000000000000..62bee7b964bd
--- /dev/null
+++ b/cmds/uinput/src/com/android/commands/uinput/Device.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.commands.uinput;
+
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Parcel;
+import android.os.SystemClock;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.internal.os.SomeArgs;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import src.com.android.commands.uinput.InputAbsInfo;
+
+/**
+ * Device class defines uinput device interfaces of device operations, for device open, close,
+ * configuration, events injection.
+ */
+public class Device {
+ private static final String TAG = "UinputDevice";
+
+ private static final int MSG_OPEN_UINPUT_DEVICE = 1;
+ private static final int MSG_CLOSE_UINPUT_DEVICE = 2;
+ private static final int MSG_INJECT_EVENT = 3;
+
+ private final int mId;
+ private final HandlerThread mThread;
+ private final DeviceHandler mHandler;
+ // mConfiguration is sparse array of ioctl code and array of values.
+ private final SparseArray<int[]> mConfiguration;
+ private final SparseArray<InputAbsInfo> mAbsInfo;
+ private final OutputStream mOutputStream;
+ private final Object mCond = new Object();
+ private long mTimeToSend;
+
+ static {
+ System.loadLibrary("uinputcommand_jni");
+ }
+
+ private static native long nativeOpenUinputDevice(String name, int id, int vid, int pid,
+ int bus, int ffEffectsMax, DeviceCallback callback);
+ private static native void nativeCloseUinputDevice(long ptr);
+ private static native void nativeInjectEvent(long ptr, int type, int code, int value);
+ private static native void nativeConfigure(int handle, int code, int[] configs);
+ private static native void nativeSetAbsInfo(int handle, int axisCode, Parcel axisParcel);
+
+ public Device(int id, String name, int vid, int pid, int bus,
+ SparseArray<int[]> configuration, int ffEffectsMax,
+ SparseArray<InputAbsInfo> absInfo) {
+ mId = id;
+ mThread = new HandlerThread("UinputDeviceHandler");
+ mThread.start();
+ mHandler = new DeviceHandler(mThread.getLooper());
+ mConfiguration = configuration;
+ mAbsInfo = absInfo;
+ mOutputStream = System.out;
+ SomeArgs args = SomeArgs.obtain();
+ args.argi1 = id;
+ args.argi2 = vid;
+ args.argi3 = pid;
+ args.argi4 = bus;
+ args.argi5 = ffEffectsMax;
+ if (name != null) {
+ args.arg1 = name;
+ } else {
+ args.arg1 = id + ":" + vid + ":" + pid;
+ }
+
+ mHandler.obtainMessage(MSG_OPEN_UINPUT_DEVICE, args).sendToTarget();
+ mTimeToSend = SystemClock.uptimeMillis();
+ }
+
+ /**
+ * Inject uinput events to device
+ *
+ * @param events Array of raw uinput events.
+ */
+ public void injectEvent(int[] events) {
+ // if two messages are sent at identical time, they will be processed in order received
+ Message msg = mHandler.obtainMessage(MSG_INJECT_EVENT, events);
+ mHandler.sendMessageAtTime(msg, mTimeToSend);
+ }
+
+ /**
+ * Impose a delay to the device for execution.
+ *
+ * @param delay Time to delay in unit of milliseconds.
+ */
+ public void addDelay(int delay) {
+ mTimeToSend = Math.max(SystemClock.uptimeMillis(), mTimeToSend) + delay;
+ }
+
+ /**
+ * Close an uinput device.
+ *
+ */
+ public void close() {
+ Message msg = mHandler.obtainMessage(MSG_CLOSE_UINPUT_DEVICE);
+ mHandler.sendMessageAtTime(msg, Math.max(SystemClock.uptimeMillis(), mTimeToSend) + 1);
+ try {
+ synchronized (mCond) {
+ mCond.wait();
+ }
+ } catch (InterruptedException ignore) {
+ }
+ }
+
+ private class DeviceHandler extends Handler {
+ private long mPtr;
+ private int mBarrierToken;
+
+ DeviceHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_OPEN_UINPUT_DEVICE:
+ SomeArgs args = (SomeArgs) msg.obj;
+ mPtr = nativeOpenUinputDevice((String) args.arg1, args.argi1, args.argi2,
+ args.argi3, args.argi4, args.argi5,
+ new DeviceCallback());
+ break;
+ case MSG_INJECT_EVENT:
+ if (mPtr != 0) {
+ int[] events = (int[]) msg.obj;
+ for (int pos = 0; pos + 2 < events.length; pos += 3) {
+ nativeInjectEvent(mPtr, events[pos], events[pos + 1], events[pos + 2]);
+ }
+ }
+ break;
+ case MSG_CLOSE_UINPUT_DEVICE:
+ if (mPtr != 0) {
+ nativeCloseUinputDevice(mPtr);
+ getLooper().quitSafely();
+ mPtr = 0;
+ } else {
+ Log.e(TAG, "Tried to close already closed device.");
+ }
+ Log.i(TAG, "Device closed.");
+ synchronized (mCond) {
+ mCond.notify();
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown device message");
+ }
+ }
+
+ public void pauseEvents() {
+ mBarrierToken = getLooper().myQueue().postSyncBarrier();
+ }
+
+ public void resumeEvents() {
+ getLooper().myQueue().removeSyncBarrier(mBarrierToken);
+ mBarrierToken = 0;
+ }
+ }
+
+ private class DeviceCallback {
+ public void onDeviceOpen() {
+ mHandler.resumeEvents();
+ }
+
+ public void onDeviceConfigure(int handle) {
+ for (int i = 0; i < mConfiguration.size(); i++) {
+ int key = mConfiguration.keyAt(i);
+ int[] data = mConfiguration.get(key);
+ nativeConfigure(handle, key, data);
+ }
+
+ if (mAbsInfo != null) {
+ for (int i = 0; i < mAbsInfo.size(); i++) {
+ int key = mAbsInfo.keyAt(i);
+ InputAbsInfo info = mAbsInfo.get(key);
+ Parcel parcel = Parcel.obtain();
+ info.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ nativeSetAbsInfo(handle, key, parcel);
+ }
+ }
+ }
+
+ public void onDeviceVibrating(int value) {
+ JSONObject json = new JSONObject();
+ try {
+ json.put("reason", "vibrating");
+ json.put("id", mId);
+ json.put("status", value);
+ } catch (JSONException e) {
+ throw new RuntimeException("Could not create JSON object ", e);
+ }
+ try {
+ mOutputStream.write(json.toString().getBytes());
+ mOutputStream.flush();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void onDeviceError() {
+ Log.e(TAG, "Device error occurred, closing /dev/uinput");
+ Message msg = mHandler.obtainMessage(MSG_CLOSE_UINPUT_DEVICE);
+ msg.setAsynchronous(true);
+ msg.sendToTarget();
+ }
+ }
+}
diff --git a/cmds/uinput/src/com/android/commands/uinput/Event.java b/cmds/uinput/src/com/android/commands/uinput/Event.java
new file mode 100644
index 000000000000..c4ba05054eda
--- /dev/null
+++ b/cmds/uinput/src/com/android/commands/uinput/Event.java
@@ -0,0 +1,454 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.commands.uinput;
+
+import android.util.JsonReader;
+import android.util.JsonToken;
+import android.util.Log;
+import android.util.SparseArray;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import src.com.android.commands.uinput.InputAbsInfo;
+
+/**
+ * An event is a JSON file defined action event to instruct uinput to perform a command like
+ * device registration or uinput events injection.
+ */
+public class Event {
+ private static final String TAG = "UinputEvent";
+
+ public static final String COMMAND_REGISTER = "register";
+ public static final String COMMAND_DELAY = "delay";
+ public static final String COMMAND_INJECT = "inject";
+ private static final int ABS_CNT = 64;
+
+ // These constants come from "include/uapi/linux/input.h" in the kernel
+ enum Bus {
+ USB(0x03), BLUETOOTH(0x05);
+ private final int mValue;
+
+ Bus(int value) {
+ mValue = value;
+ }
+
+ int getValue() {
+ return mValue;
+ }
+ }
+
+ private int mId;
+ private String mCommand;
+ private String mName;
+ private int mVid;
+ private int mPid;
+ private Bus mBus;
+ private int[] mInjections;
+ private SparseArray<int[]> mConfiguration;
+ private int mDuration;
+ private int mFfEffectsMax = 0;
+ private SparseArray<InputAbsInfo> mAbsInfo;
+
+ public int getId() {
+ return mId;
+ }
+
+ public String getCommand() {
+ return mCommand;
+ }
+
+ public String getName() {
+ return mName;
+ }
+
+ public int getVendorId() {
+ return mVid;
+ }
+
+ public int getProductId() {
+ return mPid;
+ }
+
+ public int getBus() {
+ return mBus.getValue();
+ }
+
+ public int[] getInjections() {
+ return mInjections;
+ }
+
+ public SparseArray<int[]> getConfiguration() {
+ return mConfiguration;
+ }
+
+ public int getDuration() {
+ return mDuration;
+ }
+
+ public int getFfEffectsMax() {
+ return mFfEffectsMax;
+ }
+
+ public SparseArray<InputAbsInfo> getAbsInfo() {
+ return mAbsInfo;
+ }
+
+ /**
+ * Convert an event to String.
+ */
+ public String toString() {
+ return "Event{id=" + mId
+ + ", command=" + mCommand
+ + ", name=" + mName
+ + ", vid=" + mVid
+ + ", pid=" + mPid
+ + ", bus=" + mBus
+ + ", events=" + Arrays.toString(mInjections)
+ + ", configuration=" + mConfiguration
+ + ", duration=" + mDuration
+ + ", ff_effects_max=" + mFfEffectsMax
+ + "}";
+ }
+
+ private static class Builder {
+ private Event mEvent;
+
+ Builder() {
+ mEvent = new Event();
+ }
+
+ public void setId(int id) {
+ mEvent.mId = id;
+ }
+
+ private void setCommand(String command) {
+ mEvent.mCommand = command;
+ }
+
+ public void setName(String name) {
+ mEvent.mName = name;
+ }
+
+ public void setInjections(int[] events) {
+ mEvent.mInjections = events;
+ }
+
+ public void setConfiguration(SparseArray<int[]> configuration) {
+ mEvent.mConfiguration = configuration;
+ }
+
+ public void setVid(int vid) {
+ mEvent.mVid = vid;
+ }
+
+ public void setPid(int pid) {
+ mEvent.mPid = pid;
+ }
+
+ public void setBus(Bus bus) {
+ mEvent.mBus = bus;
+ }
+
+ public void setDuration(int duration) {
+ mEvent.mDuration = duration;
+ }
+
+ public void setFfEffectsMax(int ffEffectsMax) {
+ mEvent.mFfEffectsMax = ffEffectsMax;
+ }
+
+ public void setAbsInfo(SparseArray<InputAbsInfo> absInfo) {
+ mEvent.mAbsInfo = absInfo;
+ }
+
+ public Event build() {
+ if (mEvent.mId == -1) {
+ throw new IllegalStateException("No event id");
+ } else if (mEvent.mCommand == null) {
+ throw new IllegalStateException("Event does not contain a command");
+ }
+ if (COMMAND_REGISTER.equals(mEvent.mCommand)) {
+ if (mEvent.mConfiguration == null) {
+ throw new IllegalStateException(
+ "Device registration is missing configuration");
+ }
+ } else if (COMMAND_DELAY.equals(mEvent.mCommand)) {
+ if (mEvent.mDuration <= 0) {
+ throw new IllegalStateException("Delay has missing or invalid duration");
+ }
+ } else if (COMMAND_INJECT.equals(mEvent.mCommand)) {
+ if (mEvent.mInjections == null) {
+ throw new IllegalStateException("Inject command is missing injection data");
+ }
+ } else {
+ throw new IllegalStateException("Unknown command " + mEvent.mCommand);
+ }
+ return mEvent;
+ }
+ }
+
+ /**
+ * A class that parses the JSON event format from an input stream to build device events.
+ */
+ public static class Reader {
+ private JsonReader mReader;
+
+ public Reader(InputStreamReader in) {
+ mReader = new JsonReader(in);
+ mReader.setLenient(true);
+ }
+
+ /**
+ * Get next event entry from JSON file reader.
+ */
+ public Event getNextEvent() throws IOException {
+ Event e = null;
+ while (e == null && mReader.peek() != JsonToken.END_DOCUMENT) {
+ Event.Builder eb = new Event.Builder();
+ try {
+ mReader.beginObject();
+ while (mReader.hasNext()) {
+ String name = mReader.nextName();
+ switch (name) {
+ case "id":
+ eb.setId(readInt());
+ break;
+ case "command":
+ eb.setCommand(mReader.nextString());
+ break;
+ case "name":
+ eb.setName(mReader.nextString());
+ break;
+ case "vid":
+ eb.setVid(readInt());
+ break;
+ case "pid":
+ eb.setPid(readInt());
+ break;
+ case "bus":
+ eb.setBus(readBus());
+ break;
+ case "events":
+ int[] injections = readIntList().stream()
+ .mapToInt(Integer::intValue).toArray();
+ eb.setInjections(injections);
+ break;
+ case "configuration":
+ eb.setConfiguration(readConfiguration());
+ break;
+ case "ff_effects_max":
+ eb.setFfEffectsMax(readInt());
+ break;
+ case "abs_info":
+ eb.setAbsInfo(readAbsInfoArray());
+ break;
+ case "duration":
+ eb.setDuration(readInt());
+ break;
+ default:
+ mReader.skipValue();
+ }
+ }
+ mReader.endObject();
+ } catch (IllegalStateException ex) {
+ error("Error reading in object, ignoring.", ex);
+ consumeRemainingElements();
+ mReader.endObject();
+ continue;
+ }
+ e = eb.build();
+ }
+
+ return e;
+ }
+
+ private ArrayList<Integer> readIntList() throws IOException {
+ ArrayList<Integer> data = new ArrayList<Integer>();
+ try {
+ mReader.beginArray();
+ while (mReader.hasNext()) {
+ data.add(Integer.decode(mReader.nextString()));
+ }
+ mReader.endArray();
+ } catch (IllegalStateException | NumberFormatException e) {
+ consumeRemainingElements();
+ mReader.endArray();
+ throw new IllegalStateException("Encountered malformed data.", e);
+ }
+ return data;
+ }
+
+ private byte[] readData() throws IOException {
+ ArrayList<Integer> data = readIntList();
+ byte[] rawData = new byte[data.size()];
+ for (int i = 0; i < data.size(); i++) {
+ int d = data.get(i);
+ if ((d & 0xFF) != d) {
+ throw new IllegalStateException("Invalid data, all values must be byte-sized");
+ }
+ rawData[i] = (byte) d;
+ }
+ return rawData;
+ }
+
+ private int readInt() throws IOException {
+ String val = mReader.nextString();
+ return Integer.decode(val);
+ }
+
+ private Bus readBus() throws IOException {
+ String val = mReader.nextString();
+ return Bus.valueOf(val.toUpperCase());
+ }
+
+ private SparseArray<int[]> readConfiguration()
+ throws IllegalStateException, IOException {
+ SparseArray<int[]> configuration = new SparseArray<>();
+ try {
+ mReader.beginArray();
+ while (mReader.hasNext()) {
+ int type = 0;
+ int[] data = null;
+ mReader.beginObject();
+ while (mReader.hasNext()) {
+ String name = mReader.nextName();
+ switch (name) {
+ case "type":
+ type = readInt();
+ break;
+ case "data":
+ data = readIntList().stream()
+ .mapToInt(Integer::intValue).toArray();
+ break;
+ default:
+ consumeRemainingElements();
+ mReader.endObject();
+ throw new IllegalStateException(
+ "Invalid key in device configuration: " + name);
+ }
+ }
+ mReader.endObject();
+ if (data != null) {
+ configuration.put(type, data);
+ }
+ }
+ mReader.endArray();
+ } catch (IllegalStateException | NumberFormatException e) {
+ consumeRemainingElements();
+ mReader.endArray();
+ throw new IllegalStateException("Encountered malformed data.", e);
+ }
+ return configuration;
+ }
+
+ private InputAbsInfo readAbsInfo() throws IllegalStateException, IOException {
+ InputAbsInfo absInfo = new InputAbsInfo();
+ try {
+ mReader.beginObject();
+ while (mReader.hasNext()) {
+ String name = mReader.nextName();
+ switch (name) {
+ case "value":
+ absInfo.value = readInt();
+ break;
+ case "minimum":
+ absInfo.minimum = readInt();
+ break;
+ case "maximum":
+ absInfo.maximum = readInt();
+ break;
+ case "fuzz":
+ absInfo.fuzz = readInt();
+ break;
+ case "flat":
+ absInfo.flat = readInt();
+ break;
+ case "resolution":
+ absInfo.resolution = readInt();
+ break;
+ default:
+ consumeRemainingElements();
+ mReader.endObject();
+ throw new IllegalStateException("Invalid key in abs info: " + name);
+ }
+ }
+ mReader.endObject();
+ } catch (IllegalStateException | NumberFormatException e) {
+ consumeRemainingElements();
+ mReader.endObject();
+ throw new IllegalStateException("Encountered malformed data.", e);
+ }
+ return absInfo;
+ }
+
+ private SparseArray<InputAbsInfo> readAbsInfoArray()
+ throws IllegalStateException, IOException {
+ SparseArray<InputAbsInfo> infoArray = new SparseArray<>();
+ try {
+ mReader.beginArray();
+ while (mReader.hasNext()) {
+ int type = 0;
+ InputAbsInfo absInfo = null;
+ mReader.beginObject();
+ while (mReader.hasNext()) {
+ String name = mReader.nextName();
+ switch (name) {
+ case "code":
+ type = readInt();
+ break;
+ case "info":
+ absInfo = readAbsInfo();
+ break;
+ default:
+ consumeRemainingElements();
+ mReader.endObject();
+ throw new IllegalStateException("Invalid key in abs info array: "
+ + name);
+ }
+ }
+ mReader.endObject();
+ if (absInfo != null) {
+ infoArray.put(type, absInfo);
+ }
+ }
+ mReader.endArray();
+ } catch (IllegalStateException | NumberFormatException e) {
+ consumeRemainingElements();
+ mReader.endArray();
+ throw new IllegalStateException("Encountered malformed data.", e);
+ }
+ return infoArray;
+ }
+
+ private void consumeRemainingElements() throws IOException {
+ while (mReader.hasNext()) {
+ mReader.skipValue();
+ }
+ }
+ }
+
+ private static void error(String msg, Exception e) {
+ System.out.println(msg);
+ Log.e(TAG, msg);
+ if (e != null) {
+ Log.e(TAG, Log.getStackTraceString(e));
+ }
+ }
+}
diff --git a/cmds/uinput/src/com/android/commands/uinput/InputAbsInfo.aidl b/cmds/uinput/src/com/android/commands/uinput/InputAbsInfo.aidl
new file mode 100644
index 000000000000..88c57f2c8965
--- /dev/null
+++ b/cmds/uinput/src/com/android/commands/uinput/InputAbsInfo.aidl
@@ -0,0 +1,26 @@
+/*
+**
+** Copyright 2020, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+package src.com.android.commands.uinput;
+
+parcelable InputAbsInfo {
+ int value;
+ int minimum;
+ int maximum;
+ int fuzz;
+ int flat;
+ int resolution;
+}
diff --git a/cmds/uinput/src/com/android/commands/uinput/Uinput.java b/cmds/uinput/src/com/android/commands/uinput/Uinput.java
new file mode 100644
index 000000000000..f7601a2f7c07
--- /dev/null
+++ b/cmds/uinput/src/com/android/commands/uinput/Uinput.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.commands.uinput;
+
+import android.util.Log;
+import android.util.SparseArray;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+
+/**
+ * Uinput class encapsulates execution of "uinput" command. It parses the provided input stream
+ * parameters as JSON file format, extract event entries and perform commands of event entries.
+ * Uinput device will be created when performing registration command and used to inject events.
+ */
+public class Uinput {
+ private static final String TAG = "UINPUT";
+
+ private final Event.Reader mReader;
+ private final SparseArray<Device> mDevices;
+
+ private static void usage() {
+ error("Usage: uinput [FILE]");
+ }
+
+ /**
+ * Commandline "uinput" binary main entry
+ */
+ public static void main(String[] args) {
+ if (args.length != 1) {
+ usage();
+ System.exit(1);
+ }
+
+ InputStream stream = null;
+ try {
+ if (args[0].equals("-")) {
+ stream = System.in;
+ } else {
+ File f = new File(args[0]);
+ stream = new FileInputStream(f);
+ }
+ (new Uinput(stream)).run();
+ } catch (Exception e) {
+ error("Uinput injection failed.", e);
+ System.exit(1);
+ } finally {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+
+ private Uinput(InputStream in) {
+ mDevices = new SparseArray<Device>();
+ try {
+ mReader = new Event.Reader(new InputStreamReader(in, "UTF-8"));
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private void run() {
+ try {
+ Event e = null;
+ while ((e = mReader.getNextEvent()) != null) {
+ process(e);
+ }
+ } catch (IOException ex) {
+ error("Error reading in events.", ex);
+ }
+
+ for (int i = 0; i < mDevices.size(); i++) {
+ mDevices.valueAt(i).close();
+ }
+ }
+
+ private void process(Event e) {
+ final int index = mDevices.indexOfKey(e.getId());
+ if (index >= 0) {
+ Device d = mDevices.valueAt(index);
+ if (Event.COMMAND_DELAY.equals(e.getCommand())) {
+ d.addDelay(e.getDuration());
+ } else if (Event.COMMAND_INJECT.equals(e.getCommand())) {
+ d.injectEvent(e.getInjections());
+ } else {
+ if (Event.COMMAND_REGISTER.equals(e.getCommand())) {
+ error("Device id=" + e.getId() + " is already registered. Ignoring event.");
+ } else {
+ error("Unknown command \"" + e.getCommand() + "\". Ignoring event.");
+ }
+ }
+ } else if (Event.COMMAND_REGISTER.equals(e.getCommand())) {
+ registerDevice(e);
+ } else {
+ Log.e(TAG, "Unknown device id specified. Ignoring event.");
+ }
+ }
+
+ private void registerDevice(Event e) {
+ if (!Event.COMMAND_REGISTER.equals(e.getCommand())) {
+ throw new IllegalStateException(
+ "Tried to send command \"" + e.getCommand() + "\" to an unregistered device!");
+ }
+ int id = e.getId();
+ Device d = new Device(id, e.getName(), e.getVendorId(), e.getProductId(), e.getBus(),
+ e.getConfiguration(), e.getFfEffectsMax(), e.getAbsInfo());
+ mDevices.append(id, d);
+ }
+
+ private static void error(String msg) {
+ error(msg, null);
+ }
+
+ private static void error(String msg, Exception e) {
+ Log.e(TAG, msg);
+ if (e != null) {
+ Log.e(TAG, Log.getStackTraceString(e));
+ }
+ }
+}
diff --git a/cmds/uinput/uinput b/cmds/uinput/uinput
new file mode 100755
index 000000000000..ab2770ee2043
--- /dev/null
+++ b/cmds/uinput/uinput
@@ -0,0 +1,9 @@
+#!/system/bin/sh
+
+# Preload the native portion libuinputcommand_jni.so to bypass the dependency
+# checks in the Java classloader, which prohibit dependencies that aren't
+# listed in system/core/rootdir/etc/public.libraries.android.txt.
+export LD_PRELOAD=libuinputcommand_jni.so
+
+export CLASSPATH=/system/framework/uinput.jar
+exec app_process /system/bin com.android.commands.uinput.Uinput "$@"