Merge "Resolve TODOs in MediaRouter2"
diff --git a/apex/statsd/aidl/Android.bp b/apex/statsd/aidl/Android.bp
index 7c93bc7..f7a8176 100644
--- a/apex/statsd/aidl/Android.bp
+++ b/apex/statsd/aidl/Android.bp
@@ -34,7 +34,7 @@
enabled: false, // the platform uses statsd_java_aidl
},
cpp: {
- enabled: true,
+ enabled: false,
},
ndk: {
enabled: true,
diff --git a/api/current.txt b/api/current.txt
index 140b6ae..34d0218 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2871,7 +2871,9 @@
method protected void onServiceConnected();
method public void onSystemActionsChanged();
method public final boolean performGlobalAction(int);
+ method public void setGestureDetectionPassthroughRegion(int, @NonNull android.graphics.Region);
method public final void setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo);
+ method public void setTouchExplorationPassthroughRegion(int, @NonNull android.graphics.Region);
method public boolean takeScreenshot(int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.accessibilityservice.AccessibilityService.ScreenshotResult>);
field public static final int GESTURE_2_FINGER_DOUBLE_TAP = 20; // 0x14
field public static final int GESTURE_2_FINGER_DOUBLE_TAP_AND_HOLD = 40; // 0x28
@@ -10827,6 +10829,8 @@
field public static final int FLAG_ACTIVITY_NO_USER_ACTION = 262144; // 0x40000
field public static final int FLAG_ACTIVITY_PREVIOUS_IS_TOP = 16777216; // 0x1000000
field public static final int FLAG_ACTIVITY_REORDER_TO_FRONT = 131072; // 0x20000
+ field public static final int FLAG_ACTIVITY_REQUIRE_DEFAULT = 512; // 0x200
+ field public static final int FLAG_ACTIVITY_REQUIRE_NON_BROWSER = 1024; // 0x400
field public static final int FLAG_ACTIVITY_RESET_TASK_IF_NEEDED = 2097152; // 0x200000
field public static final int FLAG_ACTIVITY_RETAIN_IN_RECENTS = 8192; // 0x2000
field public static final int FLAG_ACTIVITY_SINGLE_TOP = 536870912; // 0x20000000
@@ -25092,7 +25096,7 @@
public final class MediaCas implements java.lang.AutoCloseable {
ctor public MediaCas(int) throws android.media.MediaCasException.UnsupportedCasException;
- ctor public MediaCas(int, @Nullable String, int) throws android.media.MediaCasException.UnsupportedCasException;
+ ctor public MediaCas(@NonNull android.content.Context, int, @Nullable String, int) throws android.media.MediaCasException.UnsupportedCasException;
method public void close();
method public static android.media.MediaCas.PluginDescriptor[] enumeratePlugins();
method protected void finalize();
diff --git a/api/system-current.txt b/api/system-current.txt
index 79a9b21..f974380 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4247,15 +4247,15 @@
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioAttributes.Builder setSystemUsage(int);
}
- public final class AudioDevice implements android.os.Parcelable {
- ctor public AudioDevice(@NonNull android.media.AudioDeviceInfo);
- ctor public AudioDevice(int, int, @NonNull String);
+ public final class AudioDeviceAttributes implements android.os.Parcelable {
+ ctor public AudioDeviceAttributes(@NonNull android.media.AudioDeviceInfo);
+ ctor public AudioDeviceAttributes(int, int, @NonNull String);
method public int describeContents();
method @NonNull public String getAddress();
method public int getRole();
method public int getType();
method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.media.AudioDevice> CREATOR;
+ field @NonNull public static final android.os.Parcelable.Creator<android.media.AudioDeviceAttributes> CREATOR;
field public static final int ROLE_INPUT = 1; // 0x1
field public static final int ROLE_OUTPUT = 2; // 0x2
}
@@ -4293,11 +4293,11 @@
method @IntRange(from=0) public int getAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo);
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static java.util.List<android.media.audiopolicy.AudioProductStrategy> getAudioProductStrategies();
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static java.util.List<android.media.audiopolicy.AudioVolumeGroup> getAudioVolumeGroups();
- method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public java.util.List<android.media.AudioDevice> getDevicesForAttributes(@NonNull android.media.AudioAttributes);
+ method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public java.util.List<android.media.AudioDeviceAttributes> getDevicesForAttributes(@NonNull android.media.AudioAttributes);
method @IntRange(from=0) public int getMaxAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo);
method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMaxVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMinVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
- method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioDevice getPreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy);
+ method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioDeviceAttributes getPreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy);
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int[] getSupportedSystemUsages();
method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
method public boolean isAudioServerRunning();
@@ -4312,7 +4312,7 @@
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo, @IntRange(from=0) int);
method public void setAudioServerStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.AudioServerStateCallback);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setFocusRequestResult(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy);
- method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setPreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy, @NonNull android.media.AudioDevice);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setPreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy, @NonNull android.media.AudioDeviceAttributes);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setSupportedSystemUsages(@NonNull int[]);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setVolumeIndexForAttributes(@NonNull android.media.AudioAttributes, int, int);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void unregisterAudioPolicy(@NonNull android.media.audiopolicy.AudioPolicy);
@@ -4332,7 +4332,7 @@
}
public static interface AudioManager.OnPreferredDeviceForStrategyChangedListener {
- method public void onPreferredDeviceForStrategyChanged(@NonNull android.media.audiopolicy.AudioProductStrategy, @Nullable android.media.AudioDevice);
+ method public void onPreferredDeviceForStrategyChanged(@NonNull android.media.audiopolicy.AudioProductStrategy, @Nullable android.media.AudioDeviceAttributes);
}
public abstract static class AudioManager.VolumeGroupCallback {
@@ -4412,7 +4412,7 @@
package android.media.audiofx {
public class AudioEffect {
- ctor @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public AudioEffect(@NonNull java.util.UUID, @NonNull android.media.AudioDevice);
+ ctor @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public AudioEffect(@NonNull java.util.UUID, @NonNull android.media.AudioDeviceAttributes);
}
}
@@ -4826,7 +4826,7 @@
method public int getAudioFilterCount();
method public int getDemuxCount();
method public int getFilterCapabilities();
- method @Nullable @Size(5) public int[] getLinkCapabilities();
+ method @NonNull @Size(5) public int[] getLinkCapabilities();
method public int getPcrFilterCount();
method public int getPesFilterCount();
method public int getPlaybackCount();
@@ -4842,7 +4842,7 @@
method public int addPid(int, int, @Nullable android.media.tv.tuner.filter.Filter);
method public void close();
method public int removePid(int, int, @Nullable android.media.tv.tuner.filter.Filter);
- method public int setKeyToken(@Nullable byte[]);
+ method public int setKeyToken(@NonNull byte[]);
field public static final int PID_TYPE_MMTP = 2; // 0x2
field public static final int PID_TYPE_T = 1; // 0x1
}
@@ -4879,10 +4879,11 @@
}
public class Tuner implements java.lang.AutoCloseable {
- ctor @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public Tuner(@NonNull android.content.Context, @NonNull String, int, @Nullable android.media.tv.tuner.Tuner.OnResourceLostListener);
+ ctor @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public Tuner(@NonNull android.content.Context, @Nullable String, int);
method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int cancelScanning();
method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int cancelTuning();
method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public void clearOnTuneEventListener();
+ method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public void clearResourceLostListener();
method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public void close();
method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int connectCiCam(int);
method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int disconnectCiCam();
@@ -4892,15 +4893,16 @@
method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.frontend.FrontendInfo getFrontendInfo();
method @Nullable public android.media.tv.tuner.frontend.FrontendStatus getFrontendStatus(@NonNull int[]);
method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_DESCRAMBLER) public android.media.tv.tuner.Descrambler openDescrambler();
- method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.dvr.DvrPlayback openDvrPlayback(long, @Nullable java.util.concurrent.Executor, @Nullable android.media.tv.tuner.dvr.OnPlaybackStatusChangedListener);
- method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.dvr.DvrRecorder openDvrRecorder(long, @Nullable java.util.concurrent.Executor, @Nullable android.media.tv.tuner.dvr.OnRecordStatusChangedListener);
+ method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.dvr.DvrPlayback openDvrPlayback(long, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.dvr.OnPlaybackStatusChangedListener);
+ method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.dvr.DvrRecorder openDvrRecorder(long, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.dvr.OnRecordStatusChangedListener);
method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.filter.Filter openFilter(int, int, long, @Nullable java.util.concurrent.Executor, @Nullable android.media.tv.tuner.filter.FilterCallback);
- method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.Lnb openLnb(@Nullable java.util.concurrent.Executor, @Nullable android.media.tv.tuner.LnbCallback);
- method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.Lnb openLnbByName(@Nullable String, @Nullable java.util.concurrent.Executor, @NonNull android.media.tv.tuner.LnbCallback);
+ method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.Lnb openLnb(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.LnbCallback);
+ method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.Lnb openLnbByName(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.LnbCallback);
method @Nullable public android.media.tv.tuner.filter.TimeFilter openTimeFilter();
method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int scan(@NonNull android.media.tv.tuner.frontend.FrontendSettings, int, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.frontend.ScanCallback);
- method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int setLna(boolean);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int setLnaEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public void setOnTuneEventListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.frontend.OnTuneEventListener);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public void setResourceLostListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.Tuner.OnResourceLostListener);
method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public void shareFrontendFromTuner(@NonNull android.media.tv.tuner.Tuner);
method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int tune(@NonNull android.media.tv.tuner.frontend.FrontendSettings);
method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public void updateResourcePriority(int, int);
diff --git a/cmds/idmap2/Android.bp b/cmds/idmap2/Android.bp
index 41a1706..66f5c39 100644
--- a/cmds/idmap2/Android.bp
+++ b/cmds/idmap2/Android.bp
@@ -146,6 +146,7 @@
host_supported: true,
srcs: [
"idmap2/Create.cpp",
+ "idmap2/CreateMultiple.cpp",
"idmap2/Dump.cpp",
"idmap2/Lookup.cpp",
"idmap2/Main.cpp",
diff --git a/cmds/idmap2/idmap2/Commands.h b/cmds/idmap2/idmap2/Commands.h
index 718e361..e626738 100644
--- a/cmds/idmap2/idmap2/Commands.h
+++ b/cmds/idmap2/idmap2/Commands.h
@@ -23,6 +23,7 @@
#include "idmap2/Result.h"
android::idmap2::Result<android::idmap2::Unit> Create(const std::vector<std::string>& args);
+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);
diff --git a/cmds/idmap2/idmap2/CreateMultiple.cpp b/cmds/idmap2/idmap2/CreateMultiple.cpp
new file mode 100644
index 0000000..0b0541f
--- /dev/null
+++ b/cmds/idmap2/idmap2/CreateMultiple.cpp
@@ -0,0 +1,144 @@
+/*
+ * 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 <sys/stat.h> // umask
+#include <sys/types.h> // umask
+
+#include <fstream>
+#include <memory>
+#include <ostream>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "android-base/stringprintf.h"
+#include "idmap2/BinaryStreamVisitor.h"
+#include "idmap2/CommandLineOptions.h"
+#include "idmap2/FileUtils.h"
+#include "idmap2/Idmap.h"
+#include "idmap2/Policies.h"
+#include "idmap2/SysTrace.h"
+
+using android::ApkAssets;
+using android::base::StringPrintf;
+using android::idmap2::BinaryStreamVisitor;
+using android::idmap2::CommandLineOptions;
+using android::idmap2::Error;
+using android::idmap2::Idmap;
+using android::idmap2::PoliciesToBitmask;
+using android::idmap2::PolicyBitmask;
+using android::idmap2::PolicyFlags;
+using android::idmap2::Result;
+using android::idmap2::Unit;
+using android::idmap2::utils::kIdmapCacheDir;
+using android::idmap2::utils::kIdmapFilePermissionMask;
+using android::idmap2::utils::UidHasWriteAccessToPath;
+
+Result<Unit> CreateMultiple(const std::vector<std::string>& args) {
+ SYSTRACE << "CreateMultiple " << args;
+ std::string target_apk_path;
+ std::string idmap_dir = kIdmapCacheDir;
+ std::vector<std::string> overlay_apk_paths;
+ std::vector<std::string> policies;
+ bool ignore_overlayable = false;
+
+ const CommandLineOptions opts =
+ CommandLineOptions("idmap2 create-multiple")
+ .MandatoryOption("--target-apk-path",
+ "input: path to apk which will have its resources overlaid",
+ &target_apk_path)
+ .MandatoryOption("--overlay-apk-path",
+ "input: path to apk which contains the new resource values",
+ &overlay_apk_paths)
+ .OptionalOption("--idmap-dir",
+ StringPrintf("output: path to the directory in which to write idmap file"
+ " (defaults to %s)",
+ kIdmapCacheDir),
+ &idmap_dir)
+ .OptionalOption("--policy",
+ "input: an overlayable policy this overlay fulfills"
+ " (if none or supplied, the overlay policy will default to \"public\")",
+ &policies)
+ .OptionalFlag("--ignore-overlayable", "disables overlayable and policy checks",
+ &ignore_overlayable);
+ const auto opts_ok = opts.Parse(args);
+ if (!opts_ok) {
+ return opts_ok.GetError();
+ }
+
+ PolicyBitmask fulfilled_policies = 0;
+ auto conv_result = PoliciesToBitmask(policies);
+ if (conv_result) {
+ fulfilled_policies |= *conv_result;
+ } else {
+ return conv_result.GetError();
+ }
+
+ if (fulfilled_policies == 0) {
+ fulfilled_policies |= PolicyFlags::POLICY_PUBLIC;
+ }
+
+ const std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
+ if (!target_apk) {
+ return Error("failed to load apk %s", target_apk_path.c_str());
+ }
+
+ std::vector<std::string> idmap_paths;
+ for (const std::string& overlay_apk_path : overlay_apk_paths) {
+ const std::string idmap_path = Idmap::CanonicalIdmapPathFor(idmap_dir, overlay_apk_path);
+ const uid_t uid = getuid();
+ if (!UidHasWriteAccessToPath(uid, idmap_path)) {
+ LOG(WARNING) << "uid " << uid << "does not have write access to " << idmap_path.c_str();
+ continue;
+ }
+
+ const std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
+ if (!overlay_apk) {
+ LOG(WARNING) << "failed to load apk " << overlay_apk_path.c_str();
+ continue;
+ }
+
+ const auto idmap =
+ Idmap::FromApkAssets(*target_apk, *overlay_apk, fulfilled_policies, !ignore_overlayable);
+ if (!idmap) {
+ LOG(WARNING) << "failed to create idmap";
+ continue;
+ }
+
+ umask(kIdmapFilePermissionMask);
+ std::ofstream fout(idmap_path);
+ if (fout.fail()) {
+ LOG(WARNING) << "failed to open idmap path " << idmap_path.c_str();
+ continue;
+ }
+
+ BinaryStreamVisitor visitor(fout);
+ (*idmap)->accept(&visitor);
+ fout.close();
+ if (fout.fail()) {
+ LOG(WARNING) << "failed to write to idmap path %s" << idmap_path.c_str();
+ continue;
+ }
+
+ idmap_paths.emplace_back(idmap_path);
+ }
+
+ for (const std::string& idmap_path : idmap_paths) {
+ std::cout << idmap_path << std::endl;
+ }
+
+ return Unit{};
+}
diff --git a/cmds/idmap2/idmap2/Main.cpp b/cmds/idmap2/idmap2/Main.cpp
index 8794908..a07e793 100644
--- a/cmds/idmap2/idmap2/Main.cpp
+++ b/cmds/idmap2/idmap2/Main.cpp
@@ -53,7 +53,9 @@
int main(int argc, char** argv) {
SYSTRACE << "main";
const NameToFunctionMap commands = {
- {"create", Create}, {"dump", Dump}, {"lookup", Lookup}, {"scan", Scan}, {"verify", Verify},
+ {"create", Create}, {"create-multiple", CreateMultiple},
+ {"dump", Dump}, {"lookup", Lookup},
+ {"scan", Scan}, {"verify", Verify},
};
if (argc <= 1) {
PrintUsage(commands, std::cerr);
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index 2ee055d..93522d4 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -105,10 +105,6 @@
"src/uid_data.proto",
],
- cflags: [
- "-DNEW_ENCODING_SCHEME",
- ],
-
local_include_dirs: [
"src",
],
@@ -173,6 +169,11 @@
"libcutils",
"libstatslog",
],
+ apex_available: [
+ //TODO(b/149782403): Remove this once statsd no longer links against libstatsmetadata
+ "com.android.os.statsd",
+ "test_com.android.os.statsd",
+ ],
}
@@ -316,55 +317,55 @@
// statsd micro benchmark
//#############################
-cc_benchmark {
- name: "statsd_benchmark",
- defaults: ["statsd_defaults"],
-
- srcs: [
- // atom_field_options.proto needs field_options.proto, but that is
- // not included in libprotobuf-cpp-lite, so compile it here.
- ":libprotobuf-internal-protos",
-
- "benchmark/duration_metric_benchmark.cpp",
- "benchmark/filter_value_benchmark.cpp",
- "benchmark/get_dimensions_for_condition_benchmark.cpp",
- "benchmark/hello_world_benchmark.cpp",
- "benchmark/log_event_benchmark.cpp",
- "benchmark/main.cpp",
- "benchmark/metric_util.cpp",
- "benchmark/stats_write_benchmark.cpp",
- "src/atom_field_options.proto",
- "src/atoms.proto",
- "src/stats_log.proto",
- ],
-
- proto: {
- type: "lite",
- include_dirs: ["external/protobuf/src"],
- },
-
- cflags: [
- "-Wall",
- "-Werror",
- "-Wno-unused-parameter",
- "-Wno-unused-variable",
- "-Wno-unused-function",
-
- // Bug: http://b/29823425 Disable -Wvarargs for Clang update to r271374
- "-Wno-varargs",
- ],
-
- static_libs: [
- "libplatformprotos",
- ],
-
- shared_libs: [
- "libgtest_prod",
- "libprotobuf-cpp-lite",
- "libstatslog",
- "libstatssocket",
- ],
-}
+//cc_benchmark {
+// name: "statsd_benchmark",
+// defaults: ["statsd_defaults"],
+//
+// srcs: [
+// // atom_field_options.proto needs field_options.proto, but that is
+// // not included in libprotobuf-cpp-lite, so compile it here.
+// ":libprotobuf-internal-protos",
+//
+// "benchmark/duration_metric_benchmark.cpp",
+// "benchmark/filter_value_benchmark.cpp",
+// "benchmark/get_dimensions_for_condition_benchmark.cpp",
+// "benchmark/hello_world_benchmark.cpp",
+// "benchmark/log_event_benchmark.cpp",
+// "benchmark/main.cpp",
+// "benchmark/metric_util.cpp",
+// "benchmark/stats_write_benchmark.cpp",
+// "src/atom_field_options.proto",
+// "src/atoms.proto",
+// "src/stats_log.proto",
+// ],
+//
+// proto: {
+// type: "lite",
+// include_dirs: ["external/protobuf/src"],
+// },
+//
+// cflags: [
+// "-Wall",
+// "-Werror",
+// "-Wno-unused-parameter",
+// "-Wno-unused-variable",
+// "-Wno-unused-function",
+//
+// // Bug: http://b/29823425 Disable -Wvarargs for Clang update to r271374
+// "-Wno-varargs",
+// ],
+//
+// static_libs: [
+// "libplatformprotos",
+// ],
+//
+// shared_libs: [
+// "libgtest_prod",
+// "libprotobuf-cpp-lite",
+// "libstatslog",
+// "libstatssocket",
+// ],
+//}
// ==== java proto device library (for test only) ==============================
java_library {
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index 97e0a2e..649c004 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -208,12 +208,8 @@
trainInfo.requiresLowLatencyMonitor =
event->GetBool(5 /*requires low latency monitor field id*/, &err);
trainInfo.status = int32_t(event->GetLong(6 /*state field id*/, &err));
-#ifdef NEW_ENCODING_SCHEME
std::vector<uint8_t> trainExperimentIdBytes =
event->GetStorage(7 /*experiment ids field id*/, &err);
-#else
- string trainExperimentIdString = event->GetString(7 /*experiment ids field id*/, &err);
-#endif
bool is_rollback = event->GetBool(10 /*is rollback field id*/, &err);
if (err != NO_ERROR) {
@@ -221,12 +217,8 @@
return;
}
ExperimentIds trainExperimentIds;
-#ifdef NEW_ENCODING_SCHEME
if (!trainExperimentIds.ParseFromArray(trainExperimentIdBytes.data(),
trainExperimentIdBytes.size())) {
-#else
- if (!trainExperimentIds.ParseFromString(trainExperimentIdString)) {
-#endif
ALOGE("Failed to parse experimentids in binary push state changed.");
return;
}
@@ -241,11 +233,7 @@
int32_t userId = multiuser_get_user_id(uid);
event->updateValue(2 /*train version field id*/, trainInfo.trainVersionCode, LONG);
-#ifdef NEW_ENCODING_SCHEME
event->updateValue(7 /*experiment ids field id*/, trainExperimentIdProto, STORAGE);
-#else
- event->updateValue(7 /*experiment ids field id*/, trainExperimentIdProto, STRING);
-#endif
event->updateValue(8 /*user id field id*/, userId, INT);
// If this event is a rollback event, then the following bits in the event
@@ -352,11 +340,7 @@
vector<uint8_t> experimentIdProto;
writeExperimentIdsToProto(experimentIds, &experimentIdProto);
-#ifdef NEW_ENCODING_SCHEME
event->updateValue(6 /*experiment ids field id*/, experimentIdProto, STORAGE);
-#else
- event->updateValue(6 /*experiment ids field id*/, experimentIdProto, STRING);
-#endif
}
vector<int64_t> StatsLogProcessor::processWatchdogRollbackOccurred(const int32_t rollbackTypeIn,
diff --git a/cmds/statsd/src/external/StatsCallbackPuller.cpp b/cmds/statsd/src/external/StatsCallbackPuller.cpp
index b6c8e34..0edf40b 100644
--- a/cmds/statsd/src/external/StatsCallbackPuller.cpp
+++ b/cmds/statsd/src/external/StatsCallbackPuller.cpp
@@ -69,8 +69,7 @@
uint8_t* buf = reinterpret_cast<uint8_t*>(
const_cast<int8_t*>(parcel.buffer.data()));
shared_ptr<LogEvent> event = make_shared<LogEvent>(
- buf, parcel.buffer.size(), /*uid=*/-1, /*pid=*/-1,
- /*useNewSchema=*/true);
+ buf, parcel.buffer.size(), /*uid=*/-1, /*pid=*/-1);
sharedData->push_back(event);
}
*pullSuccess = success;
diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp
index 9c50846..3e46d13 100644
--- a/cmds/statsd/src/logd/LogEvent.cpp
+++ b/cmds/statsd/src/logd/LogEvent.cpp
@@ -74,29 +74,7 @@
mLogUid(uid),
mLogPid(pid)
{
-#ifdef NEW_ENCODING_SCHEME
initNew();
-# else
- mContext = create_android_log_parser((char*)msg, len);
- init(mContext);
- if (mContext) android_log_destroy(&mContext); // set mContext to NULL
-#endif
-}
-
-LogEvent::LogEvent(uint8_t* msg, uint32_t len, int32_t uid, int32_t pid, bool useNewSchema)
- : mBuf(msg),
- mRemainingLen(len),
- mLogdTimestampNs(time(nullptr)),
- mLogUid(uid),
- mLogPid(pid)
-{
- if (useNewSchema) {
- initNew();
- } else {
- mContext = create_android_log_parser((char*)msg, len);
- init(mContext);
- if (mContext) android_log_destroy(&mContext); // set mContext to NULL
- }
}
LogEvent::LogEvent(const LogEvent& event) {
@@ -225,22 +203,6 @@
}
}
-void LogEvent::init() {
- if (mContext) {
- const char* buffer;
- size_t len = android_log_write_list_buffer(mContext, &buffer);
- // turns to reader mode
- android_log_context contextForRead = create_android_log_parser(buffer, len);
- if (contextForRead) {
- init(contextForRead);
- // destroy the context to save memory.
- // android_log_destroy will set mContext to NULL
- android_log_destroy(&contextForRead);
- }
- android_log_destroy(&mContext);
- }
-}
-
LogEvent::~LogEvent() {
if (mContext) {
// This is for the case when LogEvent is created using the test interface
@@ -577,132 +539,6 @@
return (typeInfo >> 4) & 0x0F;
}
-/**
- * The elements of each log event are stored as a vector of android_log_list_elements.
- * The goal is to do as little preprocessing as possible, because we read a tiny fraction
- * of the elements that are written to the log.
- *
- * The idea here is to read through the log items once, we get as much information we need for
- * matching as possible. Because this log will be matched against lots of matchers.
- */
-void LogEvent::init(android_log_context context) {
- android_log_list_element elem;
- int i = 0;
- int depth = -1;
- int pos[] = {1, 1, 1};
- bool isKeyValuePairAtom = false;
- do {
- elem = android_log_read_next(context);
- switch ((int)elem.type) {
- case EVENT_TYPE_INT:
- // elem at [0] is EVENT_TYPE_LIST, [1] is the timestamp, [2] is tag id.
- if (i == 2) {
- mTagId = elem.data.int32;
- isKeyValuePairAtom = (mTagId == android::util::KEY_VALUE_PAIRS_ATOM);
- } else {
- if (depth < 0 || depth > 2) {
- return;
- }
-
- mValues.push_back(
- FieldValue(Field(mTagId, pos, depth), Value((int32_t)elem.data.int32)));
-
- pos[depth]++;
- }
- break;
- case EVENT_TYPE_FLOAT: {
- if (depth < 0 || depth > 2) {
- ALOGE("Depth > 2. Not supported!");
- return;
- }
-
- // Handles the oneof field in KeyValuePair atom.
- if (isKeyValuePairAtom && depth == 2) {
- pos[depth] = 5;
- }
-
- mValues.push_back(FieldValue(Field(mTagId, pos, depth), Value(elem.data.float32)));
-
- pos[depth]++;
-
- } break;
- case EVENT_TYPE_STRING: {
- if (depth < 0 || depth > 2) {
- ALOGE("Depth > 2. Not supported!");
- return;
- }
-
- // Handles the oneof field in KeyValuePair atom.
- if (isKeyValuePairAtom && depth == 2) {
- pos[depth] = 4;
- }
- mValues.push_back(FieldValue(Field(mTagId, pos, depth),
- Value(string(elem.data.string, elem.len))));
-
- pos[depth]++;
-
- } break;
- case EVENT_TYPE_LONG: {
- if (i == 1) {
- mElapsedTimestampNs = elem.data.int64;
- } else {
- if (depth < 0 || depth > 2) {
- ALOGE("Depth > 2. Not supported!");
- return;
- }
- // Handles the oneof field in KeyValuePair atom.
- if (isKeyValuePairAtom && depth == 2) {
- pos[depth] = 3;
- }
- mValues.push_back(
- FieldValue(Field(mTagId, pos, depth), Value((int64_t)elem.data.int64)));
-
- pos[depth]++;
- }
- } break;
- case EVENT_TYPE_LIST:
- depth++;
- if (depth > 2) {
- ALOGE("Depth > 2. Not supported!");
- return;
- }
- pos[depth] = 1;
-
- break;
- case EVENT_TYPE_LIST_STOP: {
- int prevDepth = depth;
- depth--;
- if (depth >= 0 && depth < 2) {
- // Now go back to decorate the previous items that are last at prevDepth.
- // So that we can later easily match them with Position=Last matchers.
- pos[prevDepth]--;
- int path = getEncodedField(pos, prevDepth, false);
- for (auto it = mValues.rbegin(); it != mValues.rend(); ++it) {
- if (it->mField.getDepth() >= prevDepth &&
- it->mField.getPath(prevDepth) == path) {
- it->mField.decorateLastPos(prevDepth);
- } else {
- // Safe to break, because the items are in DFS order.
- break;
- }
- }
- pos[depth]++;
- }
- break;
- }
- case EVENT_TYPE_UNKNOWN:
- break;
- default:
- break;
- }
- i++;
- } while ((elem.type != EVENT_TYPE_UNKNOWN) && !elem.complete);
- if (isKeyValuePairAtom && mValues.size() > 0) {
- mValues[0] = FieldValue(Field(android::util::KEY_VALUE_PAIRS_ATOM, getSimpleField(1)),
- Value((int32_t)mLogUid));
- }
-}
-
int64_t LogEvent::GetLong(size_t key, status_t* err) const {
// TODO(b/110561208): encapsulate the magical operations in Field struct as static functions
int field = getSimpleField(key);
diff --git a/cmds/statsd/src/logd/LogEvent.h b/cmds/statsd/src/logd/LogEvent.h
index ea449b0..e167e67 100644
--- a/cmds/statsd/src/logd/LogEvent.h
+++ b/cmds/statsd/src/logd/LogEvent.h
@@ -71,11 +71,6 @@
explicit LogEvent(uint8_t* msg, uint32_t len, int32_t uid, int32_t pid);
/**
- * Temp constructor to use for pulled atoms until we flip the socket schema.
- */
- explicit LogEvent(uint8_t* msg, uint32_t len, int32_t uid, int32_t pid, bool useNewSchema);
-
- /**
* Constructs a LogEvent with synthetic data for testing. Must call init() before reading.
*/
explicit LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedTimestampNs);
@@ -172,12 +167,6 @@
void ToProto(android::util::ProtoOutputStream& out) const;
/**
- * Used with the constructor where tag is passed in. Converts the log_event_list to read mode
- * and prepares the list for reading.
- */
- void init();
-
- /**
* Set elapsed timestamp if the original timestamp is missing.
*/
void setElapsedTimestampNs(int64_t timestampNs) {
@@ -304,11 +293,6 @@
uint8_t getTypeId(uint8_t typeInfo);
uint8_t getNumAnnotations(uint8_t typeInfo);
- /**
- * Parses a log_msg into a LogEvent object.
- */
- void init(android_log_context context);
-
// The items are naturally sorted in DFS order as we read them. this allows us to do fast
// matching.
std::vector<FieldValue> mValues;
diff --git a/cmds/statsd/tests/FieldValue_test.cpp b/cmds/statsd/tests/FieldValue_test.cpp
index 9e69d97..a5ff067 100644
--- a/cmds/statsd/tests/FieldValue_test.cpp
+++ b/cmds/statsd/tests/FieldValue_test.cpp
@@ -72,65 +72,66 @@
EXPECT_EQ((int32_t)0xff7f7f7f, matcher12.mMask);
}
-TEST(AtomMatcherTest, TestFilter_ALL) {
- FieldMatcher matcher1;
- matcher1.set_field(10);
- FieldMatcher* child = matcher1.add_child();
- child->set_field(1);
- child->set_position(Position::ALL);
-
- child->add_child()->set_field(1);
- child->add_child()->set_field(2);
-
- child = matcher1.add_child();
- child->set_field(2);
-
- vector<Matcher> matchers;
- translateFieldMatcher(matcher1, &matchers);
-
- AttributionNodeInternal attribution_node1;
- attribution_node1.set_uid(1111);
- attribution_node1.set_tag("location1");
-
- AttributionNodeInternal attribution_node2;
- attribution_node2.set_uid(2222);
- attribution_node2.set_tag("location2");
-
- AttributionNodeInternal attribution_node3;
- attribution_node3.set_uid(3333);
- attribution_node3.set_tag("location3");
- std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2,
- attribution_node3};
-
- // Set up the event
- LogEvent event(10, 12345);
- event.write(attribution_nodes);
- event.write("some value");
- // Convert to a LogEvent
- event.init();
- HashableDimensionKey output;
-
- filterValues(matchers, event.getValues(), &output);
-
- EXPECT_EQ((size_t)7, output.getValues().size());
- EXPECT_EQ((int32_t)0x02010101, output.getValues()[0].mField.getField());
- EXPECT_EQ((int32_t)1111, output.getValues()[0].mValue.int_value);
- EXPECT_EQ((int32_t)0x02010102, output.getValues()[1].mField.getField());
- EXPECT_EQ("location1", output.getValues()[1].mValue.str_value);
-
- EXPECT_EQ((int32_t)0x02010201, output.getValues()[2].mField.getField());
- EXPECT_EQ((int32_t)2222, output.getValues()[2].mValue.int_value);
- EXPECT_EQ((int32_t)0x02010202, output.getValues()[3].mField.getField());
- EXPECT_EQ("location2", output.getValues()[3].mValue.str_value);
-
- EXPECT_EQ((int32_t)0x02010301, output.getValues()[4].mField.getField());
- EXPECT_EQ((int32_t)3333, output.getValues()[4].mValue.int_value);
- EXPECT_EQ((int32_t)0x02010302, output.getValues()[5].mField.getField());
- EXPECT_EQ("location3", output.getValues()[5].mValue.str_value);
-
- EXPECT_EQ((int32_t)0x00020000, output.getValues()[6].mField.getField());
- EXPECT_EQ("some value", output.getValues()[6].mValue.str_value);
-}
+// TODO(b/149590301): Update this test to use new socket schema.
+//TEST(AtomMatcherTest, TestFilter_ALL) {
+// FieldMatcher matcher1;
+// matcher1.set_field(10);
+// FieldMatcher* child = matcher1.add_child();
+// child->set_field(1);
+// child->set_position(Position::ALL);
+//
+// child->add_child()->set_field(1);
+// child->add_child()->set_field(2);
+//
+// child = matcher1.add_child();
+// child->set_field(2);
+//
+// vector<Matcher> matchers;
+// translateFieldMatcher(matcher1, &matchers);
+//
+// AttributionNodeInternal attribution_node1;
+// attribution_node1.set_uid(1111);
+// attribution_node1.set_tag("location1");
+//
+// AttributionNodeInternal attribution_node2;
+// attribution_node2.set_uid(2222);
+// attribution_node2.set_tag("location2");
+//
+// AttributionNodeInternal attribution_node3;
+// attribution_node3.set_uid(3333);
+// attribution_node3.set_tag("location3");
+// std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2,
+// attribution_node3};
+//
+// // Set up the event
+// LogEvent event(10, 12345);
+// event.write(attribution_nodes);
+// event.write("some value");
+// // Convert to a LogEvent
+// event.init();
+// HashableDimensionKey output;
+//
+// filterValues(matchers, event.getValues(), &output);
+//
+// EXPECT_EQ((size_t)7, output.getValues().size());
+// EXPECT_EQ((int32_t)0x02010101, output.getValues()[0].mField.getField());
+// EXPECT_EQ((int32_t)1111, output.getValues()[0].mValue.int_value);
+// EXPECT_EQ((int32_t)0x02010102, output.getValues()[1].mField.getField());
+// EXPECT_EQ("location1", output.getValues()[1].mValue.str_value);
+//
+// EXPECT_EQ((int32_t)0x02010201, output.getValues()[2].mField.getField());
+// EXPECT_EQ((int32_t)2222, output.getValues()[2].mValue.int_value);
+// EXPECT_EQ((int32_t)0x02010202, output.getValues()[3].mField.getField());
+// EXPECT_EQ("location2", output.getValues()[3].mValue.str_value);
+//
+// EXPECT_EQ((int32_t)0x02010301, output.getValues()[4].mField.getField());
+// EXPECT_EQ((int32_t)3333, output.getValues()[4].mValue.int_value);
+// EXPECT_EQ((int32_t)0x02010302, output.getValues()[5].mField.getField());
+// EXPECT_EQ("location3", output.getValues()[5].mValue.str_value);
+//
+// EXPECT_EQ((int32_t)0x00020000, output.getValues()[6].mField.getField());
+// EXPECT_EQ("some value", output.getValues()[6].mValue.str_value);
+//}
TEST(AtomMatcherTest, TestSubDimension) {
HashableDimensionKey dim;
@@ -173,60 +174,61 @@
EXPECT_TRUE(dim.contains(subDim4));
}
-TEST(AtomMatcherTest, TestMetric2ConditionLink) {
- AttributionNodeInternal attribution_node1;
- attribution_node1.set_uid(1111);
- attribution_node1.set_tag("location1");
-
- AttributionNodeInternal attribution_node2;
- attribution_node2.set_uid(2222);
- attribution_node2.set_tag("location2");
-
- AttributionNodeInternal attribution_node3;
- attribution_node3.set_uid(3333);
- attribution_node3.set_tag("location3");
- std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2,
- attribution_node3};
-
- // Set up the event
- LogEvent event(10, 12345);
- event.write(attribution_nodes);
- event.write("some value");
- // Convert to a LogEvent
- event.init();
-
- FieldMatcher whatMatcher;
- whatMatcher.set_field(10);
- FieldMatcher* child11 = whatMatcher.add_child();
- child11->set_field(1);
- child11->set_position(Position::ANY);
- child11 = child11->add_child();
- child11->set_field(1);
-
- FieldMatcher conditionMatcher;
- conditionMatcher.set_field(27);
- FieldMatcher* child2 = conditionMatcher.add_child();
- child2->set_field(2);
- child2->set_position(Position::LAST);
-
- child2 = child2->add_child();
- child2->set_field(2);
-
- Metric2Condition link;
-
- translateFieldMatcher(whatMatcher, &link.metricFields);
- translateFieldMatcher(conditionMatcher, &link.conditionFields);
-
- EXPECT_EQ((size_t)1, link.metricFields.size());
- EXPECT_EQ((int32_t)0x02010001, link.metricFields[0].mMatcher.getField());
- EXPECT_EQ((int32_t)0xff7f007f, link.metricFields[0].mMask);
- EXPECT_EQ((int32_t)10, link.metricFields[0].mMatcher.getTag());
-
- EXPECT_EQ((size_t)1, link.conditionFields.size());
- EXPECT_EQ((int32_t)0x02028002, link.conditionFields[0].mMatcher.getField());
- EXPECT_EQ((int32_t)0xff7f807f, link.conditionFields[0].mMask);
- EXPECT_EQ((int32_t)27, link.conditionFields[0].mMatcher.getTag());
-}
+// TODO(b/149590301): Update this test to use new socket schema.
+//TEST(AtomMatcherTest, TestMetric2ConditionLink) {
+// AttributionNodeInternal attribution_node1;
+// attribution_node1.set_uid(1111);
+// attribution_node1.set_tag("location1");
+//
+// AttributionNodeInternal attribution_node2;
+// attribution_node2.set_uid(2222);
+// attribution_node2.set_tag("location2");
+//
+// AttributionNodeInternal attribution_node3;
+// attribution_node3.set_uid(3333);
+// attribution_node3.set_tag("location3");
+// std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2,
+// attribution_node3};
+//
+// // Set up the event
+// LogEvent event(10, 12345);
+// event.write(attribution_nodes);
+// event.write("some value");
+// // Convert to a LogEvent
+// event.init();
+//
+// FieldMatcher whatMatcher;
+// whatMatcher.set_field(10);
+// FieldMatcher* child11 = whatMatcher.add_child();
+// child11->set_field(1);
+// child11->set_position(Position::ANY);
+// child11 = child11->add_child();
+// child11->set_field(1);
+//
+// FieldMatcher conditionMatcher;
+// conditionMatcher.set_field(27);
+// FieldMatcher* child2 = conditionMatcher.add_child();
+// child2->set_field(2);
+// child2->set_position(Position::LAST);
+//
+// child2 = child2->add_child();
+// child2->set_field(2);
+//
+// Metric2Condition link;
+//
+// translateFieldMatcher(whatMatcher, &link.metricFields);
+// translateFieldMatcher(conditionMatcher, &link.conditionFields);
+//
+// EXPECT_EQ((size_t)1, link.metricFields.size());
+// EXPECT_EQ((int32_t)0x02010001, link.metricFields[0].mMatcher.getField());
+// EXPECT_EQ((int32_t)0xff7f007f, link.metricFields[0].mMask);
+// EXPECT_EQ((int32_t)10, link.metricFields[0].mMatcher.getTag());
+//
+// EXPECT_EQ((size_t)1, link.conditionFields.size());
+// EXPECT_EQ((int32_t)0x02028002, link.conditionFields[0].mMatcher.getField());
+// EXPECT_EQ((int32_t)0xff7f807f, link.conditionFields[0].mMask);
+// EXPECT_EQ((int32_t)27, link.conditionFields[0].mMatcher.getTag());
+//}
TEST(AtomMatcherTest, TestWriteDimensionPath) {
for (auto position : {Position::ANY, Position::ALL, Position::FIRST, Position::LAST}) {
@@ -437,49 +439,50 @@
EXPECT_EQ(99999, dim4.value_long());
}
-TEST(AtomMatcherTest, TestWriteAtomToProto) {
- AttributionNodeInternal attribution_node1;
- attribution_node1.set_uid(1111);
- attribution_node1.set_tag("location1");
-
- AttributionNodeInternal attribution_node2;
- attribution_node2.set_uid(2222);
- attribution_node2.set_tag("location2");
-
- std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2};
-
- // Set up the event
- LogEvent event(4, 12345);
- event.write(attribution_nodes);
- event.write((int32_t)999);
- // Convert to a LogEvent
- event.init();
-
- android::util::ProtoOutputStream protoOutput;
- writeFieldValueTreeToStream(event.GetTagId(), event.getValues(), &protoOutput);
-
- vector<uint8_t> outData;
- outData.resize(protoOutput.size());
- size_t pos = 0;
- sp<ProtoReader> reader = protoOutput.data();
- while (reader->readBuffer() != NULL) {
- size_t toRead = reader->currentToRead();
- std::memcpy(&(outData[pos]), reader->readBuffer(), toRead);
- pos += toRead;
- reader->move(toRead);
- }
-
- Atom result;
- EXPECT_EQ(true, result.ParseFromArray(&outData[0], outData.size()));
- EXPECT_EQ(Atom::PushedCase::kBleScanResultReceived, result.pushed_case());
- const auto& atom = result.ble_scan_result_received();
- EXPECT_EQ(2, atom.attribution_node_size());
- EXPECT_EQ(1111, atom.attribution_node(0).uid());
- EXPECT_EQ("location1", atom.attribution_node(0).tag());
- EXPECT_EQ(2222, atom.attribution_node(1).uid());
- EXPECT_EQ("location2", atom.attribution_node(1).tag());
- EXPECT_EQ(999, atom.num_results());
-}
+// TODO(b/149590301): Update this test to use new socket schema.
+//TEST(AtomMatcherTest, TestWriteAtomToProto) {
+// AttributionNodeInternal attribution_node1;
+// attribution_node1.set_uid(1111);
+// attribution_node1.set_tag("location1");
+//
+// AttributionNodeInternal attribution_node2;
+// attribution_node2.set_uid(2222);
+// attribution_node2.set_tag("location2");
+//
+// std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2};
+//
+// // Set up the event
+// LogEvent event(4, 12345);
+// event.write(attribution_nodes);
+// event.write((int32_t)999);
+// // Convert to a LogEvent
+// event.init();
+//
+// android::util::ProtoOutputStream protoOutput;
+// writeFieldValueTreeToStream(event.GetTagId(), event.getValues(), &protoOutput);
+//
+// vector<uint8_t> outData;
+// outData.resize(protoOutput.size());
+// size_t pos = 0;
+// sp<ProtoReader> reader = protoOutput.data();
+// while (reader->readBuffer() != NULL) {
+// size_t toRead = reader->currentToRead();
+// std::memcpy(&(outData[pos]), reader->readBuffer(), toRead);
+// pos += toRead;
+// reader->move(toRead);
+// }
+//
+// Atom result;
+// EXPECT_EQ(true, result.ParseFromArray(&outData[0], outData.size()));
+// EXPECT_EQ(Atom::PushedCase::kBleScanResultReceived, result.pushed_case());
+// const auto& atom = result.ble_scan_result_received();
+// EXPECT_EQ(2, atom.attribution_node_size());
+// EXPECT_EQ(1111, atom.attribution_node(0).uid());
+// EXPECT_EQ("location1", atom.attribution_node(0).tag());
+// EXPECT_EQ(2222, atom.attribution_node(1).uid());
+// EXPECT_EQ("location2", atom.attribution_node(1).tag());
+// EXPECT_EQ(999, atom.num_results());
+//}
/*
* Test two Matchers is not a subset of one Matcher.
diff --git a/cmds/statsd/tests/LogEntryMatcher_test.cpp b/cmds/statsd/tests/LogEntryMatcher_test.cpp
index 441d3c8..2de6377 100644
--- a/cmds/statsd/tests/LogEntryMatcher_test.cpp
+++ b/cmds/statsd/tests/LogEntryMatcher_test.cpp
@@ -39,645 +39,646 @@
#ifdef __ANDROID__
-TEST(AtomMatcherTest, TestSimpleMatcher) {
- UidMap uidMap;
-
- // Set up the matcher
- AtomMatcher matcher;
- auto simpleMatcher = matcher.mutable_simple_atom_matcher();
- simpleMatcher->set_atom_id(TAG_ID);
-
- LogEvent event(TAG_ID, 0);
- EXPECT_TRUE(event.write(11));
- event.init();
-
- // Test
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-
- // Wrong tag id.
- simpleMatcher->set_atom_id(TAG_ID + 1);
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-}
-
-TEST(AtomMatcherTest, TestAttributionMatcher) {
- UidMap uidMap;
- AttributionNodeInternal attribution_node1;
- attribution_node1.set_uid(1111);
- attribution_node1.set_tag("location1");
-
- AttributionNodeInternal attribution_node2;
- attribution_node2.set_uid(2222);
- attribution_node2.set_tag("location2");
-
- AttributionNodeInternal attribution_node3;
- attribution_node3.set_uid(3333);
- attribution_node3.set_tag("location3");
- std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2,
- attribution_node3};
-
- // Set up the event
- LogEvent event(TAG_ID, 0);
- event.write(attribution_nodes);
- event.write("some value");
- // Convert to a LogEvent
- event.init();
-
- // Set up the matcher
- AtomMatcher matcher;
- auto simpleMatcher = matcher.mutable_simple_atom_matcher();
- simpleMatcher->set_atom_id(TAG_ID);
-
- // Match first node.
- auto attributionMatcher = simpleMatcher->add_field_value_matcher();
- attributionMatcher->set_field(FIELD_ID_1);
- attributionMatcher->set_position(Position::FIRST);
- attributionMatcher->mutable_matches_tuple()->add_field_value_matcher()->set_field(
- ATTRIBUTION_TAG_FIELD_ID);
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string("tag");
-
- auto fieldMatcher = simpleMatcher->add_field_value_matcher();
- fieldMatcher->set_field(FIELD_ID_2);
- fieldMatcher->set_eq_string("some value");
-
- // Tag not matched.
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("location3");
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("location1");
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-
- // Match last node.
- attributionMatcher->set_position(Position::LAST);
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("location3");
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-
- // Match any node.
- attributionMatcher->set_position(Position::ANY);
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("location1");
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("location2");
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("location3");
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("location4");
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-
- // Attribution match but primitive field not match.
- attributionMatcher->set_position(Position::ANY);
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("location2");
- fieldMatcher->set_eq_string("wrong value");
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-
- fieldMatcher->set_eq_string("some value");
-
- // Uid match.
- attributionMatcher->set_position(Position::ANY);
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_field(
- ATTRIBUTION_UID_FIELD_ID);
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string("pkg0");
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-
- 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")},
- {android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
- android::String16("Pkg2"), android::String16("PkG3")} /* package name list */,
- {android::String16(""), android::String16(""), android::String16(""),
- android::String16(""), android::String16("")});
-
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("pkg3");
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("pkg2");
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("pkg1");
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("pkg0");
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-
- attributionMatcher->set_position(Position::FIRST);
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("pkg0");
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("pkg3");
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("pkg2");
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("pkg1");
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-
- attributionMatcher->set_position(Position::LAST);
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("pkg0");
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("pkg3");
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("pkg2");
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("pkg1");
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-
- // Uid + tag.
- attributionMatcher->set_position(Position::ANY);
- attributionMatcher->mutable_matches_tuple()->add_field_value_matcher()->set_field(
- ATTRIBUTION_TAG_FIELD_ID);
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("pkg0");
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
- ->set_eq_string("location1");
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("pkg1");
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
- ->set_eq_string("location1");
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("pkg1");
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
- ->set_eq_string("location2");
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("pkg2");
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
- ->set_eq_string("location3");
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("pkg3");
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
- ->set_eq_string("location3");
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("pkg3");
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
- ->set_eq_string("location1");
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-
- attributionMatcher->set_position(Position::FIRST);
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("pkg0");
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
- ->set_eq_string("location1");
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("pkg1");
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
- ->set_eq_string("location1");
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("pkg1");
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
- ->set_eq_string("location2");
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("pkg2");
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
- ->set_eq_string("location3");
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("pkg3");
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
- ->set_eq_string("location3");
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("pkg3");
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
- ->set_eq_string("location1");
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-
- attributionMatcher->set_position(Position::LAST);
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("pkg0");
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
- ->set_eq_string("location1");
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("pkg1");
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
- ->set_eq_string("location1");
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("pkg1");
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
- ->set_eq_string("location2");
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("pkg2");
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
- ->set_eq_string("location3");
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("pkg3");
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
- ->set_eq_string("location3");
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
- ->set_eq_string("pkg3");
- attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
- ->set_eq_string("location1");
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-}
-
-TEST(AtomMatcherTest, TestUidFieldMatcher) {
- UidMap 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")},
- {android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
- android::String16("Pkg2"), android::String16("PkG3")} /* package name list */,
- {android::String16(""), android::String16(""), android::String16(""),
- android::String16(""), android::String16("")});
-
- // Set up matcher
- AtomMatcher matcher;
- auto simpleMatcher = matcher.mutable_simple_atom_matcher();
- simpleMatcher->set_atom_id(TAG_ID);
- simpleMatcher->add_field_value_matcher()->set_field(1);
- simpleMatcher->mutable_field_value_matcher(0)->set_eq_string("pkg0");
-
- // Set up the event
- LogEvent event(TAG_ID, 0);
- event.write(1111);
- event.init();
-
- LogEvent event2(TAG_ID_2, 0);
- event2.write(1111);
- event2.write("some value");
- event2.init();
-
- // Tag not in kAtomsWithUidField
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-
- // Tag found in kAtomsWithUidField and has matching uid
- simpleMatcher->set_atom_id(TAG_ID_2);
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event2));
-
- // Tag found in kAtomsWithUidField but has non-matching uid
- simpleMatcher->mutable_field_value_matcher(0)->set_eq_string("Pkg2");
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event2));
-}
-
-TEST(AtomMatcherTest, TestNeqAnyStringMatcher) {
- UidMap 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")},
- {android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
- android::String16("Pkg2"), android::String16("PkG3")} /* package name list */,
- {android::String16(""), android::String16(""), android::String16(""),
- android::String16(""), android::String16("")});
-
- AttributionNodeInternal attribution_node1;
- attribution_node1.set_uid(1111);
- attribution_node1.set_tag("location1");
-
- AttributionNodeInternal attribution_node2;
- attribution_node2.set_uid(2222);
- attribution_node2.set_tag("location2");
-
- AttributionNodeInternal attribution_node3;
- attribution_node3.set_uid(3333);
- attribution_node3.set_tag("location3");
-
- AttributionNodeInternal attribution_node4;
- attribution_node4.set_uid(1066);
- attribution_node4.set_tag("location3");
- std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2,
- attribution_node3, attribution_node4};
-
- // Set up the event
- LogEvent event(TAG_ID, 0);
- event.write(attribution_nodes);
- event.write("some value");
- // Convert to a LogEvent
- event.init();
-
- // Set up the matcher
- AtomMatcher matcher;
- auto simpleMatcher = matcher.mutable_simple_atom_matcher();
- simpleMatcher->set_atom_id(TAG_ID);
-
- // Match first node.
- auto attributionMatcher = simpleMatcher->add_field_value_matcher();
- attributionMatcher->set_field(FIELD_ID_1);
- attributionMatcher->set_position(Position::FIRST);
- attributionMatcher->mutable_matches_tuple()->add_field_value_matcher()->set_field(
- ATTRIBUTION_UID_FIELD_ID);
- auto neqStringList = attributionMatcher->mutable_matches_tuple()
- ->mutable_field_value_matcher(0)
- ->mutable_neq_any_string();
- neqStringList->add_str_value("pkg2");
- neqStringList->add_str_value("pkg3");
-
- auto fieldMatcher = simpleMatcher->add_field_value_matcher();
- fieldMatcher->set_field(FIELD_ID_2);
- fieldMatcher->set_eq_string("some value");
-
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-
- neqStringList->Clear();
- neqStringList->add_str_value("pkg1");
- neqStringList->add_str_value("pkg3");
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-
- attributionMatcher->set_position(Position::ANY);
- neqStringList->Clear();
- neqStringList->add_str_value("maps.com");
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-
- neqStringList->Clear();
- neqStringList->add_str_value("PkG3");
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-
- attributionMatcher->set_position(Position::LAST);
- neqStringList->Clear();
- neqStringList->add_str_value("AID_STATSD");
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-}
-
-TEST(AtomMatcherTest, TestEqAnyStringMatcher) {
- UidMap 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")},
- {android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
- android::String16("Pkg2"), android::String16("PkG3")} /* package name list */,
- {android::String16(""), android::String16(""), android::String16(""),
- android::String16(""), android::String16("")});
-
- AttributionNodeInternal attribution_node1;
- attribution_node1.set_uid(1067);
- attribution_node1.set_tag("location1");
-
- AttributionNodeInternal attribution_node2;
- attribution_node2.set_uid(2222);
- attribution_node2.set_tag("location2");
-
- AttributionNodeInternal attribution_node3;
- attribution_node3.set_uid(3333);
- attribution_node3.set_tag("location3");
-
- AttributionNodeInternal attribution_node4;
- attribution_node4.set_uid(1066);
- attribution_node4.set_tag("location3");
- std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2,
- attribution_node3, attribution_node4};
-
- // Set up the event
- LogEvent event(TAG_ID, 0);
- event.write(attribution_nodes);
- event.write("some value");
- // Convert to a LogEvent
- event.init();
-
- // Set up the matcher
- AtomMatcher matcher;
- auto simpleMatcher = matcher.mutable_simple_atom_matcher();
- simpleMatcher->set_atom_id(TAG_ID);
-
- // Match first node.
- auto attributionMatcher = simpleMatcher->add_field_value_matcher();
- attributionMatcher->set_field(FIELD_ID_1);
- attributionMatcher->set_position(Position::FIRST);
- attributionMatcher->mutable_matches_tuple()->add_field_value_matcher()->set_field(
- ATTRIBUTION_UID_FIELD_ID);
- auto eqStringList = attributionMatcher->mutable_matches_tuple()
- ->mutable_field_value_matcher(0)
- ->mutable_eq_any_string();
- eqStringList->add_str_value("AID_ROOT");
- eqStringList->add_str_value("AID_INCIDENTD");
-
- auto fieldMatcher = simpleMatcher->add_field_value_matcher();
- fieldMatcher->set_field(FIELD_ID_2);
- fieldMatcher->set_eq_string("some value");
-
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-
- attributionMatcher->set_position(Position::ANY);
- eqStringList->Clear();
- eqStringList->add_str_value("AID_STATSD");
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-
- eqStringList->Clear();
- eqStringList->add_str_value("pkg1");
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-
- auto normalStringField = fieldMatcher->mutable_eq_any_string();
- normalStringField->add_str_value("some value123");
- normalStringField->add_str_value("some value");
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-
- normalStringField->Clear();
- normalStringField->add_str_value("AID_STATSD");
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-
- eqStringList->Clear();
- eqStringList->add_str_value("maps.com");
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-}
-
-TEST(AtomMatcherTest, TestBoolMatcher) {
- UidMap uidMap;
- // Set up the matcher
- AtomMatcher matcher;
- auto simpleMatcher = matcher.mutable_simple_atom_matcher();
- simpleMatcher->set_atom_id(TAG_ID);
- auto keyValue1 = simpleMatcher->add_field_value_matcher();
- keyValue1->set_field(FIELD_ID_1);
- auto keyValue2 = simpleMatcher->add_field_value_matcher();
- keyValue2->set_field(FIELD_ID_2);
-
- // Set up the event
- LogEvent event(TAG_ID, 0);
- EXPECT_TRUE(event.write(true));
- EXPECT_TRUE(event.write(false));
- // Convert to a LogEvent
- event.init();
-
- // Test
- keyValue1->set_eq_bool(true);
- keyValue2->set_eq_bool(false);
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-
- keyValue1->set_eq_bool(false);
- keyValue2->set_eq_bool(false);
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-
- keyValue1->set_eq_bool(false);
- keyValue2->set_eq_bool(true);
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-
- keyValue1->set_eq_bool(true);
- keyValue2->set_eq_bool(true);
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-}
-
-TEST(AtomMatcherTest, TestStringMatcher) {
- UidMap uidMap;
- // Set up the matcher
- AtomMatcher matcher;
- auto simpleMatcher = matcher.mutable_simple_atom_matcher();
- simpleMatcher->set_atom_id(TAG_ID);
- auto keyValue = simpleMatcher->add_field_value_matcher();
- keyValue->set_field(FIELD_ID_1);
- keyValue->set_eq_string("some value");
-
- // Set up the event
- LogEvent event(TAG_ID, 0);
- event.write("some value");
- // Convert to a LogEvent
- event.init();
-
- // Test
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-}
-
-TEST(AtomMatcherTest, TestMultiFieldsMatcher) {
- UidMap uidMap;
- // Set up the matcher
- AtomMatcher matcher;
- auto simpleMatcher = matcher.mutable_simple_atom_matcher();
- simpleMatcher->set_atom_id(TAG_ID);
- auto keyValue1 = simpleMatcher->add_field_value_matcher();
- keyValue1->set_field(FIELD_ID_1);
- auto keyValue2 = simpleMatcher->add_field_value_matcher();
- keyValue2->set_field(FIELD_ID_2);
-
- // Set up the event
- LogEvent event(TAG_ID, 0);
- event.write(2);
- event.write(3);
-
- // Convert to a LogEvent
- event.init();
-
- // Test
- keyValue1->set_eq_int(2);
- keyValue2->set_eq_int(3);
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-
- keyValue1->set_eq_int(2);
- keyValue2->set_eq_int(4);
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-
- keyValue1->set_eq_int(4);
- keyValue2->set_eq_int(3);
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-}
-
-TEST(AtomMatcherTest, TestIntComparisonMatcher) {
- UidMap uidMap;
- // Set up the matcher
- AtomMatcher matcher;
- auto simpleMatcher = matcher.mutable_simple_atom_matcher();
-
- simpleMatcher->set_atom_id(TAG_ID);
- auto keyValue = simpleMatcher->add_field_value_matcher();
- keyValue->set_field(FIELD_ID_1);
-
- // Set up the event
- LogEvent event(TAG_ID, 0);
- event.write(11);
- event.init();
-
- // Test
-
- // eq_int
- keyValue->set_eq_int(10);
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
- keyValue->set_eq_int(11);
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
- keyValue->set_eq_int(12);
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-
- // lt_int
- keyValue->set_lt_int(10);
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
- keyValue->set_lt_int(11);
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
- keyValue->set_lt_int(12);
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-
- // lte_int
- keyValue->set_lte_int(10);
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
- keyValue->set_lte_int(11);
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
- keyValue->set_lte_int(12);
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-
- // gt_int
- keyValue->set_gt_int(10);
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
- keyValue->set_gt_int(11);
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
- keyValue->set_gt_int(12);
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-
- // gte_int
- keyValue->set_gte_int(10);
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
- keyValue->set_gte_int(11);
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
- keyValue->set_gte_int(12);
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-}
-
-TEST(AtomMatcherTest, TestFloatComparisonMatcher) {
- UidMap uidMap;
- // Set up the matcher
- AtomMatcher matcher;
- auto simpleMatcher = matcher.mutable_simple_atom_matcher();
- simpleMatcher->set_atom_id(TAG_ID);
-
- auto keyValue = simpleMatcher->add_field_value_matcher();
- keyValue->set_field(FIELD_ID_1);
-
- LogEvent event1(TAG_ID, 0);
- keyValue->set_lt_float(10.0);
- event1.write(10.1f);
- event1.init();
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event1));
-
- LogEvent event2(TAG_ID, 0);
- event2.write(9.9f);
- event2.init();
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event2));
-
- LogEvent event3(TAG_ID, 0);
- event3.write(10.1f);
- event3.init();
- keyValue->set_gt_float(10.0);
- EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event3));
-
- LogEvent event4(TAG_ID, 0);
- event4.write(9.9f);
- event4.init();
- EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event4));
-}
+// TODO(b/149590301): Update these tests to use new socket schema.
+//TEST(AtomMatcherTest, TestSimpleMatcher) {
+// UidMap uidMap;
+//
+// // Set up the matcher
+// AtomMatcher matcher;
+// auto simpleMatcher = matcher.mutable_simple_atom_matcher();
+// simpleMatcher->set_atom_id(TAG_ID);
+//
+// LogEvent event(TAG_ID, 0);
+// EXPECT_TRUE(event.write(11));
+// event.init();
+//
+// // Test
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+// // Wrong tag id.
+// simpleMatcher->set_atom_id(TAG_ID + 1);
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//}
+//
+//TEST(AtomMatcherTest, TestAttributionMatcher) {
+// UidMap uidMap;
+// AttributionNodeInternal attribution_node1;
+// attribution_node1.set_uid(1111);
+// attribution_node1.set_tag("location1");
+//
+// AttributionNodeInternal attribution_node2;
+// attribution_node2.set_uid(2222);
+// attribution_node2.set_tag("location2");
+//
+// AttributionNodeInternal attribution_node3;
+// attribution_node3.set_uid(3333);
+// attribution_node3.set_tag("location3");
+// std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2,
+// attribution_node3};
+//
+// // Set up the event
+// LogEvent event(TAG_ID, 0);
+// event.write(attribution_nodes);
+// event.write("some value");
+// // Convert to a LogEvent
+// event.init();
+//
+// // Set up the matcher
+// AtomMatcher matcher;
+// auto simpleMatcher = matcher.mutable_simple_atom_matcher();
+// simpleMatcher->set_atom_id(TAG_ID);
+//
+// // Match first node.
+// auto attributionMatcher = simpleMatcher->add_field_value_matcher();
+// attributionMatcher->set_field(FIELD_ID_1);
+// attributionMatcher->set_position(Position::FIRST);
+// attributionMatcher->mutable_matches_tuple()->add_field_value_matcher()->set_field(
+// ATTRIBUTION_TAG_FIELD_ID);
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string("tag");
+//
+// auto fieldMatcher = simpleMatcher->add_field_value_matcher();
+// fieldMatcher->set_field(FIELD_ID_2);
+// fieldMatcher->set_eq_string("some value");
+//
+// // Tag not matched.
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("location3");
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("location1");
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+// // Match last node.
+// attributionMatcher->set_position(Position::LAST);
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("location3");
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+// // Match any node.
+// attributionMatcher->set_position(Position::ANY);
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("location1");
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("location2");
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("location3");
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("location4");
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+// // Attribution match but primitive field not match.
+// attributionMatcher->set_position(Position::ANY);
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("location2");
+// fieldMatcher->set_eq_string("wrong value");
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+// fieldMatcher->set_eq_string("some value");
+//
+// // Uid match.
+// attributionMatcher->set_position(Position::ANY);
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_field(
+// ATTRIBUTION_UID_FIELD_ID);
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string("pkg0");
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+// 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")},
+// {android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
+// android::String16("Pkg2"), android::String16("PkG3")} /* package name list */,
+// {android::String16(""), android::String16(""), android::String16(""),
+// android::String16(""), android::String16("")});
+//
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("pkg3");
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("pkg2");
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("pkg1");
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("pkg0");
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+// attributionMatcher->set_position(Position::FIRST);
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("pkg0");
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("pkg3");
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("pkg2");
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("pkg1");
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+// attributionMatcher->set_position(Position::LAST);
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("pkg0");
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("pkg3");
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("pkg2");
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("pkg1");
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+// // Uid + tag.
+// attributionMatcher->set_position(Position::ANY);
+// attributionMatcher->mutable_matches_tuple()->add_field_value_matcher()->set_field(
+// ATTRIBUTION_TAG_FIELD_ID);
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("pkg0");
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+// ->set_eq_string("location1");
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("pkg1");
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+// ->set_eq_string("location1");
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("pkg1");
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+// ->set_eq_string("location2");
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("pkg2");
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+// ->set_eq_string("location3");
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("pkg3");
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+// ->set_eq_string("location3");
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("pkg3");
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+// ->set_eq_string("location1");
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+// attributionMatcher->set_position(Position::FIRST);
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("pkg0");
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+// ->set_eq_string("location1");
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("pkg1");
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+// ->set_eq_string("location1");
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("pkg1");
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+// ->set_eq_string("location2");
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("pkg2");
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+// ->set_eq_string("location3");
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("pkg3");
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+// ->set_eq_string("location3");
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("pkg3");
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+// ->set_eq_string("location1");
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+// attributionMatcher->set_position(Position::LAST);
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("pkg0");
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+// ->set_eq_string("location1");
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("pkg1");
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+// ->set_eq_string("location1");
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("pkg1");
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+// ->set_eq_string("location2");
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("pkg2");
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+// ->set_eq_string("location3");
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("pkg3");
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+// ->set_eq_string("location3");
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+// ->set_eq_string("pkg3");
+// attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+// ->set_eq_string("location1");
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//}
+//
+//TEST(AtomMatcherTest, TestUidFieldMatcher) {
+// UidMap 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")},
+// {android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
+// android::String16("Pkg2"), android::String16("PkG3")} /* package name list */,
+// {android::String16(""), android::String16(""), android::String16(""),
+// android::String16(""), android::String16("")});
+//
+// // Set up matcher
+// AtomMatcher matcher;
+// auto simpleMatcher = matcher.mutable_simple_atom_matcher();
+// simpleMatcher->set_atom_id(TAG_ID);
+// simpleMatcher->add_field_value_matcher()->set_field(1);
+// simpleMatcher->mutable_field_value_matcher(0)->set_eq_string("pkg0");
+//
+// // Set up the event
+// LogEvent event(TAG_ID, 0);
+// event.write(1111);
+// event.init();
+//
+// LogEvent event2(TAG_ID_2, 0);
+// event2.write(1111);
+// event2.write("some value");
+// event2.init();
+//
+// // Tag not in kAtomsWithUidField
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+// // Tag found in kAtomsWithUidField and has matching uid
+// simpleMatcher->set_atom_id(TAG_ID_2);
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event2));
+//
+// // Tag found in kAtomsWithUidField but has non-matching uid
+// simpleMatcher->mutable_field_value_matcher(0)->set_eq_string("Pkg2");
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event2));
+//}
+//
+//TEST(AtomMatcherTest, TestNeqAnyStringMatcher) {
+// UidMap 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")},
+// {android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
+// android::String16("Pkg2"), android::String16("PkG3")} /* package name list */,
+// {android::String16(""), android::String16(""), android::String16(""),
+// android::String16(""), android::String16("")});
+//
+// AttributionNodeInternal attribution_node1;
+// attribution_node1.set_uid(1111);
+// attribution_node1.set_tag("location1");
+//
+// AttributionNodeInternal attribution_node2;
+// attribution_node2.set_uid(2222);
+// attribution_node2.set_tag("location2");
+//
+// AttributionNodeInternal attribution_node3;
+// attribution_node3.set_uid(3333);
+// attribution_node3.set_tag("location3");
+//
+// AttributionNodeInternal attribution_node4;
+// attribution_node4.set_uid(1066);
+// attribution_node4.set_tag("location3");
+// std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2,
+// attribution_node3, attribution_node4};
+//
+// // Set up the event
+// LogEvent event(TAG_ID, 0);
+// event.write(attribution_nodes);
+// event.write("some value");
+// // Convert to a LogEvent
+// event.init();
+//
+// // Set up the matcher
+// AtomMatcher matcher;
+// auto simpleMatcher = matcher.mutable_simple_atom_matcher();
+// simpleMatcher->set_atom_id(TAG_ID);
+//
+// // Match first node.
+// auto attributionMatcher = simpleMatcher->add_field_value_matcher();
+// attributionMatcher->set_field(FIELD_ID_1);
+// attributionMatcher->set_position(Position::FIRST);
+// attributionMatcher->mutable_matches_tuple()->add_field_value_matcher()->set_field(
+// ATTRIBUTION_UID_FIELD_ID);
+// auto neqStringList = attributionMatcher->mutable_matches_tuple()
+// ->mutable_field_value_matcher(0)
+// ->mutable_neq_any_string();
+// neqStringList->add_str_value("pkg2");
+// neqStringList->add_str_value("pkg3");
+//
+// auto fieldMatcher = simpleMatcher->add_field_value_matcher();
+// fieldMatcher->set_field(FIELD_ID_2);
+// fieldMatcher->set_eq_string("some value");
+//
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+// neqStringList->Clear();
+// neqStringList->add_str_value("pkg1");
+// neqStringList->add_str_value("pkg3");
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+// attributionMatcher->set_position(Position::ANY);
+// neqStringList->Clear();
+// neqStringList->add_str_value("maps.com");
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+// neqStringList->Clear();
+// neqStringList->add_str_value("PkG3");
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+// attributionMatcher->set_position(Position::LAST);
+// neqStringList->Clear();
+// neqStringList->add_str_value("AID_STATSD");
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//}
+//
+//TEST(AtomMatcherTest, TestEqAnyStringMatcher) {
+// UidMap 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")},
+// {android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
+// android::String16("Pkg2"), android::String16("PkG3")} /* package name list */,
+// {android::String16(""), android::String16(""), android::String16(""),
+// android::String16(""), android::String16("")});
+//
+// AttributionNodeInternal attribution_node1;
+// attribution_node1.set_uid(1067);
+// attribution_node1.set_tag("location1");
+//
+// AttributionNodeInternal attribution_node2;
+// attribution_node2.set_uid(2222);
+// attribution_node2.set_tag("location2");
+//
+// AttributionNodeInternal attribution_node3;
+// attribution_node3.set_uid(3333);
+// attribution_node3.set_tag("location3");
+//
+// AttributionNodeInternal attribution_node4;
+// attribution_node4.set_uid(1066);
+// attribution_node4.set_tag("location3");
+// std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2,
+// attribution_node3, attribution_node4};
+//
+// // Set up the event
+// LogEvent event(TAG_ID, 0);
+// event.write(attribution_nodes);
+// event.write("some value");
+// // Convert to a LogEvent
+// event.init();
+//
+// // Set up the matcher
+// AtomMatcher matcher;
+// auto simpleMatcher = matcher.mutable_simple_atom_matcher();
+// simpleMatcher->set_atom_id(TAG_ID);
+//
+// // Match first node.
+// auto attributionMatcher = simpleMatcher->add_field_value_matcher();
+// attributionMatcher->set_field(FIELD_ID_1);
+// attributionMatcher->set_position(Position::FIRST);
+// attributionMatcher->mutable_matches_tuple()->add_field_value_matcher()->set_field(
+// ATTRIBUTION_UID_FIELD_ID);
+// auto eqStringList = attributionMatcher->mutable_matches_tuple()
+// ->mutable_field_value_matcher(0)
+// ->mutable_eq_any_string();
+// eqStringList->add_str_value("AID_ROOT");
+// eqStringList->add_str_value("AID_INCIDENTD");
+//
+// auto fieldMatcher = simpleMatcher->add_field_value_matcher();
+// fieldMatcher->set_field(FIELD_ID_2);
+// fieldMatcher->set_eq_string("some value");
+//
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+// attributionMatcher->set_position(Position::ANY);
+// eqStringList->Clear();
+// eqStringList->add_str_value("AID_STATSD");
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+// eqStringList->Clear();
+// eqStringList->add_str_value("pkg1");
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+// auto normalStringField = fieldMatcher->mutable_eq_any_string();
+// normalStringField->add_str_value("some value123");
+// normalStringField->add_str_value("some value");
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+// normalStringField->Clear();
+// normalStringField->add_str_value("AID_STATSD");
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+// eqStringList->Clear();
+// eqStringList->add_str_value("maps.com");
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//}
+//
+//TEST(AtomMatcherTest, TestBoolMatcher) {
+// UidMap uidMap;
+// // Set up the matcher
+// AtomMatcher matcher;
+// auto simpleMatcher = matcher.mutable_simple_atom_matcher();
+// simpleMatcher->set_atom_id(TAG_ID);
+// auto keyValue1 = simpleMatcher->add_field_value_matcher();
+// keyValue1->set_field(FIELD_ID_1);
+// auto keyValue2 = simpleMatcher->add_field_value_matcher();
+// keyValue2->set_field(FIELD_ID_2);
+//
+// // Set up the event
+// LogEvent event(TAG_ID, 0);
+// EXPECT_TRUE(event.write(true));
+// EXPECT_TRUE(event.write(false));
+// // Convert to a LogEvent
+// event.init();
+//
+// // Test
+// keyValue1->set_eq_bool(true);
+// keyValue2->set_eq_bool(false);
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+// keyValue1->set_eq_bool(false);
+// keyValue2->set_eq_bool(false);
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+// keyValue1->set_eq_bool(false);
+// keyValue2->set_eq_bool(true);
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+// keyValue1->set_eq_bool(true);
+// keyValue2->set_eq_bool(true);
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//}
+//
+//TEST(AtomMatcherTest, TestStringMatcher) {
+// UidMap uidMap;
+// // Set up the matcher
+// AtomMatcher matcher;
+// auto simpleMatcher = matcher.mutable_simple_atom_matcher();
+// simpleMatcher->set_atom_id(TAG_ID);
+// auto keyValue = simpleMatcher->add_field_value_matcher();
+// keyValue->set_field(FIELD_ID_1);
+// keyValue->set_eq_string("some value");
+//
+// // Set up the event
+// LogEvent event(TAG_ID, 0);
+// event.write("some value");
+// // Convert to a LogEvent
+// event.init();
+//
+// // Test
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//}
+//
+//TEST(AtomMatcherTest, TestMultiFieldsMatcher) {
+// UidMap uidMap;
+// // Set up the matcher
+// AtomMatcher matcher;
+// auto simpleMatcher = matcher.mutable_simple_atom_matcher();
+// simpleMatcher->set_atom_id(TAG_ID);
+// auto keyValue1 = simpleMatcher->add_field_value_matcher();
+// keyValue1->set_field(FIELD_ID_1);
+// auto keyValue2 = simpleMatcher->add_field_value_matcher();
+// keyValue2->set_field(FIELD_ID_2);
+//
+// // Set up the event
+// LogEvent event(TAG_ID, 0);
+// event.write(2);
+// event.write(3);
+//
+// // Convert to a LogEvent
+// event.init();
+//
+// // Test
+// keyValue1->set_eq_int(2);
+// keyValue2->set_eq_int(3);
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+// keyValue1->set_eq_int(2);
+// keyValue2->set_eq_int(4);
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+// keyValue1->set_eq_int(4);
+// keyValue2->set_eq_int(3);
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//}
+//
+//TEST(AtomMatcherTest, TestIntComparisonMatcher) {
+// UidMap uidMap;
+// // Set up the matcher
+// AtomMatcher matcher;
+// auto simpleMatcher = matcher.mutable_simple_atom_matcher();
+//
+// simpleMatcher->set_atom_id(TAG_ID);
+// auto keyValue = simpleMatcher->add_field_value_matcher();
+// keyValue->set_field(FIELD_ID_1);
+//
+// // Set up the event
+// LogEvent event(TAG_ID, 0);
+// event.write(11);
+// event.init();
+//
+// // Test
+//
+// // eq_int
+// keyValue->set_eq_int(10);
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+// keyValue->set_eq_int(11);
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+// keyValue->set_eq_int(12);
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+// // lt_int
+// keyValue->set_lt_int(10);
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+// keyValue->set_lt_int(11);
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+// keyValue->set_lt_int(12);
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+// // lte_int
+// keyValue->set_lte_int(10);
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+// keyValue->set_lte_int(11);
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+// keyValue->set_lte_int(12);
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+// // gt_int
+// keyValue->set_gt_int(10);
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+// keyValue->set_gt_int(11);
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+// keyValue->set_gt_int(12);
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+// // gte_int
+// keyValue->set_gte_int(10);
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+// keyValue->set_gte_int(11);
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+// keyValue->set_gte_int(12);
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//}
+//
+//TEST(AtomMatcherTest, TestFloatComparisonMatcher) {
+// UidMap uidMap;
+// // Set up the matcher
+// AtomMatcher matcher;
+// auto simpleMatcher = matcher.mutable_simple_atom_matcher();
+// simpleMatcher->set_atom_id(TAG_ID);
+//
+// auto keyValue = simpleMatcher->add_field_value_matcher();
+// keyValue->set_field(FIELD_ID_1);
+//
+// LogEvent event1(TAG_ID, 0);
+// keyValue->set_lt_float(10.0);
+// event1.write(10.1f);
+// event1.init();
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event1));
+//
+// LogEvent event2(TAG_ID, 0);
+// event2.write(9.9f);
+// event2.init();
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event2));
+//
+// LogEvent event3(TAG_ID, 0);
+// event3.write(10.1f);
+// event3.init();
+// keyValue->set_gt_float(10.0);
+// EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event3));
+//
+// LogEvent event4(TAG_ID, 0);
+// event4.write(9.9f);
+// event4.init();
+// EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event4));
+//}
// Helper for the composite matchers.
void addSimpleMatcher(SimpleAtomMatcher* simpleMatcher, int tag, int key, int val) {
diff --git a/cmds/statsd/tests/LogEvent_test.cpp b/cmds/statsd/tests/LogEvent_test.cpp
index f624e12..7542faf 100644
--- a/cmds/statsd/tests/LogEvent_test.cpp
+++ b/cmds/statsd/tests/LogEvent_test.cpp
@@ -31,9 +31,6 @@
using util::ProtoOutputStream;
using util::ProtoReader;
-
-#ifdef NEW_ENCODING_SCHEME
-
Field getField(int32_t tag, const vector<int32_t>& pos, int32_t depth, const vector<bool>& last) {
Field f(tag, (int32_t*)pos.data(), depth);
@@ -241,480 +238,6 @@
AStatsEvent_release(event);
}
-#else // NEW_ENCODING_SCHEME
-
-TEST(LogEventTest, TestLogParsing) {
- LogEvent event1(1, 2000);
-
- std::vector<AttributionNodeInternal> nodes;
-
- AttributionNodeInternal node1;
- node1.set_uid(1000);
- node1.set_tag("tag1");
- nodes.push_back(node1);
-
- AttributionNodeInternal node2;
- node2.set_uid(2000);
- node2.set_tag("tag2");
- nodes.push_back(node2);
-
- event1.write(nodes);
- event1.write("hello");
- event1.write((int32_t)10);
- event1.write((int64_t)20);
- event1.write((float)1.1);
- event1.init();
-
- const auto& items = event1.getValues();
- EXPECT_EQ((size_t)8, items.size());
- EXPECT_EQ(1, event1.GetTagId());
-
- const FieldValue& item0 = event1.getValues()[0];
- EXPECT_EQ(0x2010101, item0.mField.getField());
- EXPECT_EQ(Type::INT, item0.mValue.getType());
- EXPECT_EQ(1000, item0.mValue.int_value);
-
- const FieldValue& item1 = event1.getValues()[1];
- EXPECT_EQ(0x2010182, item1.mField.getField());
- EXPECT_EQ(Type::STRING, item1.mValue.getType());
- EXPECT_EQ("tag1", item1.mValue.str_value);
-
- const FieldValue& item2 = event1.getValues()[2];
- EXPECT_EQ(0x2018201, item2.mField.getField());
- EXPECT_EQ(Type::INT, item2.mValue.getType());
- EXPECT_EQ(2000, item2.mValue.int_value);
-
- const FieldValue& item3 = event1.getValues()[3];
- EXPECT_EQ(0x2018282, item3.mField.getField());
- EXPECT_EQ(Type::STRING, item3.mValue.getType());
- EXPECT_EQ("tag2", item3.mValue.str_value);
-
- const FieldValue& item4 = event1.getValues()[4];
- EXPECT_EQ(0x20000, item4.mField.getField());
- EXPECT_EQ(Type::STRING, item4.mValue.getType());
- EXPECT_EQ("hello", item4.mValue.str_value);
-
- const FieldValue& item5 = event1.getValues()[5];
- EXPECT_EQ(0x30000, item5.mField.getField());
- EXPECT_EQ(Type::INT, item5.mValue.getType());
- EXPECT_EQ(10, item5.mValue.int_value);
-
- const FieldValue& item6 = event1.getValues()[6];
- EXPECT_EQ(0x40000, item6.mField.getField());
- EXPECT_EQ(Type::LONG, item6.mValue.getType());
- EXPECT_EQ((int64_t)20, item6.mValue.long_value);
-
- const FieldValue& item7 = event1.getValues()[7];
- EXPECT_EQ(0x50000, item7.mField.getField());
- EXPECT_EQ(Type::FLOAT, item7.mValue.getType());
- EXPECT_EQ((float)1.1, item7.mValue.float_value);
-}
-
-TEST(LogEventTest, TestKeyValuePairsAtomParsing) {
- LogEvent event1(83, 2000, 1000);
- std::map<int32_t, int32_t> int_map;
- std::map<int32_t, int64_t> long_map;
- std::map<int32_t, std::string> string_map;
- std::map<int32_t, float> float_map;
-
- int_map[11] = 123;
- int_map[22] = 345;
-
- long_map[33] = 678L;
- long_map[44] = 890L;
-
- string_map[1] = "test2";
- string_map[2] = "test1";
-
- float_map[111] = 2.2f;
- float_map[222] = 1.1f;
-
- EXPECT_TRUE(event1.writeKeyValuePairs(0, // Logging side logs 0 uid.
- int_map,
- long_map,
- string_map,
- float_map));
- event1.init();
-
- EXPECT_EQ(83, event1.GetTagId());
- const auto& items = event1.getValues();
- EXPECT_EQ((size_t)17, items.size());
-
- const FieldValue& item0 = event1.getValues()[0];
- EXPECT_EQ(0x10000, item0.mField.getField());
- EXPECT_EQ(Type::INT, item0.mValue.getType());
- EXPECT_EQ(1000, item0.mValue.int_value);
-
- const FieldValue& item1 = event1.getValues()[1];
- EXPECT_EQ(0x2010201, item1.mField.getField());
- EXPECT_EQ(Type::INT, item1.mValue.getType());
- EXPECT_EQ(11, item1.mValue.int_value);
-
- const FieldValue& item2 = event1.getValues()[2];
- EXPECT_EQ(0x2010282, item2.mField.getField());
- EXPECT_EQ(Type::INT, item2.mValue.getType());
- EXPECT_EQ(123, item2.mValue.int_value);
-
- const FieldValue& item3 = event1.getValues()[3];
- EXPECT_EQ(0x2010301, item3.mField.getField());
- EXPECT_EQ(Type::INT, item3.mValue.getType());
- EXPECT_EQ(22, item3.mValue.int_value);
-
- const FieldValue& item4 = event1.getValues()[4];
- EXPECT_EQ(0x2010382, item4.mField.getField());
- EXPECT_EQ(Type::INT, item4.mValue.getType());
- EXPECT_EQ(345, item4.mValue.int_value);
-
- const FieldValue& item5 = event1.getValues()[5];
- EXPECT_EQ(0x2010401, item5.mField.getField());
- EXPECT_EQ(Type::INT, item5.mValue.getType());
- EXPECT_EQ(33, item5.mValue.int_value);
-
- const FieldValue& item6 = event1.getValues()[6];
- EXPECT_EQ(0x2010483, item6.mField.getField());
- EXPECT_EQ(Type::LONG, item6.mValue.getType());
- EXPECT_EQ(678L, item6.mValue.int_value);
-
- const FieldValue& item7 = event1.getValues()[7];
- EXPECT_EQ(0x2010501, item7.mField.getField());
- EXPECT_EQ(Type::INT, item7.mValue.getType());
- EXPECT_EQ(44, item7.mValue.int_value);
-
- const FieldValue& item8 = event1.getValues()[8];
- EXPECT_EQ(0x2010583, item8.mField.getField());
- EXPECT_EQ(Type::LONG, item8.mValue.getType());
- EXPECT_EQ(890L, item8.mValue.int_value);
-
- const FieldValue& item9 = event1.getValues()[9];
- EXPECT_EQ(0x2010601, item9.mField.getField());
- EXPECT_EQ(Type::INT, item9.mValue.getType());
- EXPECT_EQ(1, item9.mValue.int_value);
-
- const FieldValue& item10 = event1.getValues()[10];
- EXPECT_EQ(0x2010684, item10.mField.getField());
- EXPECT_EQ(Type::STRING, item10.mValue.getType());
- EXPECT_EQ("test2", item10.mValue.str_value);
-
- const FieldValue& item11 = event1.getValues()[11];
- EXPECT_EQ(0x2010701, item11.mField.getField());
- EXPECT_EQ(Type::INT, item11.mValue.getType());
- EXPECT_EQ(2, item11.mValue.int_value);
-
- const FieldValue& item12 = event1.getValues()[12];
- EXPECT_EQ(0x2010784, item12.mField.getField());
- EXPECT_EQ(Type::STRING, item12.mValue.getType());
- EXPECT_EQ("test1", item12.mValue.str_value);
-
- const FieldValue& item13 = event1.getValues()[13];
- EXPECT_EQ(0x2010801, item13.mField.getField());
- EXPECT_EQ(Type::INT, item13.mValue.getType());
- EXPECT_EQ(111, item13.mValue.int_value);
-
- const FieldValue& item14 = event1.getValues()[14];
- EXPECT_EQ(0x2010885, item14.mField.getField());
- EXPECT_EQ(Type::FLOAT, item14.mValue.getType());
- EXPECT_EQ(2.2f, item14.mValue.float_value);
-
- const FieldValue& item15 = event1.getValues()[15];
- EXPECT_EQ(0x2018901, item15.mField.getField());
- EXPECT_EQ(Type::INT, item15.mValue.getType());
- EXPECT_EQ(222, item15.mValue.int_value);
-
- const FieldValue& item16 = event1.getValues()[16];
- EXPECT_EQ(0x2018985, item16.mField.getField());
- EXPECT_EQ(Type::FLOAT, item16.mValue.getType());
- EXPECT_EQ(1.1f, item16.mValue.float_value);
-}
-
-TEST(LogEventTest, TestLogParsing2) {
- LogEvent event1(1, 2000);
-
- std::vector<AttributionNodeInternal> nodes;
-
- event1.write("hello");
-
- // repeated msg can be in the middle
- AttributionNodeInternal node1;
- node1.set_uid(1000);
- node1.set_tag("tag1");
- nodes.push_back(node1);
-
- AttributionNodeInternal node2;
- node2.set_uid(2000);
- node2.set_tag("tag2");
- nodes.push_back(node2);
- event1.write(nodes);
-
- event1.write((int32_t)10);
- event1.write((int64_t)20);
- event1.write((float)1.1);
- event1.init();
-
- const auto& items = event1.getValues();
- EXPECT_EQ((size_t)8, items.size());
- EXPECT_EQ(1, event1.GetTagId());
-
- const FieldValue& item = event1.getValues()[0];
- EXPECT_EQ(0x00010000, item.mField.getField());
- EXPECT_EQ(Type::STRING, item.mValue.getType());
- EXPECT_EQ("hello", item.mValue.str_value);
-
- const FieldValue& item0 = event1.getValues()[1];
- EXPECT_EQ(0x2020101, item0.mField.getField());
- EXPECT_EQ(Type::INT, item0.mValue.getType());
- EXPECT_EQ(1000, item0.mValue.int_value);
-
- const FieldValue& item1 = event1.getValues()[2];
- EXPECT_EQ(0x2020182, item1.mField.getField());
- EXPECT_EQ(Type::STRING, item1.mValue.getType());
- EXPECT_EQ("tag1", item1.mValue.str_value);
-
- const FieldValue& item2 = event1.getValues()[3];
- EXPECT_EQ(0x2028201, item2.mField.getField());
- EXPECT_EQ(Type::INT, item2.mValue.getType());
- EXPECT_EQ(2000, item2.mValue.int_value);
-
- const FieldValue& item3 = event1.getValues()[4];
- EXPECT_EQ(0x2028282, item3.mField.getField());
- EXPECT_EQ(Type::STRING, item3.mValue.getType());
- EXPECT_EQ("tag2", item3.mValue.str_value);
-
- const FieldValue& item5 = event1.getValues()[5];
- EXPECT_EQ(0x30000, item5.mField.getField());
- EXPECT_EQ(Type::INT, item5.mValue.getType());
- EXPECT_EQ(10, item5.mValue.int_value);
-
- const FieldValue& item6 = event1.getValues()[6];
- EXPECT_EQ(0x40000, item6.mField.getField());
- EXPECT_EQ(Type::LONG, item6.mValue.getType());
- EXPECT_EQ((int64_t)20, item6.mValue.long_value);
-
- const FieldValue& item7 = event1.getValues()[7];
- EXPECT_EQ(0x50000, item7.mField.getField());
- EXPECT_EQ(Type::FLOAT, item7.mValue.getType());
- EXPECT_EQ((float)1.1, item7.mValue.float_value);
-}
-
-TEST(LogEventTest, TestKeyValuePairsEvent) {
- std::map<int32_t, int32_t> int_map;
- std::map<int32_t, int64_t> long_map;
- std::map<int32_t, std::string> string_map;
- std::map<int32_t, float> float_map;
-
- int_map[11] = 123;
- int_map[22] = 345;
-
- long_map[33] = 678L;
- long_map[44] = 890L;
-
- string_map[1] = "test2";
- string_map[2] = "test1";
-
- float_map[111] = 2.2f;
- float_map[222] = 1.1f;
-
- LogEvent event1(83, 2000, 2001, 10001, int_map, long_map, string_map, float_map);
- event1.init();
-
- EXPECT_EQ(83, event1.GetTagId());
- EXPECT_EQ((int64_t)2000, event1.GetLogdTimestampNs());
- EXPECT_EQ((int64_t)2001, event1.GetElapsedTimestampNs());
- EXPECT_EQ((int64_t)10001, event1.GetUid());
-
- const auto& items = event1.getValues();
- EXPECT_EQ((size_t)17, items.size());
-
- const FieldValue& item0 = event1.getValues()[0];
- EXPECT_EQ(0x00010000, item0.mField.getField());
- EXPECT_EQ(Type::INT, item0.mValue.getType());
- EXPECT_EQ(10001, item0.mValue.int_value);
-
- const FieldValue& item1 = event1.getValues()[1];
- EXPECT_EQ(0x2020101, item1.mField.getField());
- EXPECT_EQ(Type::INT, item1.mValue.getType());
- EXPECT_EQ(11, item1.mValue.int_value);
-
- const FieldValue& item2 = event1.getValues()[2];
- EXPECT_EQ(0x2020182, item2.mField.getField());
- EXPECT_EQ(Type::INT, item2.mValue.getType());
- EXPECT_EQ(123, item2.mValue.int_value);
-
- const FieldValue& item3 = event1.getValues()[3];
- EXPECT_EQ(0x2020201, item3.mField.getField());
- EXPECT_EQ(Type::INT, item3.mValue.getType());
- EXPECT_EQ(22, item3.mValue.int_value);
-
- const FieldValue& item4 = event1.getValues()[4];
- EXPECT_EQ(0x2020282, item4.mField.getField());
- EXPECT_EQ(Type::INT, item4.mValue.getType());
- EXPECT_EQ(345, item4.mValue.int_value);
-
- const FieldValue& item5 = event1.getValues()[5];
- EXPECT_EQ(0x2020301, item5.mField.getField());
- EXPECT_EQ(Type::INT, item5.mValue.getType());
- EXPECT_EQ(33, item5.mValue.int_value);
-
- const FieldValue& item6 = event1.getValues()[6];
- EXPECT_EQ(0x2020383, item6.mField.getField());
- EXPECT_EQ(Type::LONG, item6.mValue.getType());
- EXPECT_EQ(678L, item6.mValue.long_value);
-
- const FieldValue& item7 = event1.getValues()[7];
- EXPECT_EQ(0x2020401, item7.mField.getField());
- EXPECT_EQ(Type::INT, item7.mValue.getType());
- EXPECT_EQ(44, item7.mValue.int_value);
-
- const FieldValue& item8 = event1.getValues()[8];
- EXPECT_EQ(0x2020483, item8.mField.getField());
- EXPECT_EQ(Type::LONG, item8.mValue.getType());
- EXPECT_EQ(890L, item8.mValue.long_value);
-
- const FieldValue& item9 = event1.getValues()[9];
- EXPECT_EQ(0x2020501, item9.mField.getField());
- EXPECT_EQ(Type::INT, item9.mValue.getType());
- EXPECT_EQ(1, item9.mValue.int_value);
-
- const FieldValue& item10 = event1.getValues()[10];
- EXPECT_EQ(0x2020584, item10.mField.getField());
- EXPECT_EQ(Type::STRING, item10.mValue.getType());
- EXPECT_EQ("test2", item10.mValue.str_value);
-
- const FieldValue& item11 = event1.getValues()[11];
- EXPECT_EQ(0x2020601, item11.mField.getField());
- EXPECT_EQ(Type::INT, item11.mValue.getType());
- EXPECT_EQ(2, item11.mValue.int_value);
-
- const FieldValue& item12 = event1.getValues()[12];
- EXPECT_EQ(0x2020684, item12.mField.getField());
- EXPECT_EQ(Type::STRING, item12.mValue.getType());
- EXPECT_EQ("test1", item12.mValue.str_value);
-
- const FieldValue& item13 = event1.getValues()[13];
- EXPECT_EQ(0x2020701, item13.mField.getField());
- EXPECT_EQ(Type::INT, item13.mValue.getType());
- EXPECT_EQ(111, item13.mValue.int_value);
-
- const FieldValue& item14 = event1.getValues()[14];
- EXPECT_EQ(0x2020785, item14.mField.getField());
- EXPECT_EQ(Type::FLOAT, item14.mValue.getType());
- EXPECT_EQ(2.2f, item14.mValue.float_value);
-
- const FieldValue& item15 = event1.getValues()[15];
- EXPECT_EQ(0x2028801, item15.mField.getField());
- EXPECT_EQ(Type::INT, item15.mValue.getType());
- EXPECT_EQ(222, item15.mValue.int_value);
-
- const FieldValue& item16 = event1.getValues()[16];
- EXPECT_EQ(0x2028885, item16.mField.getField());
- EXPECT_EQ(Type::FLOAT, item16.mValue.getType());
- EXPECT_EQ(1.1f, item16.mValue.float_value);
-}
-
-TEST(LogEventTest, TestBinaryFieldAtom) {
- Atom launcherAtom;
- auto launcher_event = launcherAtom.mutable_launcher_event();
- launcher_event->set_action(stats::launcher::LauncherAction::LONGPRESS);
- launcher_event->set_src_state(stats::launcher::LauncherState::OVERVIEW);
- launcher_event->set_dst_state(stats::launcher::LauncherState::ALLAPPS);
-
- auto extension = launcher_event->mutable_extension();
-
- auto src_target = extension->add_src_target();
- src_target->set_type(stats::launcher::LauncherTarget_Type_ITEM_TYPE);
- src_target->set_item(stats::launcher::LauncherTarget_Item_FOLDER_ICON);
-
- auto dst_target = extension->add_dst_target();
- dst_target->set_type(stats::launcher::LauncherTarget_Type_ITEM_TYPE);
- dst_target->set_item(stats::launcher::LauncherTarget_Item_WIDGET);
-
- string extension_str;
- extension->SerializeToString(&extension_str);
-
- LogEvent event1(Atom::kLauncherEventFieldNumber, 1000);
-
- event1.write((int32_t)stats::launcher::LauncherAction::LONGPRESS);
- event1.write((int32_t)stats::launcher::LauncherState::OVERVIEW);
- event1.write((int64_t)stats::launcher::LauncherState::ALLAPPS);
- event1.writeBytes(extension_str);
- event1.init();
-
- ProtoOutputStream proto;
- event1.ToProto(proto);
-
- std::vector<uint8_t> outData;
- outData.resize(proto.size());
- size_t pos = 0;
- sp<ProtoReader> reader = proto.data();
- while (reader->readBuffer() != NULL) {
- size_t toRead = reader->currentToRead();
- std::memcpy(&(outData[pos]), reader->readBuffer(), toRead);
- pos += toRead;
- reader->move(toRead);
- }
-
- std::string result_str(outData.begin(), outData.end());
- std::string orig_str;
- launcherAtom.SerializeToString(&orig_str);
-
- EXPECT_EQ(orig_str, result_str);
-}
-
-TEST(LogEventTest, TestBinaryFieldAtom_empty) {
- Atom launcherAtom;
- auto launcher_event = launcherAtom.mutable_launcher_event();
- launcher_event->set_action(stats::launcher::LauncherAction::LONGPRESS);
- launcher_event->set_src_state(stats::launcher::LauncherState::OVERVIEW);
- launcher_event->set_dst_state(stats::launcher::LauncherState::ALLAPPS);
-
- // empty string.
- string extension_str;
-
- LogEvent event1(Atom::kLauncherEventFieldNumber, 1000);
-
- event1.write((int32_t)stats::launcher::LauncherAction::LONGPRESS);
- event1.write((int32_t)stats::launcher::LauncherState::OVERVIEW);
- event1.write((int64_t)stats::launcher::LauncherState::ALLAPPS);
- event1.writeBytes(extension_str);
- event1.init();
-
- ProtoOutputStream proto;
- event1.ToProto(proto);
-
- std::vector<uint8_t> outData;
- outData.resize(proto.size());
- size_t pos = 0;
- sp<ProtoReader> reader = proto.data();
- while (reader->readBuffer() != NULL) {
- size_t toRead = reader->currentToRead();
- std::memcpy(&(outData[pos]), reader->readBuffer(), toRead);
- pos += toRead;
- reader->move(toRead);
- }
-
- std::string result_str(outData.begin(), outData.end());
- std::string orig_str;
- launcherAtom.SerializeToString(&orig_str);
-
- EXPECT_EQ(orig_str, result_str);
-}
-
-TEST(LogEventTest, TestWriteExperimentIdsToProto) {
- std::vector<int64_t> expIds;
- expIds.push_back(5038);
- std::vector<uint8_t> proto;
-
- writeExperimentIdsToProto(expIds, &proto);
-
- EXPECT_EQ(proto.size(), 3);
- // Proto wire format for field ID 1, varint
- EXPECT_EQ(proto[0], 0x08);
- // varint of 5038, 2 bytes long
- EXPECT_EQ(proto[1], 0xae);
- EXPECT_EQ(proto[2], 0x27);
-}
-#endif // NEW_ENCODING_SCHEME
-
-
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/cmds/statsd/tests/StatsLogProcessor_test.cpp b/cmds/statsd/tests/StatsLogProcessor_test.cpp
index 3d7e5c9..81d6f72 100644
--- a/cmds/statsd/tests/StatsLogProcessor_test.cpp
+++ b/cmds/statsd/tests/StatsLogProcessor_test.cpp
@@ -253,1415 +253,1416 @@
EXPECT_EQ(2, report.annotation(0).field_int32());
}
-TEST(StatsLogProcessorTest, TestOnDumpReportEraseData) {
- // Setup a simple config.
- StatsdConfig config;
- config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
- auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
- *config.add_atom_matcher() = wakelockAcquireMatcher;
-
- auto countMetric = config.add_count_metric();
- countMetric->set_id(123456);
- countMetric->set_what(wakelockAcquireMatcher.id());
- countMetric->set_bucket(FIVE_MINUTES);
-
- ConfigKey cfgKey;
- sp<StatsLogProcessor> processor = CreateStatsLogProcessor(1, 1, config, cfgKey);
-
- std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
- auto event = CreateAcquireWakelockEvent(attributions1, "wl1", 2);
- processor->OnLogEvent(event.get());
-
- vector<uint8_t> bytes;
- ConfigMetricsReportList output;
-
- // Dump report WITHOUT erasing data.
- processor->onDumpReport(cfgKey, 3, true, false /* Do NOT erase data. */, ADB_DUMP, FAST, &bytes);
- output.ParseFromArray(bytes.data(), bytes.size());
- EXPECT_EQ(output.reports_size(), 1);
- EXPECT_EQ(output.reports(0).metrics_size(), 1);
- EXPECT_EQ(output.reports(0).metrics(0).count_metrics().data_size(), 1);
-
- // Dump report WITH erasing data. There should be data since we didn't previously erase it.
- processor->onDumpReport(cfgKey, 4, true, true /* DO erase data. */, ADB_DUMP, FAST, &bytes);
- output.ParseFromArray(bytes.data(), bytes.size());
- EXPECT_EQ(output.reports_size(), 1);
- EXPECT_EQ(output.reports(0).metrics_size(), 1);
- EXPECT_EQ(output.reports(0).metrics(0).count_metrics().data_size(), 1);
-
- // Dump report again. There should be no data since we erased it.
- processor->onDumpReport(cfgKey, 5, true, true /* DO erase data. */, ADB_DUMP, FAST, &bytes);
- output.ParseFromArray(bytes.data(), bytes.size());
- // We don't care whether statsd has a report, as long as it has no count metrics in it.
- bool noData = output.reports_size() == 0
- || output.reports(0).metrics_size() == 0
- || output.reports(0).metrics(0).count_metrics().data_size() == 0;
- EXPECT_TRUE(noData);
-}
-
-TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead) {
- int uid = 1111;
-
- // Setup a simple config, no activation
- StatsdConfig config1;
- int64_t cfgId1 = 12341;
- config1.set_id(cfgId1);
- config1.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
- auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
- *config1.add_atom_matcher() = wakelockAcquireMatcher;
-
- long metricId1 = 1234561;
- long metricId2 = 1234562;
- auto countMetric1 = config1.add_count_metric();
- countMetric1->set_id(metricId1);
- countMetric1->set_what(wakelockAcquireMatcher.id());
- countMetric1->set_bucket(FIVE_MINUTES);
-
- auto countMetric2 = config1.add_count_metric();
- countMetric2->set_id(metricId2);
- countMetric2->set_what(wakelockAcquireMatcher.id());
- countMetric2->set_bucket(FIVE_MINUTES);
-
- ConfigKey cfgKey1(uid, cfgId1);
-
- // Add another config, with two metrics, one with activation
- StatsdConfig config2;
- int64_t cfgId2 = 12342;
- config2.set_id(cfgId2);
- config2.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
- *config2.add_atom_matcher() = wakelockAcquireMatcher;
-
- long metricId3 = 1234561;
- long metricId4 = 1234562;
-
- auto countMetric3 = config2.add_count_metric();
- countMetric3->set_id(metricId3);
- countMetric3->set_what(wakelockAcquireMatcher.id());
- countMetric3->set_bucket(FIVE_MINUTES);
-
- auto countMetric4 = config2.add_count_metric();
- countMetric4->set_id(metricId4);
- countMetric4->set_what(wakelockAcquireMatcher.id());
- countMetric4->set_bucket(FIVE_MINUTES);
-
- auto metric3Activation = config2.add_metric_activation();
- metric3Activation->set_metric_id(metricId3);
- metric3Activation->set_activation_type(ACTIVATE_IMMEDIATELY);
- auto metric3ActivationTrigger = metric3Activation->add_event_activation();
- metric3ActivationTrigger->set_atom_matcher_id(wakelockAcquireMatcher.id());
- metric3ActivationTrigger->set_ttl_seconds(100);
-
- ConfigKey cfgKey2(uid, cfgId2);
-
- // Add another config, with two metrics, both with activations
- StatsdConfig config3;
- int64_t cfgId3 = 12343;
- config3.set_id(cfgId3);
- config3.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
- *config3.add_atom_matcher() = wakelockAcquireMatcher;
-
- long metricId5 = 1234565;
- long metricId6 = 1234566;
- auto countMetric5 = config3.add_count_metric();
- countMetric5->set_id(metricId5);
- countMetric5->set_what(wakelockAcquireMatcher.id());
- countMetric5->set_bucket(FIVE_MINUTES);
-
- auto countMetric6 = config3.add_count_metric();
- countMetric6->set_id(metricId6);
- countMetric6->set_what(wakelockAcquireMatcher.id());
- countMetric6->set_bucket(FIVE_MINUTES);
-
- auto metric5Activation = config3.add_metric_activation();
- metric5Activation->set_metric_id(metricId5);
- metric5Activation->set_activation_type(ACTIVATE_IMMEDIATELY);
- auto metric5ActivationTrigger = metric5Activation->add_event_activation();
- metric5ActivationTrigger->set_atom_matcher_id(wakelockAcquireMatcher.id());
- metric5ActivationTrigger->set_ttl_seconds(100);
-
- auto metric6Activation = config3.add_metric_activation();
- metric6Activation->set_metric_id(metricId6);
- metric6Activation->set_activation_type(ACTIVATE_IMMEDIATELY);
- auto metric6ActivationTrigger = metric6Activation->add_event_activation();
- metric6ActivationTrigger->set_atom_matcher_id(wakelockAcquireMatcher.id());
- metric6ActivationTrigger->set_ttl_seconds(200);
-
- ConfigKey cfgKey3(uid, cfgId3);
-
- sp<UidMap> m = new UidMap();
- sp<StatsPullerManager> pullerManager = new StatsPullerManager();
- sp<AlarmMonitor> anomalyAlarmMonitor;
- sp<AlarmMonitor> subscriberAlarmMonitor;
- vector<int64_t> activeConfigsBroadcast;
-
- long timeBase1 = 1;
- int broadcastCount = 0;
- StatsLogProcessor processor(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor,
- timeBase1, [](const ConfigKey& key) { return true; },
- [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid,
- const vector<int64_t>& activeConfigs) {
- broadcastCount++;
- EXPECT_EQ(broadcastUid, uid);
- activeConfigsBroadcast.clear();
- activeConfigsBroadcast.insert(activeConfigsBroadcast.end(),
- activeConfigs.begin(), activeConfigs.end());
- return true;
- });
-
- processor.OnConfigUpdated(1, cfgKey1, config1);
- processor.OnConfigUpdated(2, cfgKey2, config2);
- processor.OnConfigUpdated(3, cfgKey3, config3);
-
- EXPECT_EQ(3, processor.mMetricsManagers.size());
-
- // Expect the first config and both metrics in it to be active.
- auto it = processor.mMetricsManagers.find(cfgKey1);
- EXPECT_TRUE(it != processor.mMetricsManagers.end());
- auto& metricsManager1 = it->second;
- EXPECT_TRUE(metricsManager1->isActive());
-
- auto metricIt = metricsManager1->mAllMetricProducers.begin();
- for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
- if ((*metricIt)->getMetricId() == metricId1) {
- break;
- }
- }
- EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
- auto& metricProducer1 = *metricIt;
- EXPECT_TRUE(metricProducer1->isActive());
-
- metricIt = metricsManager1->mAllMetricProducers.begin();
- for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
- if ((*metricIt)->getMetricId() == metricId2) {
- break;
- }
- }
- EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
- auto& metricProducer2 = *metricIt;
- EXPECT_TRUE(metricProducer2->isActive());
-
- // Expect config 2 to be active. Metric 3 shouldn't be active, metric 4 should be active.
- it = processor.mMetricsManagers.find(cfgKey2);
- EXPECT_TRUE(it != processor.mMetricsManagers.end());
- auto& metricsManager2 = it->second;
- EXPECT_TRUE(metricsManager2->isActive());
-
- metricIt = metricsManager2->mAllMetricProducers.begin();
- for (; metricIt != metricsManager2->mAllMetricProducers.end(); metricIt++) {
- if ((*metricIt)->getMetricId() == metricId3) {
- break;
- }
- }
- EXPECT_TRUE(metricIt != metricsManager2->mAllMetricProducers.end());
- auto& metricProducer3 = *metricIt;
- EXPECT_FALSE(metricProducer3->isActive());
-
- metricIt = metricsManager2->mAllMetricProducers.begin();
- for (; metricIt != metricsManager2->mAllMetricProducers.end(); metricIt++) {
- if ((*metricIt)->getMetricId() == metricId4) {
- break;
- }
- }
- EXPECT_TRUE(metricIt != metricsManager2->mAllMetricProducers.end());
- auto& metricProducer4 = *metricIt;
- EXPECT_TRUE(metricProducer4->isActive());
-
- // Expect the third config and both metrics in it to be inactive.
- it = processor.mMetricsManagers.find(cfgKey3);
- EXPECT_TRUE(it != processor.mMetricsManagers.end());
- auto& metricsManager3 = it->second;
- EXPECT_FALSE(metricsManager3->isActive());
-
- metricIt = metricsManager3->mAllMetricProducers.begin();
- for (; metricIt != metricsManager2->mAllMetricProducers.end(); metricIt++) {
- if ((*metricIt)->getMetricId() == metricId5) {
- break;
- }
- }
- EXPECT_TRUE(metricIt != metricsManager3->mAllMetricProducers.end());
- auto& metricProducer5 = *metricIt;
- EXPECT_FALSE(metricProducer5->isActive());
-
- metricIt = metricsManager3->mAllMetricProducers.begin();
- for (; metricIt != metricsManager3->mAllMetricProducers.end(); metricIt++) {
- if ((*metricIt)->getMetricId() == metricId6) {
- break;
- }
- }
- EXPECT_TRUE(metricIt != metricsManager3->mAllMetricProducers.end());
- auto& metricProducer6 = *metricIt;
- EXPECT_FALSE(metricProducer6->isActive());
-
- // No broadcast for active configs should have happened yet.
- EXPECT_EQ(broadcastCount, 0);
-
- // Activate all 3 metrics that were not active.
- std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
- auto event = CreateAcquireWakelockEvent(attributions1, "wl1", 100 + timeBase1);
- processor.OnLogEvent(event.get());
-
- // Assert that all 3 configs are active.
- EXPECT_TRUE(metricsManager1->isActive());
- EXPECT_TRUE(metricsManager2->isActive());
- EXPECT_TRUE(metricsManager3->isActive());
-
- // A broadcast should have happened, and all 3 configs should be active in the broadcast.
- EXPECT_EQ(broadcastCount, 1);
- EXPECT_EQ(activeConfigsBroadcast.size(), 3);
- EXPECT_TRUE(std::find(activeConfigsBroadcast.begin(), activeConfigsBroadcast.end(), cfgId1)
- != activeConfigsBroadcast.end());
- EXPECT_TRUE(std::find(activeConfigsBroadcast.begin(), activeConfigsBroadcast.end(), cfgId2)
- != activeConfigsBroadcast.end());
- EXPECT_TRUE(std::find(activeConfigsBroadcast.begin(), activeConfigsBroadcast.end(), cfgId3)
- != activeConfigsBroadcast.end());
-
- // When we shut down, metrics 3 & 5 have 100ns remaining, metric 6 has 100s + 100ns.
- int64_t shutDownTime = timeBase1 + 100 * NS_PER_SEC;
- processor.SaveActiveConfigsToDisk(shutDownTime);
- const int64_t ttl3 = event->GetElapsedTimestampNs() +
- metric3ActivationTrigger->ttl_seconds() * NS_PER_SEC - shutDownTime;
- const int64_t ttl5 = event->GetElapsedTimestampNs() +
- metric5ActivationTrigger->ttl_seconds() * NS_PER_SEC - shutDownTime;
- const int64_t ttl6 = event->GetElapsedTimestampNs() +
- metric6ActivationTrigger->ttl_seconds() * NS_PER_SEC - shutDownTime;
-
- // Create a second StatsLogProcessor and push the same 3 configs.
- long timeBase2 = 1000;
- sp<StatsLogProcessor> processor2 =
- CreateStatsLogProcessor(timeBase2, timeBase2, config1, cfgKey1);
- processor2->OnConfigUpdated(timeBase2, cfgKey2, config2);
- processor2->OnConfigUpdated(timeBase2, cfgKey3, config3);
-
- EXPECT_EQ(3, processor2->mMetricsManagers.size());
-
- // First config and both metrics are active.
- it = processor2->mMetricsManagers.find(cfgKey1);
- EXPECT_TRUE(it != processor2->mMetricsManagers.end());
- auto& metricsManager1001 = it->second;
- EXPECT_TRUE(metricsManager1001->isActive());
-
- metricIt = metricsManager1001->mAllMetricProducers.begin();
- for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
- if ((*metricIt)->getMetricId() == metricId1) {
- break;
- }
- }
- EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
- auto& metricProducer1001 = *metricIt;
- EXPECT_TRUE(metricProducer1001->isActive());
-
- metricIt = metricsManager1001->mAllMetricProducers.begin();
- for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
- if ((*metricIt)->getMetricId() == metricId2) {
- break;
- }
- }
- EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
- auto& metricProducer1002 = *metricIt;
- EXPECT_TRUE(metricProducer1002->isActive());
-
- // Second config is active. Metric 3 is inactive, metric 4 is active.
- it = processor2->mMetricsManagers.find(cfgKey2);
- EXPECT_TRUE(it != processor2->mMetricsManagers.end());
- auto& metricsManager1002 = it->second;
- EXPECT_TRUE(metricsManager1002->isActive());
-
- metricIt = metricsManager1002->mAllMetricProducers.begin();
- for (; metricIt != metricsManager1002->mAllMetricProducers.end(); metricIt++) {
- if ((*metricIt)->getMetricId() == metricId3) {
- break;
- }
- }
- EXPECT_TRUE(metricIt != metricsManager1002->mAllMetricProducers.end());
- auto& metricProducer1003 = *metricIt;
- EXPECT_FALSE(metricProducer1003->isActive());
-
- metricIt = metricsManager1002->mAllMetricProducers.begin();
- for (; metricIt != metricsManager1002->mAllMetricProducers.end(); metricIt++) {
- if ((*metricIt)->getMetricId() == metricId4) {
- break;
- }
- }
- EXPECT_TRUE(metricIt != metricsManager1002->mAllMetricProducers.end());
- auto& metricProducer1004 = *metricIt;
- EXPECT_TRUE(metricProducer1004->isActive());
-
- // Config 3 is inactive. both metrics are inactive.
- it = processor2->mMetricsManagers.find(cfgKey3);
- EXPECT_TRUE(it != processor2->mMetricsManagers.end());
- auto& metricsManager1003 = it->second;
- EXPECT_FALSE(metricsManager1003->isActive());
- EXPECT_EQ(2, metricsManager1003->mAllMetricProducers.size());
-
- metricIt = metricsManager1003->mAllMetricProducers.begin();
- for (; metricIt != metricsManager1002->mAllMetricProducers.end(); metricIt++) {
- if ((*metricIt)->getMetricId() == metricId5) {
- break;
- }
- }
- EXPECT_TRUE(metricIt != metricsManager1003->mAllMetricProducers.end());
- auto& metricProducer1005 = *metricIt;
- EXPECT_FALSE(metricProducer1005->isActive());
-
- metricIt = metricsManager1003->mAllMetricProducers.begin();
- for (; metricIt != metricsManager1003->mAllMetricProducers.end(); metricIt++) {
- if ((*metricIt)->getMetricId() == metricId6) {
- break;
- }
- }
- EXPECT_TRUE(metricIt != metricsManager1003->mAllMetricProducers.end());
- auto& metricProducer1006 = *metricIt;
- EXPECT_FALSE(metricProducer1006->isActive());
-
- // Assert that all 3 metrics with activation are inactive and that the ttls were properly set.
- EXPECT_FALSE(metricProducer1003->isActive());
- const auto& activation1003 = metricProducer1003->mEventActivationMap.begin()->second;
- EXPECT_EQ(100 * NS_PER_SEC, activation1003->ttl_ns);
- EXPECT_EQ(0, activation1003->start_ns);
- EXPECT_FALSE(metricProducer1005->isActive());
- const auto& activation1005 = metricProducer1005->mEventActivationMap.begin()->second;
- EXPECT_EQ(100 * NS_PER_SEC, activation1005->ttl_ns);
- EXPECT_EQ(0, activation1005->start_ns);
- EXPECT_FALSE(metricProducer1006->isActive());
- const auto& activation1006 = metricProducer1006->mEventActivationMap.begin()->second;
- EXPECT_EQ(200 * NS_PER_SEC, activation1006->ttl_ns);
- EXPECT_EQ(0, activation1006->start_ns);
-
- processor2->LoadActiveConfigsFromDisk();
-
- // After loading activations from disk, assert that all 3 metrics are active.
- EXPECT_TRUE(metricProducer1003->isActive());
- EXPECT_EQ(timeBase2 + ttl3 - activation1003->ttl_ns, activation1003->start_ns);
- EXPECT_TRUE(metricProducer1005->isActive());
- EXPECT_EQ(timeBase2 + ttl5 - activation1005->ttl_ns, activation1005->start_ns);
- EXPECT_TRUE(metricProducer1006->isActive());
- EXPECT_EQ(timeBase2 + ttl6 - activation1006->ttl_ns, activation1003->start_ns);
-
- // Make sure no more broadcasts have happened.
- EXPECT_EQ(broadcastCount, 1);
-}
-
-TEST(StatsLogProcessorTest, TestActivationOnBoot) {
- int uid = 1111;
-
- StatsdConfig config1;
- config1.set_id(12341);
- config1.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
- auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
- *config1.add_atom_matcher() = wakelockAcquireMatcher;
-
- long metricId1 = 1234561;
- long metricId2 = 1234562;
- auto countMetric1 = config1.add_count_metric();
- countMetric1->set_id(metricId1);
- countMetric1->set_what(wakelockAcquireMatcher.id());
- countMetric1->set_bucket(FIVE_MINUTES);
-
- auto countMetric2 = config1.add_count_metric();
- countMetric2->set_id(metricId2);
- countMetric2->set_what(wakelockAcquireMatcher.id());
- countMetric2->set_bucket(FIVE_MINUTES);
-
- auto metric1Activation = config1.add_metric_activation();
- metric1Activation->set_metric_id(metricId1);
- metric1Activation->set_activation_type(ACTIVATE_ON_BOOT);
- auto metric1ActivationTrigger = metric1Activation->add_event_activation();
- metric1ActivationTrigger->set_atom_matcher_id(wakelockAcquireMatcher.id());
- metric1ActivationTrigger->set_ttl_seconds(100);
-
- ConfigKey cfgKey1(uid, 12341);
- long timeBase1 = 1;
- sp<StatsLogProcessor> processor =
- CreateStatsLogProcessor(timeBase1, timeBase1, config1, cfgKey1);
-
- EXPECT_EQ(1, processor->mMetricsManagers.size());
- auto it = processor->mMetricsManagers.find(cfgKey1);
- EXPECT_TRUE(it != processor->mMetricsManagers.end());
- auto& metricsManager1 = it->second;
- EXPECT_TRUE(metricsManager1->isActive());
-
- auto metricIt = metricsManager1->mAllMetricProducers.begin();
- for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
- if ((*metricIt)->getMetricId() == metricId1) {
- break;
- }
- }
- EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
- auto& metricProducer1 = *metricIt;
- EXPECT_FALSE(metricProducer1->isActive());
-
- metricIt = metricsManager1->mAllMetricProducers.begin();
- for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
- if ((*metricIt)->getMetricId() == metricId2) {
- break;
- }
- }
- EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
- auto& metricProducer2 = *metricIt;
- EXPECT_TRUE(metricProducer2->isActive());
-
- const auto& activation1 = metricProducer1->mEventActivationMap.begin()->second;
- EXPECT_EQ(100 * NS_PER_SEC, activation1->ttl_ns);
- EXPECT_EQ(0, activation1->start_ns);
- EXPECT_EQ(kNotActive, activation1->state);
-
- std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
- auto event = CreateAcquireWakelockEvent(attributions1, "wl1", 100 + timeBase1);
- processor->OnLogEvent(event.get());
-
- EXPECT_FALSE(metricProducer1->isActive());
- EXPECT_EQ(0, activation1->start_ns);
- EXPECT_EQ(kActiveOnBoot, activation1->state);
-
- int64_t shutDownTime = timeBase1 + 100 * NS_PER_SEC;
- processor->SaveActiveConfigsToDisk(shutDownTime);
- EXPECT_FALSE(metricProducer1->isActive());
- const int64_t ttl1 = metric1ActivationTrigger->ttl_seconds() * NS_PER_SEC;
-
- long timeBase2 = 1000;
- sp<StatsLogProcessor> processor2 =
- CreateStatsLogProcessor(timeBase2, timeBase2, config1, cfgKey1);
-
- EXPECT_EQ(1, processor2->mMetricsManagers.size());
- it = processor2->mMetricsManagers.find(cfgKey1);
- EXPECT_TRUE(it != processor2->mMetricsManagers.end());
- auto& metricsManager1001 = it->second;
- EXPECT_TRUE(metricsManager1001->isActive());
-
- metricIt = metricsManager1001->mAllMetricProducers.begin();
- for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
- if ((*metricIt)->getMetricId() == metricId1) {
- break;
- }
- }
- EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
- auto& metricProducer1001 = *metricIt;
- EXPECT_FALSE(metricProducer1001->isActive());
-
- metricIt = metricsManager1001->mAllMetricProducers.begin();
- for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
- if ((*metricIt)->getMetricId() == metricId2) {
- break;
- }
- }
- EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
- auto& metricProducer1002 = *metricIt;
- EXPECT_TRUE(metricProducer1002->isActive());
-
- const auto& activation1001 = metricProducer1001->mEventActivationMap.begin()->second;
- EXPECT_EQ(100 * NS_PER_SEC, activation1001->ttl_ns);
- EXPECT_EQ(0, activation1001->start_ns);
- EXPECT_EQ(kNotActive, activation1001->state);
-
- processor2->LoadActiveConfigsFromDisk();
-
- EXPECT_TRUE(metricProducer1001->isActive());
- EXPECT_EQ(timeBase2 + ttl1 - activation1001->ttl_ns, activation1001->start_ns);
- EXPECT_EQ(kActive, activation1001->state);
-}
-
-TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivations) {
- int uid = 1111;
-
- // Create config with 2 metrics:
- // Metric 1: Activate on boot with 2 activations
- // Metric 2: Always active
- StatsdConfig config1;
- config1.set_id(12341);
- config1.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
- auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
- auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
- *config1.add_atom_matcher() = wakelockAcquireMatcher;
- *config1.add_atom_matcher() = screenOnMatcher;
-
- long metricId1 = 1234561;
- long metricId2 = 1234562;
-
- auto countMetric1 = config1.add_count_metric();
- countMetric1->set_id(metricId1);
- countMetric1->set_what(wakelockAcquireMatcher.id());
- countMetric1->set_bucket(FIVE_MINUTES);
-
- auto countMetric2 = config1.add_count_metric();
- countMetric2->set_id(metricId2);
- countMetric2->set_what(wakelockAcquireMatcher.id());
- countMetric2->set_bucket(FIVE_MINUTES);
-
- auto metric1Activation = config1.add_metric_activation();
- metric1Activation->set_metric_id(metricId1);
- metric1Activation->set_activation_type(ACTIVATE_ON_BOOT);
- auto metric1ActivationTrigger1 = metric1Activation->add_event_activation();
- metric1ActivationTrigger1->set_atom_matcher_id(wakelockAcquireMatcher.id());
- metric1ActivationTrigger1->set_ttl_seconds(100);
- auto metric1ActivationTrigger2 = metric1Activation->add_event_activation();
- metric1ActivationTrigger2->set_atom_matcher_id(screenOnMatcher.id());
- metric1ActivationTrigger2->set_ttl_seconds(200);
-
- ConfigKey cfgKey1(uid, 12341);
- long timeBase1 = 1;
- sp<StatsLogProcessor> processor =
- CreateStatsLogProcessor(timeBase1, timeBase1, config1, cfgKey1);
-
- // Metric 1 is not active.
- // Metric 2 is active.
- // {{{---------------------------------------------------------------------------
- EXPECT_EQ(1, processor->mMetricsManagers.size());
- auto it = processor->mMetricsManagers.find(cfgKey1);
- EXPECT_TRUE(it != processor->mMetricsManagers.end());
- auto& metricsManager1 = it->second;
- EXPECT_TRUE(metricsManager1->isActive());
-
- auto metricIt = metricsManager1->mAllMetricProducers.begin();
- for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
- if ((*metricIt)->getMetricId() == metricId1) {
- break;
- }
- }
- EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
- auto& metricProducer1 = *metricIt;
- EXPECT_FALSE(metricProducer1->isActive());
-
- metricIt = metricsManager1->mAllMetricProducers.begin();
- for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
- if ((*metricIt)->getMetricId() == metricId2) {
- break;
- }
- }
- EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
- auto& metricProducer2 = *metricIt;
- EXPECT_TRUE(metricProducer2->isActive());
-
- int i = 0;
- for (; i < metricsManager1->mAllAtomMatchers.size(); i++) {
- if (metricsManager1->mAllAtomMatchers[i]->getId() ==
- metric1ActivationTrigger1->atom_matcher_id()) {
- break;
- }
- }
- const auto& activation1 = metricProducer1->mEventActivationMap.at(i);
- EXPECT_EQ(100 * NS_PER_SEC, activation1->ttl_ns);
- EXPECT_EQ(0, activation1->start_ns);
- EXPECT_EQ(kNotActive, activation1->state);
-
- i = 0;
- for (; i < metricsManager1->mAllAtomMatchers.size(); i++) {
- if (metricsManager1->mAllAtomMatchers[i]->getId() ==
- metric1ActivationTrigger2->atom_matcher_id()) {
- break;
- }
- }
- const auto& activation2 = metricProducer1->mEventActivationMap.at(i);
- EXPECT_EQ(200 * NS_PER_SEC, activation2->ttl_ns);
- EXPECT_EQ(0, activation2->start_ns);
- EXPECT_EQ(kNotActive, activation2->state);
- // }}}------------------------------------------------------------------------------
-
- // Trigger Activation 1 for Metric 1
- std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
- auto event = CreateAcquireWakelockEvent(attributions1, "wl1", 100 + timeBase1);
- processor->OnLogEvent(event.get());
-
- // Metric 1 is not active; Activation 1 set to kActiveOnBoot
- // Metric 2 is active.
- // {{{---------------------------------------------------------------------------
- EXPECT_FALSE(metricProducer1->isActive());
- EXPECT_EQ(0, activation1->start_ns);
- EXPECT_EQ(kActiveOnBoot, activation1->state);
- EXPECT_EQ(0, activation2->start_ns);
- EXPECT_EQ(kNotActive, activation2->state);
-
- EXPECT_TRUE(metricProducer2->isActive());
- // }}}-----------------------------------------------------------------------------
-
- // Simulate shutdown by saving state to disk
- int64_t shutDownTime = timeBase1 + 100 * NS_PER_SEC;
- processor->SaveActiveConfigsToDisk(shutDownTime);
- EXPECT_FALSE(metricProducer1->isActive());
- int64_t ttl1 = metric1ActivationTrigger1->ttl_seconds() * NS_PER_SEC;
-
- // Simulate device restarted state by creating new instance of StatsLogProcessor with the
- // same config.
- long timeBase2 = 1000;
- sp<StatsLogProcessor> processor2 =
- CreateStatsLogProcessor(timeBase2, timeBase2, config1, cfgKey1);
-
- // Metric 1 is not active.
- // Metric 2 is active.
- // {{{---------------------------------------------------------------------------
- EXPECT_EQ(1, processor2->mMetricsManagers.size());
- it = processor2->mMetricsManagers.find(cfgKey1);
- EXPECT_TRUE(it != processor2->mMetricsManagers.end());
- auto& metricsManager1001 = it->second;
- EXPECT_TRUE(metricsManager1001->isActive());
-
- metricIt = metricsManager1001->mAllMetricProducers.begin();
- for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
- if ((*metricIt)->getMetricId() == metricId1) {
- break;
- }
- }
- EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
- auto& metricProducer1001 = *metricIt;
- EXPECT_FALSE(metricProducer1001->isActive());
-
- metricIt = metricsManager1001->mAllMetricProducers.begin();
- for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
- if ((*metricIt)->getMetricId() == metricId2) {
- break;
- }
- }
- EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
- auto& metricProducer1002 = *metricIt;
- EXPECT_TRUE(metricProducer1002->isActive());
-
- i = 0;
- for (; i < metricsManager1001->mAllAtomMatchers.size(); i++) {
- if (metricsManager1001->mAllAtomMatchers[i]->getId() ==
- metric1ActivationTrigger1->atom_matcher_id()) {
- break;
- }
- }
- const auto& activation1001_1 = metricProducer1001->mEventActivationMap.at(i);
- EXPECT_EQ(100 * NS_PER_SEC, activation1001_1->ttl_ns);
- EXPECT_EQ(0, activation1001_1->start_ns);
- EXPECT_EQ(kNotActive, activation1001_1->state);
-
- i = 0;
- for (; i < metricsManager1001->mAllAtomMatchers.size(); i++) {
- if (metricsManager1001->mAllAtomMatchers[i]->getId() ==
- metric1ActivationTrigger2->atom_matcher_id()) {
- break;
- }
- }
-
- const auto& activation1001_2 = metricProducer1001->mEventActivationMap.at(i);
- EXPECT_EQ(200 * NS_PER_SEC, activation1001_2->ttl_ns);
- EXPECT_EQ(0, activation1001_2->start_ns);
- EXPECT_EQ(kNotActive, activation1001_2->state);
- // }}}-----------------------------------------------------------------------------------
-
- // Load saved state from disk.
- processor2->LoadActiveConfigsFromDisk();
-
- // Metric 1 active; Activation 1 is active, Activation 2 is not active
- // Metric 2 is active.
- // {{{---------------------------------------------------------------------------
- EXPECT_TRUE(metricProducer1001->isActive());
- EXPECT_EQ(timeBase2 + ttl1 - activation1001_1->ttl_ns, activation1001_1->start_ns);
- EXPECT_EQ(kActive, activation1001_1->state);
- EXPECT_EQ(0, activation1001_2->start_ns);
- EXPECT_EQ(kNotActive, activation1001_2->state);
-
- EXPECT_TRUE(metricProducer1002->isActive());
- // }}}--------------------------------------------------------------------------------
-
- // Trigger Activation 2 for Metric 1.
- auto screenOnEvent = CreateScreenStateChangedEvent(
- android::view::DISPLAY_STATE_ON,
- timeBase2 + 200
- );
- processor2->OnLogEvent(screenOnEvent.get());
-
- // Metric 1 active; Activation 1 is active, Activation 2 is set to kActiveOnBoot
- // Metric 2 is active.
- // {{{---------------------------------------------------------------------------
- EXPECT_TRUE(metricProducer1001->isActive());
- EXPECT_EQ(timeBase2 + ttl1 - activation1001_1->ttl_ns, activation1001_1->start_ns);
- EXPECT_EQ(kActive, activation1001_1->state);
- EXPECT_EQ(0, activation1001_2->start_ns);
- EXPECT_EQ(kActiveOnBoot, activation1001_2->state);
-
- EXPECT_TRUE(metricProducer1002->isActive());
- // }}}---------------------------------------------------------------------------
-
- // Simulate shutdown by saving state to disk
- shutDownTime = timeBase2 + 50 * NS_PER_SEC;
- processor2->SaveActiveConfigsToDisk(shutDownTime);
- EXPECT_TRUE(metricProducer1001->isActive());
- EXPECT_TRUE(metricProducer1002->isActive());
- ttl1 = timeBase2 + metric1ActivationTrigger1->ttl_seconds() * NS_PER_SEC - shutDownTime;
- int64_t ttl2 = metric1ActivationTrigger2->ttl_seconds() * NS_PER_SEC;
-
- // Simulate device restarted state by creating new instance of StatsLogProcessor with the
- // same config.
- long timeBase3 = timeBase2 + 120 * NS_PER_SEC;
- sp<StatsLogProcessor> processor3 =
- CreateStatsLogProcessor(timeBase3, timeBase3, config1, cfgKey1);
-
- // Metric 1 is not active.
- // Metric 2 is active.
- // {{{---------------------------------------------------------------------------
- EXPECT_EQ(1, processor3->mMetricsManagers.size());
- it = processor3->mMetricsManagers.find(cfgKey1);
- EXPECT_TRUE(it != processor3->mMetricsManagers.end());
- auto& metricsManagerTimeBase3 = it->second;
- EXPECT_TRUE(metricsManagerTimeBase3->isActive());
-
- metricIt = metricsManagerTimeBase3->mAllMetricProducers.begin();
- for (; metricIt != metricsManagerTimeBase3->mAllMetricProducers.end(); metricIt++) {
- if ((*metricIt)->getMetricId() == metricId1) {
- break;
- }
- }
- EXPECT_TRUE(metricIt != metricsManagerTimeBase3->mAllMetricProducers.end());
- auto& metricProducerTimeBase3_1 = *metricIt;
- EXPECT_FALSE(metricProducerTimeBase3_1->isActive());
-
- metricIt = metricsManagerTimeBase3->mAllMetricProducers.begin();
- for (; metricIt != metricsManagerTimeBase3->mAllMetricProducers.end(); metricIt++) {
- if ((*metricIt)->getMetricId() == metricId2) {
- break;
- }
- }
- EXPECT_TRUE(metricIt != metricsManagerTimeBase3->mAllMetricProducers.end());
- auto& metricProducerTimeBase3_2 = *metricIt;
- EXPECT_TRUE(metricProducerTimeBase3_2->isActive());
-
- i = 0;
- for (; i < metricsManagerTimeBase3->mAllAtomMatchers.size(); i++) {
- if (metricsManagerTimeBase3->mAllAtomMatchers[i]->getId() ==
- metric1ActivationTrigger1->atom_matcher_id()) {
- break;
- }
- }
- const auto& activationTimeBase3_1 = metricProducerTimeBase3_1->mEventActivationMap.at(i);
- EXPECT_EQ(100 * NS_PER_SEC, activationTimeBase3_1->ttl_ns);
- EXPECT_EQ(0, activationTimeBase3_1->start_ns);
- EXPECT_EQ(kNotActive, activationTimeBase3_1->state);
-
- i = 0;
- for (; i < metricsManagerTimeBase3->mAllAtomMatchers.size(); i++) {
- if (metricsManagerTimeBase3->mAllAtomMatchers[i]->getId() ==
- metric1ActivationTrigger2->atom_matcher_id()) {
- break;
- }
- }
-
- const auto& activationTimeBase3_2 = metricProducerTimeBase3_1->mEventActivationMap.at(i);
- EXPECT_EQ(200 * NS_PER_SEC, activationTimeBase3_2->ttl_ns);
- EXPECT_EQ(0, activationTimeBase3_2->start_ns);
- EXPECT_EQ(kNotActive, activationTimeBase3_2->state);
-
- EXPECT_TRUE(metricProducerTimeBase3_2->isActive());
- // }}}----------------------------------------------------------------------------------
-
- // Load saved state from disk.
- processor3->LoadActiveConfigsFromDisk();
-
- // Metric 1 active: Activation 1 is active, Activation 2 is active
- // Metric 2 is active.
- // {{{---------------------------------------------------------------------------
- EXPECT_TRUE(metricProducerTimeBase3_1->isActive());
- EXPECT_EQ(timeBase3 + ttl1 - activationTimeBase3_1->ttl_ns, activationTimeBase3_1->start_ns);
- EXPECT_EQ(kActive, activationTimeBase3_1->state);
- EXPECT_EQ(timeBase3 + ttl2 - activationTimeBase3_2->ttl_ns, activationTimeBase3_2->start_ns);
- EXPECT_EQ(kActive, activationTimeBase3_2->state);
-
- EXPECT_TRUE(metricProducerTimeBase3_2->isActive());
- // }}}-------------------------------------------------------------------------------
-
- // Trigger Activation 2 for Metric 1 again.
- screenOnEvent = CreateScreenStateChangedEvent(
- android::view::DISPLAY_STATE_ON,
- timeBase3 + 100 * NS_PER_SEC
- );
- processor3->OnLogEvent(screenOnEvent.get());
-
- // Metric 1 active; Activation 1 is not active, Activation 2 is set to active
- // Metric 2 is active.
- // {{{---------------------------------------------------------------------------
- EXPECT_TRUE(metricProducerTimeBase3_1->isActive());
- EXPECT_EQ(kNotActive, activationTimeBase3_1->state);
- EXPECT_EQ(timeBase3 + ttl2 - activationTimeBase3_2->ttl_ns, activationTimeBase3_2->start_ns);
- EXPECT_EQ(kActive, activationTimeBase3_2->state);
-
- EXPECT_TRUE(metricProducerTimeBase3_2->isActive());
- // }}}---------------------------------------------------------------------------
-
- // Simulate shutdown by saving state to disk.
- shutDownTime = timeBase3 + 500 * NS_PER_SEC;
- processor3->SaveActiveConfigsToDisk(shutDownTime);
- EXPECT_TRUE(metricProducer1001->isActive());
- EXPECT_TRUE(metricProducer1002->isActive());
- ttl1 = timeBase3 + ttl1 - shutDownTime;
- ttl2 = timeBase3 + metric1ActivationTrigger2->ttl_seconds() * NS_PER_SEC - shutDownTime;
-
- // Simulate device restarted state by creating new instance of StatsLogProcessor with the
- // same config.
- long timeBase4 = timeBase3 + 600 * NS_PER_SEC;
- sp<StatsLogProcessor> processor4 =
- CreateStatsLogProcessor(timeBase4, timeBase4, config1, cfgKey1);
-
- // Metric 1 is not active.
- // Metric 2 is active.
- // {{{---------------------------------------------------------------------------
- EXPECT_EQ(1, processor4->mMetricsManagers.size());
- it = processor4->mMetricsManagers.find(cfgKey1);
- EXPECT_TRUE(it != processor4->mMetricsManagers.end());
- auto& metricsManagerTimeBase4 = it->second;
- EXPECT_TRUE(metricsManagerTimeBase4->isActive());
-
- metricIt = metricsManagerTimeBase4->mAllMetricProducers.begin();
- for (; metricIt != metricsManagerTimeBase4->mAllMetricProducers.end(); metricIt++) {
- if ((*metricIt)->getMetricId() == metricId1) {
- break;
- }
- }
- EXPECT_TRUE(metricIt != metricsManagerTimeBase4->mAllMetricProducers.end());
- auto& metricProducerTimeBase4_1 = *metricIt;
- EXPECT_FALSE(metricProducerTimeBase4_1->isActive());
-
- metricIt = metricsManagerTimeBase4->mAllMetricProducers.begin();
- for (; metricIt != metricsManagerTimeBase4->mAllMetricProducers.end(); metricIt++) {
- if ((*metricIt)->getMetricId() == metricId2) {
- break;
- }
- }
- EXPECT_TRUE(metricIt != metricsManagerTimeBase4->mAllMetricProducers.end());
- auto& metricProducerTimeBase4_2 = *metricIt;
- EXPECT_TRUE(metricProducerTimeBase4_2->isActive());
-
- i = 0;
- for (; i < metricsManagerTimeBase4->mAllAtomMatchers.size(); i++) {
- if (metricsManagerTimeBase4->mAllAtomMatchers[i]->getId() ==
- metric1ActivationTrigger1->atom_matcher_id()) {
- break;
- }
- }
- const auto& activationTimeBase4_1 = metricProducerTimeBase4_1->mEventActivationMap.at(i);
- EXPECT_EQ(100 * NS_PER_SEC, activationTimeBase4_1->ttl_ns);
- EXPECT_EQ(0, activationTimeBase4_1->start_ns);
- EXPECT_EQ(kNotActive, activationTimeBase4_1->state);
-
- i = 0;
- for (; i < metricsManagerTimeBase4->mAllAtomMatchers.size(); i++) {
- if (metricsManagerTimeBase4->mAllAtomMatchers[i]->getId() ==
- metric1ActivationTrigger2->atom_matcher_id()) {
- break;
- }
- }
-
- const auto& activationTimeBase4_2 = metricProducerTimeBase4_1->mEventActivationMap.at(i);
- EXPECT_EQ(200 * NS_PER_SEC, activationTimeBase4_2->ttl_ns);
- EXPECT_EQ(0, activationTimeBase4_2->start_ns);
- EXPECT_EQ(kNotActive, activationTimeBase4_2->state);
-
- EXPECT_TRUE(metricProducerTimeBase4_2->isActive());
- // }}}----------------------------------------------------------------------------------
-
- // Load saved state from disk.
- processor4->LoadActiveConfigsFromDisk();
-
- // Metric 1 active: Activation 1 is not active, Activation 2 is not active
- // Metric 2 is active.
- // {{{---------------------------------------------------------------------------
- EXPECT_FALSE(metricProducerTimeBase4_1->isActive());
- EXPECT_EQ(kNotActive, activationTimeBase4_1->state);
- EXPECT_EQ(kNotActive, activationTimeBase4_2->state);
-
- EXPECT_TRUE(metricProducerTimeBase4_2->isActive());
- // }}}-------------------------------------------------------------------------------
-}
-
-TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivationsDifferentActivationTypes) {
- int uid = 1111;
-
- // Create config with 2 metrics:
- // Metric 1: Activate on boot with 2 activations
- // Metric 2: Always active
- StatsdConfig config1;
- config1.set_id(12341);
- config1.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
- auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
- auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
- *config1.add_atom_matcher() = wakelockAcquireMatcher;
- *config1.add_atom_matcher() = screenOnMatcher;
-
- long metricId1 = 1234561;
- long metricId2 = 1234562;
-
- auto countMetric1 = config1.add_count_metric();
- countMetric1->set_id(metricId1);
- countMetric1->set_what(wakelockAcquireMatcher.id());
- countMetric1->set_bucket(FIVE_MINUTES);
-
- auto countMetric2 = config1.add_count_metric();
- countMetric2->set_id(metricId2);
- countMetric2->set_what(wakelockAcquireMatcher.id());
- countMetric2->set_bucket(FIVE_MINUTES);
-
- auto metric1Activation = config1.add_metric_activation();
- metric1Activation->set_metric_id(metricId1);
- metric1Activation->set_activation_type(ACTIVATE_ON_BOOT);
- auto metric1ActivationTrigger1 = metric1Activation->add_event_activation();
- metric1ActivationTrigger1->set_atom_matcher_id(wakelockAcquireMatcher.id());
- metric1ActivationTrigger1->set_ttl_seconds(100);
- auto metric1ActivationTrigger2 = metric1Activation->add_event_activation();
- metric1ActivationTrigger2->set_atom_matcher_id(screenOnMatcher.id());
- metric1ActivationTrigger2->set_ttl_seconds(200);
- metric1ActivationTrigger2->set_activation_type(ACTIVATE_IMMEDIATELY);
-
- ConfigKey cfgKey1(uid, 12341);
- long timeBase1 = 1;
- sp<StatsLogProcessor> processor1 =
- CreateStatsLogProcessor(timeBase1, timeBase1, config1, cfgKey1);
-
- // Metric 1 is not active.
- // Metric 2 is active.
- // {{{---------------------------------------------------------------------------
- EXPECT_EQ(1, processor1->mMetricsManagers.size());
- auto it = processor1->mMetricsManagers.find(cfgKey1);
- EXPECT_TRUE(it != processor1->mMetricsManagers.end());
- auto& metricsManager1 = it->second;
- EXPECT_TRUE(metricsManager1->isActive());
-
- EXPECT_EQ(metricsManager1->mAllMetricProducers.size(), 2);
- // We assume that the index of a MetricProducer within the mAllMetricProducers
- // array follows the order in which metrics are added to the config.
- auto& metricProducer1_1 = metricsManager1->mAllMetricProducers[0];
- EXPECT_EQ(metricProducer1_1->getMetricId(), metricId1);
- EXPECT_FALSE(metricProducer1_1->isActive()); // inactive due to associated MetricActivation
-
- auto& metricProducer1_2 = metricsManager1->mAllMetricProducers[1];
- EXPECT_EQ(metricProducer1_2->getMetricId(), metricId2);
- EXPECT_TRUE(metricProducer1_2->isActive());
-
- EXPECT_EQ(metricProducer1_1->mEventActivationMap.size(), 2);
- // The key in mEventActivationMap is the index of the associated atom matcher. We assume
- // that matchers are indexed in the order that they are added to the config.
- const auto& activation1_1_1 = metricProducer1_1->mEventActivationMap.at(0);
- EXPECT_EQ(100 * NS_PER_SEC, activation1_1_1->ttl_ns);
- EXPECT_EQ(0, activation1_1_1->start_ns);
- EXPECT_EQ(kNotActive, activation1_1_1->state);
- EXPECT_EQ(ACTIVATE_ON_BOOT, activation1_1_1->activationType);
-
- const auto& activation1_1_2 = metricProducer1_1->mEventActivationMap.at(1);
- EXPECT_EQ(200 * NS_PER_SEC, activation1_1_2->ttl_ns);
- EXPECT_EQ(0, activation1_1_2->start_ns);
- EXPECT_EQ(kNotActive, activation1_1_2->state);
- EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation1_1_2->activationType);
- // }}}------------------------------------------------------------------------------
-
- // Trigger Activation 1 for Metric 1
- std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
- auto event = CreateAcquireWakelockEvent(attributions1, "wl1", 100 + timeBase1);
- processor1->OnLogEvent(event.get());
-
- // Metric 1 is not active; Activation 1 set to kActiveOnBoot
- // Metric 2 is active.
- // {{{---------------------------------------------------------------------------
- EXPECT_FALSE(metricProducer1_1->isActive());
- EXPECT_EQ(0, activation1_1_1->start_ns);
- EXPECT_EQ(kActiveOnBoot, activation1_1_1->state);
- EXPECT_EQ(0, activation1_1_2->start_ns);
- EXPECT_EQ(kNotActive, activation1_1_2->state);
-
- EXPECT_TRUE(metricProducer1_2->isActive());
- // }}}-----------------------------------------------------------------------------
-
- // Simulate shutdown by saving state to disk
- int64_t shutDownTime = timeBase1 + 100 * NS_PER_SEC;
- processor1->SaveActiveConfigsToDisk(shutDownTime);
- EXPECT_FALSE(metricProducer1_1->isActive());
-
- // Simulate device restarted state by creating new instance of StatsLogProcessor with the
- // same config.
- long timeBase2 = 1000;
- sp<StatsLogProcessor> processor2 =
- CreateStatsLogProcessor(timeBase2, timeBase2, config1, cfgKey1);
-
- // Metric 1 is not active.
- // Metric 2 is active.
- // {{{---------------------------------------------------------------------------
- EXPECT_EQ(1, processor2->mMetricsManagers.size());
- it = processor2->mMetricsManagers.find(cfgKey1);
- EXPECT_TRUE(it != processor2->mMetricsManagers.end());
- auto& metricsManager2 = it->second;
- EXPECT_TRUE(metricsManager2->isActive());
-
- EXPECT_EQ(metricsManager2->mAllMetricProducers.size(), 2);
- // We assume that the index of a MetricProducer within the mAllMetricProducers
- // array follows the order in which metrics are added to the config.
- auto& metricProducer2_1 = metricsManager2->mAllMetricProducers[0];
- EXPECT_EQ(metricProducer2_1->getMetricId(), metricId1);
- EXPECT_FALSE(metricProducer2_1->isActive());
-
- auto& metricProducer2_2 = metricsManager2->mAllMetricProducers[1];
- EXPECT_EQ(metricProducer2_2->getMetricId(), metricId2);
- EXPECT_TRUE(metricProducer2_2->isActive());
-
- EXPECT_EQ(metricProducer2_1->mEventActivationMap.size(), 2);
- // The key in mEventActivationMap is the index of the associated atom matcher. We assume
- // that matchers are indexed in the order that they are added to the config.
- const auto& activation2_1_1 = metricProducer2_1->mEventActivationMap.at(0);
- EXPECT_EQ(100 * NS_PER_SEC, activation2_1_1->ttl_ns);
- EXPECT_EQ(0, activation2_1_1->start_ns);
- EXPECT_EQ(kNotActive, activation2_1_1->state);
- EXPECT_EQ(ACTIVATE_ON_BOOT, activation2_1_1->activationType);
-
- const auto& activation2_1_2 = metricProducer2_1->mEventActivationMap.at(1);
- EXPECT_EQ(200 * NS_PER_SEC, activation2_1_2->ttl_ns);
- EXPECT_EQ(0, activation2_1_2->start_ns);
- EXPECT_EQ(kNotActive, activation2_1_2->state);
- EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation2_1_2->activationType);
- // }}}-----------------------------------------------------------------------------------
-
- // Load saved state from disk.
- processor2->LoadActiveConfigsFromDisk();
-
- // Metric 1 active; Activation 1 is active, Activation 2 is not active
- // Metric 2 is active.
- // {{{---------------------------------------------------------------------------
- EXPECT_TRUE(metricProducer2_1->isActive());
- int64_t ttl1 = metric1ActivationTrigger1->ttl_seconds() * NS_PER_SEC;
- EXPECT_EQ(timeBase2 + ttl1 - activation2_1_1->ttl_ns, activation2_1_1->start_ns);
- EXPECT_EQ(kActive, activation2_1_1->state);
- EXPECT_EQ(0, activation2_1_2->start_ns);
- EXPECT_EQ(kNotActive, activation2_1_2->state);
-
- EXPECT_TRUE(metricProducer2_2->isActive());
- // }}}--------------------------------------------------------------------------------
-
- // Trigger Activation 2 for Metric 1.
- auto screenOnEvent = CreateScreenStateChangedEvent(
- android::view::DISPLAY_STATE_ON,
- timeBase2 + 200
- );
- processor2->OnLogEvent(screenOnEvent.get());
-
- // Metric 1 active; Activation 1 is active, Activation 2 is active
- // Metric 2 is active.
- // {{{---------------------------------------------------------------------------
- EXPECT_TRUE(metricProducer2_1->isActive());
- EXPECT_EQ(timeBase2 + ttl1 - activation2_1_1->ttl_ns, activation2_1_1->start_ns);
- EXPECT_EQ(kActive, activation2_1_1->state);
- EXPECT_EQ(screenOnEvent->GetElapsedTimestampNs(), activation2_1_2->start_ns);
- EXPECT_EQ(kActive, activation2_1_2->state);
-
- EXPECT_TRUE(metricProducer2_2->isActive());
- // }}}---------------------------------------------------------------------------
-
- // Simulate shutdown by saving state to disk
- shutDownTime = timeBase2 + 50 * NS_PER_SEC;
- processor2->SaveActiveConfigsToDisk(shutDownTime);
- EXPECT_TRUE(metricProducer2_1->isActive());
- EXPECT_TRUE(metricProducer2_2->isActive());
- ttl1 -= shutDownTime - timeBase2;
- int64_t ttl2 = metric1ActivationTrigger2->ttl_seconds() * NS_PER_SEC
- - (shutDownTime - screenOnEvent->GetElapsedTimestampNs());
-
- // Simulate device restarted state by creating new instance of StatsLogProcessor with the
- // same config.
- long timeBase3 = timeBase2 + 120 * NS_PER_SEC;
- sp<StatsLogProcessor> processor3 =
- CreateStatsLogProcessor(timeBase3, timeBase3, config1, cfgKey1);
-
- // Metric 1 is not active.
- // Metric 2 is active.
- // {{{---------------------------------------------------------------------------
- EXPECT_EQ(1, processor3->mMetricsManagers.size());
- it = processor3->mMetricsManagers.find(cfgKey1);
- EXPECT_TRUE(it != processor3->mMetricsManagers.end());
- auto& metricsManager3 = it->second;
- EXPECT_TRUE(metricsManager3->isActive());
-
- EXPECT_EQ(metricsManager3->mAllMetricProducers.size(), 2);
- // We assume that the index of a MetricProducer within the mAllMetricProducers
- // array follows the order in which metrics are added to the config.
- auto& metricProducer3_1 = metricsManager3->mAllMetricProducers[0];
- EXPECT_EQ(metricProducer3_1->getMetricId(), metricId1);
- EXPECT_FALSE(metricProducer3_1->isActive());
-
- auto& metricProducer3_2 = metricsManager3->mAllMetricProducers[1];
- EXPECT_EQ(metricProducer3_2->getMetricId(), metricId2);
- EXPECT_TRUE(metricProducer3_2->isActive());
-
- EXPECT_EQ(metricProducer3_1->mEventActivationMap.size(), 2);
- // The key in mEventActivationMap is the index of the associated atom matcher. We assume
- // that matchers are indexed in the order that they are added to the config.
- const auto& activation3_1_1 = metricProducer3_1->mEventActivationMap.at(0);
- EXPECT_EQ(100 * NS_PER_SEC, activation3_1_1->ttl_ns);
- EXPECT_EQ(0, activation3_1_1->start_ns);
- EXPECT_EQ(kNotActive, activation3_1_1->state);
- EXPECT_EQ(ACTIVATE_ON_BOOT, activation3_1_1->activationType);
-
- const auto& activation3_1_2 = metricProducer3_1->mEventActivationMap.at(1);
- EXPECT_EQ(200 * NS_PER_SEC, activation3_1_2->ttl_ns);
- EXPECT_EQ(0, activation3_1_2->start_ns);
- EXPECT_EQ(kNotActive, activation3_1_2->state);
- EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation3_1_2->activationType);
- // }}}----------------------------------------------------------------------------------
-
- // Load saved state from disk.
- processor3->LoadActiveConfigsFromDisk();
-
- // Metric 1 active: Activation 1 is active, Activation 2 is active
- // Metric 2 is active.
- // {{{---------------------------------------------------------------------------
- EXPECT_TRUE(metricProducer3_1->isActive());
- EXPECT_EQ(timeBase3 + ttl1 - activation3_1_1->ttl_ns, activation3_1_1->start_ns);
- EXPECT_EQ(kActive, activation3_1_1->state);
- EXPECT_EQ(timeBase3 + ttl2 - activation3_1_2->ttl_ns, activation3_1_2->start_ns);
- EXPECT_EQ(kActive, activation3_1_2->state);
-
- EXPECT_TRUE(metricProducer3_2->isActive());
- // }}}-------------------------------------------------------------------------------
-
-
- // Trigger Activation 2 for Metric 1 again.
- screenOnEvent = CreateScreenStateChangedEvent(
- android::view::DISPLAY_STATE_ON,
- timeBase3 + 100 * NS_PER_SEC
- );
- processor3->OnLogEvent(screenOnEvent.get());
-
- // Metric 1 active; Activation 1 is inactive (above screenOnEvent causes ttl1 to expire),
- // Activation 2 is set to active
- // Metric 2 is active.
- // {{{---------------------------------------------------------------------------
- EXPECT_TRUE(metricProducer3_1->isActive());
- EXPECT_EQ(kNotActive, activation3_1_1->state);
- EXPECT_EQ(screenOnEvent->GetElapsedTimestampNs(), activation3_1_2->start_ns);
- EXPECT_EQ(kActive, activation3_1_2->state);
-
- EXPECT_TRUE(metricProducer3_2->isActive());
- // }}}---------------------------------------------------------------------------
-}
-
-TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart) {
- int uid = 9876;
- long configId = 12341;
-
- // Create config with 3 metrics:
- // Metric 1: Activate on 2 activations, 1 on boot, 1 immediate.
- // Metric 2: Activate on 2 activations, 1 on boot, 1 immediate.
- // Metric 3: Always active
- StatsdConfig config1;
- config1.set_id(configId);
- config1.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
- auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
- auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
- auto jobStartMatcher = CreateStartScheduledJobAtomMatcher();
- auto jobFinishMatcher = CreateFinishScheduledJobAtomMatcher();
- *config1.add_atom_matcher() = wakelockAcquireMatcher;
- *config1.add_atom_matcher() = screenOnMatcher;
- *config1.add_atom_matcher() = jobStartMatcher;
- *config1.add_atom_matcher() = jobFinishMatcher;
-
- long metricId1 = 1234561;
- long metricId2 = 1234562;
- long metricId3 = 1234563;
-
- auto countMetric1 = config1.add_count_metric();
- countMetric1->set_id(metricId1);
- countMetric1->set_what(wakelockAcquireMatcher.id());
- countMetric1->set_bucket(FIVE_MINUTES);
-
- auto countMetric2 = config1.add_count_metric();
- countMetric2->set_id(metricId2);
- countMetric2->set_what(wakelockAcquireMatcher.id());
- countMetric2->set_bucket(FIVE_MINUTES);
-
- auto countMetric3 = config1.add_count_metric();
- countMetric3->set_id(metricId3);
- countMetric3->set_what(wakelockAcquireMatcher.id());
- countMetric3->set_bucket(FIVE_MINUTES);
-
- // Metric 1 activates on boot for wakelock acquire, immediately for screen on.
- auto metric1Activation = config1.add_metric_activation();
- metric1Activation->set_metric_id(metricId1);
- auto metric1ActivationTrigger1 = metric1Activation->add_event_activation();
- metric1ActivationTrigger1->set_atom_matcher_id(wakelockAcquireMatcher.id());
- metric1ActivationTrigger1->set_ttl_seconds(100);
- metric1ActivationTrigger1->set_activation_type(ACTIVATE_ON_BOOT);
- auto metric1ActivationTrigger2 = metric1Activation->add_event_activation();
- metric1ActivationTrigger2->set_atom_matcher_id(screenOnMatcher.id());
- metric1ActivationTrigger2->set_ttl_seconds(200);
- metric1ActivationTrigger2->set_activation_type(ACTIVATE_IMMEDIATELY);
-
- // Metric 2 activates on boot for scheduled job start, immediately for scheduled job finish.
- auto metric2Activation = config1.add_metric_activation();
- metric2Activation->set_metric_id(metricId2);
- auto metric2ActivationTrigger1 = metric2Activation->add_event_activation();
- metric2ActivationTrigger1->set_atom_matcher_id(jobStartMatcher.id());
- metric2ActivationTrigger1->set_ttl_seconds(100);
- metric2ActivationTrigger1->set_activation_type(ACTIVATE_ON_BOOT);
- auto metric2ActivationTrigger2 = metric2Activation->add_event_activation();
- metric2ActivationTrigger2->set_atom_matcher_id(jobFinishMatcher.id());
- metric2ActivationTrigger2->set_ttl_seconds(200);
- metric2ActivationTrigger2->set_activation_type(ACTIVATE_IMMEDIATELY);
-
- // Send the config.
- shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
- string serialized = config1.SerializeAsString();
- service->addConfigurationChecked(uid, configId, {serialized.begin(), serialized.end()});
-
- // Make sure the config is stored on disk. Otherwise, we will not reset on system server death.
- StatsdConfig tmpConfig;
- ConfigKey cfgKey1(uid, configId);
- EXPECT_TRUE(StorageManager::readConfigFromDisk(cfgKey1, &tmpConfig));
-
- // Metric 1 is not active.
- // Metric 2 is not active.
- // Metric 3 is active.
- // {{{---------------------------------------------------------------------------
- sp<StatsLogProcessor> processor = service->mProcessor;
- EXPECT_EQ(1, processor->mMetricsManagers.size());
- auto it = processor->mMetricsManagers.find(cfgKey1);
- EXPECT_TRUE(it != processor->mMetricsManagers.end());
- auto& metricsManager1 = it->second;
- EXPECT_TRUE(metricsManager1->isActive());
- EXPECT_EQ(3, metricsManager1->mAllMetricProducers.size());
-
- auto& metricProducer1 = metricsManager1->mAllMetricProducers[0];
- EXPECT_EQ(metricId1, metricProducer1->getMetricId());
- EXPECT_FALSE(metricProducer1->isActive());
-
- auto& metricProducer2 = metricsManager1->mAllMetricProducers[1];
- EXPECT_EQ(metricId2, metricProducer2->getMetricId());
- EXPECT_FALSE(metricProducer2->isActive());
-
- auto& metricProducer3 = metricsManager1->mAllMetricProducers[2];
- EXPECT_EQ(metricId3, metricProducer3->getMetricId());
- EXPECT_TRUE(metricProducer3->isActive());
-
- // Check event activations.
- EXPECT_EQ(metricsManager1->mAllAtomMatchers.size(), 4);
- EXPECT_EQ(metricsManager1->mAllAtomMatchers[0]->getId(),
- metric1ActivationTrigger1->atom_matcher_id());
- const auto& activation1 = metricProducer1->mEventActivationMap.at(0);
- EXPECT_EQ(100 * NS_PER_SEC, activation1->ttl_ns);
- EXPECT_EQ(0, activation1->start_ns);
- EXPECT_EQ(kNotActive, activation1->state);
- EXPECT_EQ(ACTIVATE_ON_BOOT, activation1->activationType);
-
- EXPECT_EQ(metricsManager1->mAllAtomMatchers[1]->getId(),
- metric1ActivationTrigger2->atom_matcher_id());
- const auto& activation2 = metricProducer1->mEventActivationMap.at(1);
- EXPECT_EQ(200 * NS_PER_SEC, activation2->ttl_ns);
- EXPECT_EQ(0, activation2->start_ns);
- EXPECT_EQ(kNotActive, activation2->state);
- EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation2->activationType);
-
- EXPECT_EQ(metricsManager1->mAllAtomMatchers[2]->getId(),
- metric2ActivationTrigger1->atom_matcher_id());
- const auto& activation3 = metricProducer2->mEventActivationMap.at(2);
- EXPECT_EQ(100 * NS_PER_SEC, activation3->ttl_ns);
- EXPECT_EQ(0, activation3->start_ns);
- EXPECT_EQ(kNotActive, activation3->state);
- EXPECT_EQ(ACTIVATE_ON_BOOT, activation3->activationType);
-
- EXPECT_EQ(metricsManager1->mAllAtomMatchers[3]->getId(),
- metric2ActivationTrigger2->atom_matcher_id());
- const auto& activation4 = metricProducer2->mEventActivationMap.at(3);
- EXPECT_EQ(200 * NS_PER_SEC, activation4->ttl_ns);
- EXPECT_EQ(0, activation4->start_ns);
- EXPECT_EQ(kNotActive, activation4->state);
- EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation4->activationType);
- // }}}------------------------------------------------------------------------------
-
- // Trigger Activation 1 for Metric 1. Should activate on boot.
- // Trigger Activation 4 for Metric 2. Should activate immediately.
- long configAddedTimeNs = metricsManager1->mLastReportTimeNs;
- std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
- auto event = CreateAcquireWakelockEvent(attributions1, "wl1", 1 + configAddedTimeNs);
- processor->OnLogEvent(event.get());
-
- event = CreateFinishScheduledJobEvent(attributions1, "finish1", 2 + configAddedTimeNs);
- processor->OnLogEvent(event.get());
-
- // Metric 1 is not active; Activation 1 set to kActiveOnBoot
- // Metric 2 is active. Activation 4 set to kActive
- // Metric 3 is active.
- // {{{---------------------------------------------------------------------------
- EXPECT_FALSE(metricProducer1->isActive());
- EXPECT_EQ(0, activation1->start_ns);
- EXPECT_EQ(kActiveOnBoot, activation1->state);
- EXPECT_EQ(0, activation2->start_ns);
- EXPECT_EQ(kNotActive, activation2->state);
-
- EXPECT_TRUE(metricProducer2->isActive());
- EXPECT_EQ(0, activation3->start_ns);
- EXPECT_EQ(kNotActive, activation3->state);
- EXPECT_EQ(2 + configAddedTimeNs, activation4->start_ns);
- EXPECT_EQ(kActive, activation4->state);
-
- EXPECT_TRUE(metricProducer3->isActive());
- // }}}-----------------------------------------------------------------------------
-
- // Can't fake time with StatsService.
- // Lets get a time close to the system server death time and make sure it's sane.
- int64_t approximateSystemServerDeath = getElapsedRealtimeNs();
- EXPECT_TRUE(approximateSystemServerDeath > 2 + configAddedTimeNs);
- EXPECT_TRUE(approximateSystemServerDeath < NS_PER_SEC + configAddedTimeNs);
-
- // System server dies.
- service->statsCompanionServiceDiedImpl();
-
- // We should have a new metrics manager. Lets get it and ensure activation status is restored.
- // {{{---------------------------------------------------------------------------
- EXPECT_EQ(1, processor->mMetricsManagers.size());
- it = processor->mMetricsManagers.find(cfgKey1);
- EXPECT_TRUE(it != processor->mMetricsManagers.end());
- auto& metricsManager2 = it->second;
- EXPECT_TRUE(metricsManager2->isActive());
- EXPECT_EQ(3, metricsManager2->mAllMetricProducers.size());
-
- auto& metricProducer1001 = metricsManager2->mAllMetricProducers[0];
- EXPECT_EQ(metricId1, metricProducer1001->getMetricId());
- EXPECT_FALSE(metricProducer1001->isActive());
-
- auto& metricProducer1002 = metricsManager2->mAllMetricProducers[1];
- EXPECT_EQ(metricId2, metricProducer1002->getMetricId());
- EXPECT_TRUE(metricProducer1002->isActive());
-
- auto& metricProducer1003 = metricsManager2->mAllMetricProducers[2];
- EXPECT_EQ(metricId3, metricProducer1003->getMetricId());
- EXPECT_TRUE(metricProducer1003->isActive());
-
- // Check event activations.
- // Activation 1 is kActiveOnBoot.
- // Activation 2 and 3 are not active.
- // Activation 4 is active.
- EXPECT_EQ(metricsManager2->mAllAtomMatchers.size(), 4);
- EXPECT_EQ(metricsManager2->mAllAtomMatchers[0]->getId(),
- metric1ActivationTrigger1->atom_matcher_id());
- const auto& activation1001 = metricProducer1001->mEventActivationMap.at(0);
- EXPECT_EQ(100 * NS_PER_SEC, activation1001->ttl_ns);
- EXPECT_EQ(0, activation1001->start_ns);
- EXPECT_EQ(kActiveOnBoot, activation1001->state);
- EXPECT_EQ(ACTIVATE_ON_BOOT, activation1001->activationType);
-
- EXPECT_EQ(metricsManager2->mAllAtomMatchers[1]->getId(),
- metric1ActivationTrigger2->atom_matcher_id());
- const auto& activation1002 = metricProducer1001->mEventActivationMap.at(1);
- EXPECT_EQ(200 * NS_PER_SEC, activation1002->ttl_ns);
- EXPECT_EQ(0, activation1002->start_ns);
- EXPECT_EQ(kNotActive, activation1002->state);
- EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation1002->activationType);
-
- EXPECT_EQ(metricsManager2->mAllAtomMatchers[2]->getId(),
- metric2ActivationTrigger1->atom_matcher_id());
- const auto& activation1003 = metricProducer1002->mEventActivationMap.at(2);
- EXPECT_EQ(100 * NS_PER_SEC, activation1003->ttl_ns);
- EXPECT_EQ(0, activation1003->start_ns);
- EXPECT_EQ(kNotActive, activation1003->state);
- EXPECT_EQ(ACTIVATE_ON_BOOT, activation1003->activationType);
-
- EXPECT_EQ(metricsManager2->mAllAtomMatchers[3]->getId(),
- metric2ActivationTrigger2->atom_matcher_id());
- const auto& activation1004 = metricProducer1002->mEventActivationMap.at(3);
- EXPECT_EQ(200 * NS_PER_SEC, activation1004->ttl_ns);
- EXPECT_EQ(2 + configAddedTimeNs, activation1004->start_ns);
- EXPECT_EQ(kActive, activation1004->state);
- EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation1004->activationType);
- // }}}------------------------------------------------------------------------------
-
- // Clear the data stored on disk as a result of the system server death.
- vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey1, configAddedTimeNs + NS_PER_SEC, false, true,
- ADB_DUMP, FAST, &buffer);
-}
+// TODO(b/149590301): Update this test to use new socket schema.
+//TEST(StatsLogProcessorTest, TestOnDumpReportEraseData) {
+// // Setup a simple config.
+// StatsdConfig config;
+// config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+// auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
+// *config.add_atom_matcher() = wakelockAcquireMatcher;
+//
+// auto countMetric = config.add_count_metric();
+// countMetric->set_id(123456);
+// countMetric->set_what(wakelockAcquireMatcher.id());
+// countMetric->set_bucket(FIVE_MINUTES);
+//
+// ConfigKey cfgKey;
+// sp<StatsLogProcessor> processor = CreateStatsLogProcessor(1, 1, config, cfgKey);
+//
+// std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
+// auto event = CreateAcquireWakelockEvent(attributions1, "wl1", 2);
+// processor->OnLogEvent(event.get());
+//
+// vector<uint8_t> bytes;
+// ConfigMetricsReportList output;
+//
+// // Dump report WITHOUT erasing data.
+// processor->onDumpReport(cfgKey, 3, true, false /* Do NOT erase data. */, ADB_DUMP, FAST, &bytes);
+// output.ParseFromArray(bytes.data(), bytes.size());
+// EXPECT_EQ(output.reports_size(), 1);
+// EXPECT_EQ(output.reports(0).metrics_size(), 1);
+// EXPECT_EQ(output.reports(0).metrics(0).count_metrics().data_size(), 1);
+//
+// // Dump report WITH erasing data. There should be data since we didn't previously erase it.
+// processor->onDumpReport(cfgKey, 4, true, true /* DO erase data. */, ADB_DUMP, FAST, &bytes);
+// output.ParseFromArray(bytes.data(), bytes.size());
+// EXPECT_EQ(output.reports_size(), 1);
+// EXPECT_EQ(output.reports(0).metrics_size(), 1);
+// EXPECT_EQ(output.reports(0).metrics(0).count_metrics().data_size(), 1);
+//
+// // Dump report again. There should be no data since we erased it.
+// processor->onDumpReport(cfgKey, 5, true, true /* DO erase data. */, ADB_DUMP, FAST, &bytes);
+// output.ParseFromArray(bytes.data(), bytes.size());
+// // We don't care whether statsd has a report, as long as it has no count metrics in it.
+// bool noData = output.reports_size() == 0
+// || output.reports(0).metrics_size() == 0
+// || output.reports(0).metrics(0).count_metrics().data_size() == 0;
+// EXPECT_TRUE(noData);
+//}
+//
+//TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead) {
+// int uid = 1111;
+//
+// // Setup a simple config, no activation
+// StatsdConfig config1;
+// int64_t cfgId1 = 12341;
+// config1.set_id(cfgId1);
+// config1.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+// auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
+// *config1.add_atom_matcher() = wakelockAcquireMatcher;
+//
+// long metricId1 = 1234561;
+// long metricId2 = 1234562;
+// auto countMetric1 = config1.add_count_metric();
+// countMetric1->set_id(metricId1);
+// countMetric1->set_what(wakelockAcquireMatcher.id());
+// countMetric1->set_bucket(FIVE_MINUTES);
+//
+// auto countMetric2 = config1.add_count_metric();
+// countMetric2->set_id(metricId2);
+// countMetric2->set_what(wakelockAcquireMatcher.id());
+// countMetric2->set_bucket(FIVE_MINUTES);
+//
+// ConfigKey cfgKey1(uid, cfgId1);
+//
+// // Add another config, with two metrics, one with activation
+// StatsdConfig config2;
+// int64_t cfgId2 = 12342;
+// config2.set_id(cfgId2);
+// config2.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+// *config2.add_atom_matcher() = wakelockAcquireMatcher;
+//
+// long metricId3 = 1234561;
+// long metricId4 = 1234562;
+//
+// auto countMetric3 = config2.add_count_metric();
+// countMetric3->set_id(metricId3);
+// countMetric3->set_what(wakelockAcquireMatcher.id());
+// countMetric3->set_bucket(FIVE_MINUTES);
+//
+// auto countMetric4 = config2.add_count_metric();
+// countMetric4->set_id(metricId4);
+// countMetric4->set_what(wakelockAcquireMatcher.id());
+// countMetric4->set_bucket(FIVE_MINUTES);
+//
+// auto metric3Activation = config2.add_metric_activation();
+// metric3Activation->set_metric_id(metricId3);
+// metric3Activation->set_activation_type(ACTIVATE_IMMEDIATELY);
+// auto metric3ActivationTrigger = metric3Activation->add_event_activation();
+// metric3ActivationTrigger->set_atom_matcher_id(wakelockAcquireMatcher.id());
+// metric3ActivationTrigger->set_ttl_seconds(100);
+//
+// ConfigKey cfgKey2(uid, cfgId2);
+//
+// // Add another config, with two metrics, both with activations
+// StatsdConfig config3;
+// int64_t cfgId3 = 12343;
+// config3.set_id(cfgId3);
+// config3.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+// *config3.add_atom_matcher() = wakelockAcquireMatcher;
+//
+// long metricId5 = 1234565;
+// long metricId6 = 1234566;
+// auto countMetric5 = config3.add_count_metric();
+// countMetric5->set_id(metricId5);
+// countMetric5->set_what(wakelockAcquireMatcher.id());
+// countMetric5->set_bucket(FIVE_MINUTES);
+//
+// auto countMetric6 = config3.add_count_metric();
+// countMetric6->set_id(metricId6);
+// countMetric6->set_what(wakelockAcquireMatcher.id());
+// countMetric6->set_bucket(FIVE_MINUTES);
+//
+// auto metric5Activation = config3.add_metric_activation();
+// metric5Activation->set_metric_id(metricId5);
+// metric5Activation->set_activation_type(ACTIVATE_IMMEDIATELY);
+// auto metric5ActivationTrigger = metric5Activation->add_event_activation();
+// metric5ActivationTrigger->set_atom_matcher_id(wakelockAcquireMatcher.id());
+// metric5ActivationTrigger->set_ttl_seconds(100);
+//
+// auto metric6Activation = config3.add_metric_activation();
+// metric6Activation->set_metric_id(metricId6);
+// metric6Activation->set_activation_type(ACTIVATE_IMMEDIATELY);
+// auto metric6ActivationTrigger = metric6Activation->add_event_activation();
+// metric6ActivationTrigger->set_atom_matcher_id(wakelockAcquireMatcher.id());
+// metric6ActivationTrigger->set_ttl_seconds(200);
+//
+// ConfigKey cfgKey3(uid, cfgId3);
+//
+// sp<UidMap> m = new UidMap();
+// sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+// sp<AlarmMonitor> anomalyAlarmMonitor;
+// sp<AlarmMonitor> subscriberAlarmMonitor;
+// vector<int64_t> activeConfigsBroadcast;
+//
+// long timeBase1 = 1;
+// int broadcastCount = 0;
+// StatsLogProcessor processor(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor,
+// timeBase1, [](const ConfigKey& key) { return true; },
+// [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid,
+// const vector<int64_t>& activeConfigs) {
+// broadcastCount++;
+// EXPECT_EQ(broadcastUid, uid);
+// activeConfigsBroadcast.clear();
+// activeConfigsBroadcast.insert(activeConfigsBroadcast.end(),
+// activeConfigs.begin(), activeConfigs.end());
+// return true;
+// });
+//
+// processor.OnConfigUpdated(1, cfgKey1, config1);
+// processor.OnConfigUpdated(2, cfgKey2, config2);
+// processor.OnConfigUpdated(3, cfgKey3, config3);
+//
+// EXPECT_EQ(3, processor.mMetricsManagers.size());
+//
+// // Expect the first config and both metrics in it to be active.
+// auto it = processor.mMetricsManagers.find(cfgKey1);
+// EXPECT_TRUE(it != processor.mMetricsManagers.end());
+// auto& metricsManager1 = it->second;
+// EXPECT_TRUE(metricsManager1->isActive());
+//
+// auto metricIt = metricsManager1->mAllMetricProducers.begin();
+// for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
+// if ((*metricIt)->getMetricId() == metricId1) {
+// break;
+// }
+// }
+// EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
+// auto& metricProducer1 = *metricIt;
+// EXPECT_TRUE(metricProducer1->isActive());
+//
+// metricIt = metricsManager1->mAllMetricProducers.begin();
+// for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
+// if ((*metricIt)->getMetricId() == metricId2) {
+// break;
+// }
+// }
+// EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
+// auto& metricProducer2 = *metricIt;
+// EXPECT_TRUE(metricProducer2->isActive());
+//
+// // Expect config 2 to be active. Metric 3 shouldn't be active, metric 4 should be active.
+// it = processor.mMetricsManagers.find(cfgKey2);
+// EXPECT_TRUE(it != processor.mMetricsManagers.end());
+// auto& metricsManager2 = it->second;
+// EXPECT_TRUE(metricsManager2->isActive());
+//
+// metricIt = metricsManager2->mAllMetricProducers.begin();
+// for (; metricIt != metricsManager2->mAllMetricProducers.end(); metricIt++) {
+// if ((*metricIt)->getMetricId() == metricId3) {
+// break;
+// }
+// }
+// EXPECT_TRUE(metricIt != metricsManager2->mAllMetricProducers.end());
+// auto& metricProducer3 = *metricIt;
+// EXPECT_FALSE(metricProducer3->isActive());
+//
+// metricIt = metricsManager2->mAllMetricProducers.begin();
+// for (; metricIt != metricsManager2->mAllMetricProducers.end(); metricIt++) {
+// if ((*metricIt)->getMetricId() == metricId4) {
+// break;
+// }
+// }
+// EXPECT_TRUE(metricIt != metricsManager2->mAllMetricProducers.end());
+// auto& metricProducer4 = *metricIt;
+// EXPECT_TRUE(metricProducer4->isActive());
+//
+// // Expect the third config and both metrics in it to be inactive.
+// it = processor.mMetricsManagers.find(cfgKey3);
+// EXPECT_TRUE(it != processor.mMetricsManagers.end());
+// auto& metricsManager3 = it->second;
+// EXPECT_FALSE(metricsManager3->isActive());
+//
+// metricIt = metricsManager3->mAllMetricProducers.begin();
+// for (; metricIt != metricsManager2->mAllMetricProducers.end(); metricIt++) {
+// if ((*metricIt)->getMetricId() == metricId5) {
+// break;
+// }
+// }
+// EXPECT_TRUE(metricIt != metricsManager3->mAllMetricProducers.end());
+// auto& metricProducer5 = *metricIt;
+// EXPECT_FALSE(metricProducer5->isActive());
+//
+// metricIt = metricsManager3->mAllMetricProducers.begin();
+// for (; metricIt != metricsManager3->mAllMetricProducers.end(); metricIt++) {
+// if ((*metricIt)->getMetricId() == metricId6) {
+// break;
+// }
+// }
+// EXPECT_TRUE(metricIt != metricsManager3->mAllMetricProducers.end());
+// auto& metricProducer6 = *metricIt;
+// EXPECT_FALSE(metricProducer6->isActive());
+//
+// // No broadcast for active configs should have happened yet.
+// EXPECT_EQ(broadcastCount, 0);
+//
+// // Activate all 3 metrics that were not active.
+// std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
+// auto event = CreateAcquireWakelockEvent(attributions1, "wl1", 100 + timeBase1);
+// processor.OnLogEvent(event.get());
+//
+// // Assert that all 3 configs are active.
+// EXPECT_TRUE(metricsManager1->isActive());
+// EXPECT_TRUE(metricsManager2->isActive());
+// EXPECT_TRUE(metricsManager3->isActive());
+//
+// // A broadcast should have happened, and all 3 configs should be active in the broadcast.
+// EXPECT_EQ(broadcastCount, 1);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 3);
+// EXPECT_TRUE(std::find(activeConfigsBroadcast.begin(), activeConfigsBroadcast.end(), cfgId1)
+// != activeConfigsBroadcast.end());
+// EXPECT_TRUE(std::find(activeConfigsBroadcast.begin(), activeConfigsBroadcast.end(), cfgId2)
+// != activeConfigsBroadcast.end());
+// EXPECT_TRUE(std::find(activeConfigsBroadcast.begin(), activeConfigsBroadcast.end(), cfgId3)
+// != activeConfigsBroadcast.end());
+//
+// // When we shut down, metrics 3 & 5 have 100ns remaining, metric 6 has 100s + 100ns.
+// int64_t shutDownTime = timeBase1 + 100 * NS_PER_SEC;
+// processor.SaveActiveConfigsToDisk(shutDownTime);
+// const int64_t ttl3 = event->GetElapsedTimestampNs() +
+// metric3ActivationTrigger->ttl_seconds() * NS_PER_SEC - shutDownTime;
+// const int64_t ttl5 = event->GetElapsedTimestampNs() +
+// metric5ActivationTrigger->ttl_seconds() * NS_PER_SEC - shutDownTime;
+// const int64_t ttl6 = event->GetElapsedTimestampNs() +
+// metric6ActivationTrigger->ttl_seconds() * NS_PER_SEC - shutDownTime;
+//
+// // Create a second StatsLogProcessor and push the same 3 configs.
+// long timeBase2 = 1000;
+// sp<StatsLogProcessor> processor2 =
+// CreateStatsLogProcessor(timeBase2, timeBase2, config1, cfgKey1);
+// processor2->OnConfigUpdated(timeBase2, cfgKey2, config2);
+// processor2->OnConfigUpdated(timeBase2, cfgKey3, config3);
+//
+// EXPECT_EQ(3, processor2->mMetricsManagers.size());
+//
+// // First config and both metrics are active.
+// it = processor2->mMetricsManagers.find(cfgKey1);
+// EXPECT_TRUE(it != processor2->mMetricsManagers.end());
+// auto& metricsManager1001 = it->second;
+// EXPECT_TRUE(metricsManager1001->isActive());
+//
+// metricIt = metricsManager1001->mAllMetricProducers.begin();
+// for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
+// if ((*metricIt)->getMetricId() == metricId1) {
+// break;
+// }
+// }
+// EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
+// auto& metricProducer1001 = *metricIt;
+// EXPECT_TRUE(metricProducer1001->isActive());
+//
+// metricIt = metricsManager1001->mAllMetricProducers.begin();
+// for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
+// if ((*metricIt)->getMetricId() == metricId2) {
+// break;
+// }
+// }
+// EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
+// auto& metricProducer1002 = *metricIt;
+// EXPECT_TRUE(metricProducer1002->isActive());
+//
+// // Second config is active. Metric 3 is inactive, metric 4 is active.
+// it = processor2->mMetricsManagers.find(cfgKey2);
+// EXPECT_TRUE(it != processor2->mMetricsManagers.end());
+// auto& metricsManager1002 = it->second;
+// EXPECT_TRUE(metricsManager1002->isActive());
+//
+// metricIt = metricsManager1002->mAllMetricProducers.begin();
+// for (; metricIt != metricsManager1002->mAllMetricProducers.end(); metricIt++) {
+// if ((*metricIt)->getMetricId() == metricId3) {
+// break;
+// }
+// }
+// EXPECT_TRUE(metricIt != metricsManager1002->mAllMetricProducers.end());
+// auto& metricProducer1003 = *metricIt;
+// EXPECT_FALSE(metricProducer1003->isActive());
+//
+// metricIt = metricsManager1002->mAllMetricProducers.begin();
+// for (; metricIt != metricsManager1002->mAllMetricProducers.end(); metricIt++) {
+// if ((*metricIt)->getMetricId() == metricId4) {
+// break;
+// }
+// }
+// EXPECT_TRUE(metricIt != metricsManager1002->mAllMetricProducers.end());
+// auto& metricProducer1004 = *metricIt;
+// EXPECT_TRUE(metricProducer1004->isActive());
+//
+// // Config 3 is inactive. both metrics are inactive.
+// it = processor2->mMetricsManagers.find(cfgKey3);
+// EXPECT_TRUE(it != processor2->mMetricsManagers.end());
+// auto& metricsManager1003 = it->second;
+// EXPECT_FALSE(metricsManager1003->isActive());
+// EXPECT_EQ(2, metricsManager1003->mAllMetricProducers.size());
+//
+// metricIt = metricsManager1003->mAllMetricProducers.begin();
+// for (; metricIt != metricsManager1002->mAllMetricProducers.end(); metricIt++) {
+// if ((*metricIt)->getMetricId() == metricId5) {
+// break;
+// }
+// }
+// EXPECT_TRUE(metricIt != metricsManager1003->mAllMetricProducers.end());
+// auto& metricProducer1005 = *metricIt;
+// EXPECT_FALSE(metricProducer1005->isActive());
+//
+// metricIt = metricsManager1003->mAllMetricProducers.begin();
+// for (; metricIt != metricsManager1003->mAllMetricProducers.end(); metricIt++) {
+// if ((*metricIt)->getMetricId() == metricId6) {
+// break;
+// }
+// }
+// EXPECT_TRUE(metricIt != metricsManager1003->mAllMetricProducers.end());
+// auto& metricProducer1006 = *metricIt;
+// EXPECT_FALSE(metricProducer1006->isActive());
+//
+// // Assert that all 3 metrics with activation are inactive and that the ttls were properly set.
+// EXPECT_FALSE(metricProducer1003->isActive());
+// const auto& activation1003 = metricProducer1003->mEventActivationMap.begin()->second;
+// EXPECT_EQ(100 * NS_PER_SEC, activation1003->ttl_ns);
+// EXPECT_EQ(0, activation1003->start_ns);
+// EXPECT_FALSE(metricProducer1005->isActive());
+// const auto& activation1005 = metricProducer1005->mEventActivationMap.begin()->second;
+// EXPECT_EQ(100 * NS_PER_SEC, activation1005->ttl_ns);
+// EXPECT_EQ(0, activation1005->start_ns);
+// EXPECT_FALSE(metricProducer1006->isActive());
+// const auto& activation1006 = metricProducer1006->mEventActivationMap.begin()->second;
+// EXPECT_EQ(200 * NS_PER_SEC, activation1006->ttl_ns);
+// EXPECT_EQ(0, activation1006->start_ns);
+//
+// processor2->LoadActiveConfigsFromDisk();
+//
+// // After loading activations from disk, assert that all 3 metrics are active.
+// EXPECT_TRUE(metricProducer1003->isActive());
+// EXPECT_EQ(timeBase2 + ttl3 - activation1003->ttl_ns, activation1003->start_ns);
+// EXPECT_TRUE(metricProducer1005->isActive());
+// EXPECT_EQ(timeBase2 + ttl5 - activation1005->ttl_ns, activation1005->start_ns);
+// EXPECT_TRUE(metricProducer1006->isActive());
+// EXPECT_EQ(timeBase2 + ttl6 - activation1006->ttl_ns, activation1003->start_ns);
+//
+// // Make sure no more broadcasts have happened.
+// EXPECT_EQ(broadcastCount, 1);
+//}
+//
+//TEST(StatsLogProcessorTest, TestActivationOnBoot) {
+// int uid = 1111;
+//
+// StatsdConfig config1;
+// config1.set_id(12341);
+// config1.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+// auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
+// *config1.add_atom_matcher() = wakelockAcquireMatcher;
+//
+// long metricId1 = 1234561;
+// long metricId2 = 1234562;
+// auto countMetric1 = config1.add_count_metric();
+// countMetric1->set_id(metricId1);
+// countMetric1->set_what(wakelockAcquireMatcher.id());
+// countMetric1->set_bucket(FIVE_MINUTES);
+//
+// auto countMetric2 = config1.add_count_metric();
+// countMetric2->set_id(metricId2);
+// countMetric2->set_what(wakelockAcquireMatcher.id());
+// countMetric2->set_bucket(FIVE_MINUTES);
+//
+// auto metric1Activation = config1.add_metric_activation();
+// metric1Activation->set_metric_id(metricId1);
+// metric1Activation->set_activation_type(ACTIVATE_ON_BOOT);
+// auto metric1ActivationTrigger = metric1Activation->add_event_activation();
+// metric1ActivationTrigger->set_atom_matcher_id(wakelockAcquireMatcher.id());
+// metric1ActivationTrigger->set_ttl_seconds(100);
+//
+// ConfigKey cfgKey1(uid, 12341);
+// long timeBase1 = 1;
+// sp<StatsLogProcessor> processor =
+// CreateStatsLogProcessor(timeBase1, timeBase1, config1, cfgKey1);
+//
+// EXPECT_EQ(1, processor->mMetricsManagers.size());
+// auto it = processor->mMetricsManagers.find(cfgKey1);
+// EXPECT_TRUE(it != processor->mMetricsManagers.end());
+// auto& metricsManager1 = it->second;
+// EXPECT_TRUE(metricsManager1->isActive());
+//
+// auto metricIt = metricsManager1->mAllMetricProducers.begin();
+// for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
+// if ((*metricIt)->getMetricId() == metricId1) {
+// break;
+// }
+// }
+// EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
+// auto& metricProducer1 = *metricIt;
+// EXPECT_FALSE(metricProducer1->isActive());
+//
+// metricIt = metricsManager1->mAllMetricProducers.begin();
+// for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
+// if ((*metricIt)->getMetricId() == metricId2) {
+// break;
+// }
+// }
+// EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
+// auto& metricProducer2 = *metricIt;
+// EXPECT_TRUE(metricProducer2->isActive());
+//
+// const auto& activation1 = metricProducer1->mEventActivationMap.begin()->second;
+// EXPECT_EQ(100 * NS_PER_SEC, activation1->ttl_ns);
+// EXPECT_EQ(0, activation1->start_ns);
+// EXPECT_EQ(kNotActive, activation1->state);
+//
+// std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
+// auto event = CreateAcquireWakelockEvent(attributions1, "wl1", 100 + timeBase1);
+// processor->OnLogEvent(event.get());
+//
+// EXPECT_FALSE(metricProducer1->isActive());
+// EXPECT_EQ(0, activation1->start_ns);
+// EXPECT_EQ(kActiveOnBoot, activation1->state);
+//
+// int64_t shutDownTime = timeBase1 + 100 * NS_PER_SEC;
+// processor->SaveActiveConfigsToDisk(shutDownTime);
+// EXPECT_FALSE(metricProducer1->isActive());
+// const int64_t ttl1 = metric1ActivationTrigger->ttl_seconds() * NS_PER_SEC;
+//
+// long timeBase2 = 1000;
+// sp<StatsLogProcessor> processor2 =
+// CreateStatsLogProcessor(timeBase2, timeBase2, config1, cfgKey1);
+//
+// EXPECT_EQ(1, processor2->mMetricsManagers.size());
+// it = processor2->mMetricsManagers.find(cfgKey1);
+// EXPECT_TRUE(it != processor2->mMetricsManagers.end());
+// auto& metricsManager1001 = it->second;
+// EXPECT_TRUE(metricsManager1001->isActive());
+//
+// metricIt = metricsManager1001->mAllMetricProducers.begin();
+// for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
+// if ((*metricIt)->getMetricId() == metricId1) {
+// break;
+// }
+// }
+// EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
+// auto& metricProducer1001 = *metricIt;
+// EXPECT_FALSE(metricProducer1001->isActive());
+//
+// metricIt = metricsManager1001->mAllMetricProducers.begin();
+// for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
+// if ((*metricIt)->getMetricId() == metricId2) {
+// break;
+// }
+// }
+// EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
+// auto& metricProducer1002 = *metricIt;
+// EXPECT_TRUE(metricProducer1002->isActive());
+//
+// const auto& activation1001 = metricProducer1001->mEventActivationMap.begin()->second;
+// EXPECT_EQ(100 * NS_PER_SEC, activation1001->ttl_ns);
+// EXPECT_EQ(0, activation1001->start_ns);
+// EXPECT_EQ(kNotActive, activation1001->state);
+//
+// processor2->LoadActiveConfigsFromDisk();
+//
+// EXPECT_TRUE(metricProducer1001->isActive());
+// EXPECT_EQ(timeBase2 + ttl1 - activation1001->ttl_ns, activation1001->start_ns);
+// EXPECT_EQ(kActive, activation1001->state);
+//}
+//
+//TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivations) {
+// int uid = 1111;
+//
+// // Create config with 2 metrics:
+// // Metric 1: Activate on boot with 2 activations
+// // Metric 2: Always active
+// StatsdConfig config1;
+// config1.set_id(12341);
+// config1.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+// auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
+// auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
+// *config1.add_atom_matcher() = wakelockAcquireMatcher;
+// *config1.add_atom_matcher() = screenOnMatcher;
+//
+// long metricId1 = 1234561;
+// long metricId2 = 1234562;
+//
+// auto countMetric1 = config1.add_count_metric();
+// countMetric1->set_id(metricId1);
+// countMetric1->set_what(wakelockAcquireMatcher.id());
+// countMetric1->set_bucket(FIVE_MINUTES);
+//
+// auto countMetric2 = config1.add_count_metric();
+// countMetric2->set_id(metricId2);
+// countMetric2->set_what(wakelockAcquireMatcher.id());
+// countMetric2->set_bucket(FIVE_MINUTES);
+//
+// auto metric1Activation = config1.add_metric_activation();
+// metric1Activation->set_metric_id(metricId1);
+// metric1Activation->set_activation_type(ACTIVATE_ON_BOOT);
+// auto metric1ActivationTrigger1 = metric1Activation->add_event_activation();
+// metric1ActivationTrigger1->set_atom_matcher_id(wakelockAcquireMatcher.id());
+// metric1ActivationTrigger1->set_ttl_seconds(100);
+// auto metric1ActivationTrigger2 = metric1Activation->add_event_activation();
+// metric1ActivationTrigger2->set_atom_matcher_id(screenOnMatcher.id());
+// metric1ActivationTrigger2->set_ttl_seconds(200);
+//
+// ConfigKey cfgKey1(uid, 12341);
+// long timeBase1 = 1;
+// sp<StatsLogProcessor> processor =
+// CreateStatsLogProcessor(timeBase1, timeBase1, config1, cfgKey1);
+//
+// // Metric 1 is not active.
+// // Metric 2 is active.
+// // {{{---------------------------------------------------------------------------
+// EXPECT_EQ(1, processor->mMetricsManagers.size());
+// auto it = processor->mMetricsManagers.find(cfgKey1);
+// EXPECT_TRUE(it != processor->mMetricsManagers.end());
+// auto& metricsManager1 = it->second;
+// EXPECT_TRUE(metricsManager1->isActive());
+//
+// auto metricIt = metricsManager1->mAllMetricProducers.begin();
+// for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
+// if ((*metricIt)->getMetricId() == metricId1) {
+// break;
+// }
+// }
+// EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
+// auto& metricProducer1 = *metricIt;
+// EXPECT_FALSE(metricProducer1->isActive());
+//
+// metricIt = metricsManager1->mAllMetricProducers.begin();
+// for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
+// if ((*metricIt)->getMetricId() == metricId2) {
+// break;
+// }
+// }
+// EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
+// auto& metricProducer2 = *metricIt;
+// EXPECT_TRUE(metricProducer2->isActive());
+//
+// int i = 0;
+// for (; i < metricsManager1->mAllAtomMatchers.size(); i++) {
+// if (metricsManager1->mAllAtomMatchers[i]->getId() ==
+// metric1ActivationTrigger1->atom_matcher_id()) {
+// break;
+// }
+// }
+// const auto& activation1 = metricProducer1->mEventActivationMap.at(i);
+// EXPECT_EQ(100 * NS_PER_SEC, activation1->ttl_ns);
+// EXPECT_EQ(0, activation1->start_ns);
+// EXPECT_EQ(kNotActive, activation1->state);
+//
+// i = 0;
+// for (; i < metricsManager1->mAllAtomMatchers.size(); i++) {
+// if (metricsManager1->mAllAtomMatchers[i]->getId() ==
+// metric1ActivationTrigger2->atom_matcher_id()) {
+// break;
+// }
+// }
+// const auto& activation2 = metricProducer1->mEventActivationMap.at(i);
+// EXPECT_EQ(200 * NS_PER_SEC, activation2->ttl_ns);
+// EXPECT_EQ(0, activation2->start_ns);
+// EXPECT_EQ(kNotActive, activation2->state);
+// // }}}------------------------------------------------------------------------------
+//
+// // Trigger Activation 1 for Metric 1
+// std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
+// auto event = CreateAcquireWakelockEvent(attributions1, "wl1", 100 + timeBase1);
+// processor->OnLogEvent(event.get());
+//
+// // Metric 1 is not active; Activation 1 set to kActiveOnBoot
+// // Metric 2 is active.
+// // {{{---------------------------------------------------------------------------
+// EXPECT_FALSE(metricProducer1->isActive());
+// EXPECT_EQ(0, activation1->start_ns);
+// EXPECT_EQ(kActiveOnBoot, activation1->state);
+// EXPECT_EQ(0, activation2->start_ns);
+// EXPECT_EQ(kNotActive, activation2->state);
+//
+// EXPECT_TRUE(metricProducer2->isActive());
+// // }}}-----------------------------------------------------------------------------
+//
+// // Simulate shutdown by saving state to disk
+// int64_t shutDownTime = timeBase1 + 100 * NS_PER_SEC;
+// processor->SaveActiveConfigsToDisk(shutDownTime);
+// EXPECT_FALSE(metricProducer1->isActive());
+// int64_t ttl1 = metric1ActivationTrigger1->ttl_seconds() * NS_PER_SEC;
+//
+// // Simulate device restarted state by creating new instance of StatsLogProcessor with the
+// // same config.
+// long timeBase2 = 1000;
+// sp<StatsLogProcessor> processor2 =
+// CreateStatsLogProcessor(timeBase2, timeBase2, config1, cfgKey1);
+//
+// // Metric 1 is not active.
+// // Metric 2 is active.
+// // {{{---------------------------------------------------------------------------
+// EXPECT_EQ(1, processor2->mMetricsManagers.size());
+// it = processor2->mMetricsManagers.find(cfgKey1);
+// EXPECT_TRUE(it != processor2->mMetricsManagers.end());
+// auto& metricsManager1001 = it->second;
+// EXPECT_TRUE(metricsManager1001->isActive());
+//
+// metricIt = metricsManager1001->mAllMetricProducers.begin();
+// for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
+// if ((*metricIt)->getMetricId() == metricId1) {
+// break;
+// }
+// }
+// EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
+// auto& metricProducer1001 = *metricIt;
+// EXPECT_FALSE(metricProducer1001->isActive());
+//
+// metricIt = metricsManager1001->mAllMetricProducers.begin();
+// for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
+// if ((*metricIt)->getMetricId() == metricId2) {
+// break;
+// }
+// }
+// EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
+// auto& metricProducer1002 = *metricIt;
+// EXPECT_TRUE(metricProducer1002->isActive());
+//
+// i = 0;
+// for (; i < metricsManager1001->mAllAtomMatchers.size(); i++) {
+// if (metricsManager1001->mAllAtomMatchers[i]->getId() ==
+// metric1ActivationTrigger1->atom_matcher_id()) {
+// break;
+// }
+// }
+// const auto& activation1001_1 = metricProducer1001->mEventActivationMap.at(i);
+// EXPECT_EQ(100 * NS_PER_SEC, activation1001_1->ttl_ns);
+// EXPECT_EQ(0, activation1001_1->start_ns);
+// EXPECT_EQ(kNotActive, activation1001_1->state);
+//
+// i = 0;
+// for (; i < metricsManager1001->mAllAtomMatchers.size(); i++) {
+// if (metricsManager1001->mAllAtomMatchers[i]->getId() ==
+// metric1ActivationTrigger2->atom_matcher_id()) {
+// break;
+// }
+// }
+//
+// const auto& activation1001_2 = metricProducer1001->mEventActivationMap.at(i);
+// EXPECT_EQ(200 * NS_PER_SEC, activation1001_2->ttl_ns);
+// EXPECT_EQ(0, activation1001_2->start_ns);
+// EXPECT_EQ(kNotActive, activation1001_2->state);
+// // }}}-----------------------------------------------------------------------------------
+//
+// // Load saved state from disk.
+// processor2->LoadActiveConfigsFromDisk();
+//
+// // Metric 1 active; Activation 1 is active, Activation 2 is not active
+// // Metric 2 is active.
+// // {{{---------------------------------------------------------------------------
+// EXPECT_TRUE(metricProducer1001->isActive());
+// EXPECT_EQ(timeBase2 + ttl1 - activation1001_1->ttl_ns, activation1001_1->start_ns);
+// EXPECT_EQ(kActive, activation1001_1->state);
+// EXPECT_EQ(0, activation1001_2->start_ns);
+// EXPECT_EQ(kNotActive, activation1001_2->state);
+//
+// EXPECT_TRUE(metricProducer1002->isActive());
+// // }}}--------------------------------------------------------------------------------
+//
+// // Trigger Activation 2 for Metric 1.
+// auto screenOnEvent = CreateScreenStateChangedEvent(
+// android::view::DISPLAY_STATE_ON,
+// timeBase2 + 200
+// );
+// processor2->OnLogEvent(screenOnEvent.get());
+//
+// // Metric 1 active; Activation 1 is active, Activation 2 is set to kActiveOnBoot
+// // Metric 2 is active.
+// // {{{---------------------------------------------------------------------------
+// EXPECT_TRUE(metricProducer1001->isActive());
+// EXPECT_EQ(timeBase2 + ttl1 - activation1001_1->ttl_ns, activation1001_1->start_ns);
+// EXPECT_EQ(kActive, activation1001_1->state);
+// EXPECT_EQ(0, activation1001_2->start_ns);
+// EXPECT_EQ(kActiveOnBoot, activation1001_2->state);
+//
+// EXPECT_TRUE(metricProducer1002->isActive());
+// // }}}---------------------------------------------------------------------------
+//
+// // Simulate shutdown by saving state to disk
+// shutDownTime = timeBase2 + 50 * NS_PER_SEC;
+// processor2->SaveActiveConfigsToDisk(shutDownTime);
+// EXPECT_TRUE(metricProducer1001->isActive());
+// EXPECT_TRUE(metricProducer1002->isActive());
+// ttl1 = timeBase2 + metric1ActivationTrigger1->ttl_seconds() * NS_PER_SEC - shutDownTime;
+// int64_t ttl2 = metric1ActivationTrigger2->ttl_seconds() * NS_PER_SEC;
+//
+// // Simulate device restarted state by creating new instance of StatsLogProcessor with the
+// // same config.
+// long timeBase3 = timeBase2 + 120 * NS_PER_SEC;
+// sp<StatsLogProcessor> processor3 =
+// CreateStatsLogProcessor(timeBase3, timeBase3, config1, cfgKey1);
+//
+// // Metric 1 is not active.
+// // Metric 2 is active.
+// // {{{---------------------------------------------------------------------------
+// EXPECT_EQ(1, processor3->mMetricsManagers.size());
+// it = processor3->mMetricsManagers.find(cfgKey1);
+// EXPECT_TRUE(it != processor3->mMetricsManagers.end());
+// auto& metricsManagerTimeBase3 = it->second;
+// EXPECT_TRUE(metricsManagerTimeBase3->isActive());
+//
+// metricIt = metricsManagerTimeBase3->mAllMetricProducers.begin();
+// for (; metricIt != metricsManagerTimeBase3->mAllMetricProducers.end(); metricIt++) {
+// if ((*metricIt)->getMetricId() == metricId1) {
+// break;
+// }
+// }
+// EXPECT_TRUE(metricIt != metricsManagerTimeBase3->mAllMetricProducers.end());
+// auto& metricProducerTimeBase3_1 = *metricIt;
+// EXPECT_FALSE(metricProducerTimeBase3_1->isActive());
+//
+// metricIt = metricsManagerTimeBase3->mAllMetricProducers.begin();
+// for (; metricIt != metricsManagerTimeBase3->mAllMetricProducers.end(); metricIt++) {
+// if ((*metricIt)->getMetricId() == metricId2) {
+// break;
+// }
+// }
+// EXPECT_TRUE(metricIt != metricsManagerTimeBase3->mAllMetricProducers.end());
+// auto& metricProducerTimeBase3_2 = *metricIt;
+// EXPECT_TRUE(metricProducerTimeBase3_2->isActive());
+//
+// i = 0;
+// for (; i < metricsManagerTimeBase3->mAllAtomMatchers.size(); i++) {
+// if (metricsManagerTimeBase3->mAllAtomMatchers[i]->getId() ==
+// metric1ActivationTrigger1->atom_matcher_id()) {
+// break;
+// }
+// }
+// const auto& activationTimeBase3_1 = metricProducerTimeBase3_1->mEventActivationMap.at(i);
+// EXPECT_EQ(100 * NS_PER_SEC, activationTimeBase3_1->ttl_ns);
+// EXPECT_EQ(0, activationTimeBase3_1->start_ns);
+// EXPECT_EQ(kNotActive, activationTimeBase3_1->state);
+//
+// i = 0;
+// for (; i < metricsManagerTimeBase3->mAllAtomMatchers.size(); i++) {
+// if (metricsManagerTimeBase3->mAllAtomMatchers[i]->getId() ==
+// metric1ActivationTrigger2->atom_matcher_id()) {
+// break;
+// }
+// }
+//
+// const auto& activationTimeBase3_2 = metricProducerTimeBase3_1->mEventActivationMap.at(i);
+// EXPECT_EQ(200 * NS_PER_SEC, activationTimeBase3_2->ttl_ns);
+// EXPECT_EQ(0, activationTimeBase3_2->start_ns);
+// EXPECT_EQ(kNotActive, activationTimeBase3_2->state);
+//
+// EXPECT_TRUE(metricProducerTimeBase3_2->isActive());
+// // }}}----------------------------------------------------------------------------------
+//
+// // Load saved state from disk.
+// processor3->LoadActiveConfigsFromDisk();
+//
+// // Metric 1 active: Activation 1 is active, Activation 2 is active
+// // Metric 2 is active.
+// // {{{---------------------------------------------------------------------------
+// EXPECT_TRUE(metricProducerTimeBase3_1->isActive());
+// EXPECT_EQ(timeBase3 + ttl1 - activationTimeBase3_1->ttl_ns, activationTimeBase3_1->start_ns);
+// EXPECT_EQ(kActive, activationTimeBase3_1->state);
+// EXPECT_EQ(timeBase3 + ttl2 - activationTimeBase3_2->ttl_ns, activationTimeBase3_2->start_ns);
+// EXPECT_EQ(kActive, activationTimeBase3_2->state);
+//
+// EXPECT_TRUE(metricProducerTimeBase3_2->isActive());
+// // }}}-------------------------------------------------------------------------------
+//
+// // Trigger Activation 2 for Metric 1 again.
+// screenOnEvent = CreateScreenStateChangedEvent(
+// android::view::DISPLAY_STATE_ON,
+// timeBase3 + 100 * NS_PER_SEC
+// );
+// processor3->OnLogEvent(screenOnEvent.get());
+//
+// // Metric 1 active; Activation 1 is not active, Activation 2 is set to active
+// // Metric 2 is active.
+// // {{{---------------------------------------------------------------------------
+// EXPECT_TRUE(metricProducerTimeBase3_1->isActive());
+// EXPECT_EQ(kNotActive, activationTimeBase3_1->state);
+// EXPECT_EQ(timeBase3 + ttl2 - activationTimeBase3_2->ttl_ns, activationTimeBase3_2->start_ns);
+// EXPECT_EQ(kActive, activationTimeBase3_2->state);
+//
+// EXPECT_TRUE(metricProducerTimeBase3_2->isActive());
+// // }}}---------------------------------------------------------------------------
+//
+// // Simulate shutdown by saving state to disk.
+// shutDownTime = timeBase3 + 500 * NS_PER_SEC;
+// processor3->SaveActiveConfigsToDisk(shutDownTime);
+// EXPECT_TRUE(metricProducer1001->isActive());
+// EXPECT_TRUE(metricProducer1002->isActive());
+// ttl1 = timeBase3 + ttl1 - shutDownTime;
+// ttl2 = timeBase3 + metric1ActivationTrigger2->ttl_seconds() * NS_PER_SEC - shutDownTime;
+//
+// // Simulate device restarted state by creating new instance of StatsLogProcessor with the
+// // same config.
+// long timeBase4 = timeBase3 + 600 * NS_PER_SEC;
+// sp<StatsLogProcessor> processor4 =
+// CreateStatsLogProcessor(timeBase4, timeBase4, config1, cfgKey1);
+//
+// // Metric 1 is not active.
+// // Metric 2 is active.
+// // {{{---------------------------------------------------------------------------
+// EXPECT_EQ(1, processor4->mMetricsManagers.size());
+// it = processor4->mMetricsManagers.find(cfgKey1);
+// EXPECT_TRUE(it != processor4->mMetricsManagers.end());
+// auto& metricsManagerTimeBase4 = it->second;
+// EXPECT_TRUE(metricsManagerTimeBase4->isActive());
+//
+// metricIt = metricsManagerTimeBase4->mAllMetricProducers.begin();
+// for (; metricIt != metricsManagerTimeBase4->mAllMetricProducers.end(); metricIt++) {
+// if ((*metricIt)->getMetricId() == metricId1) {
+// break;
+// }
+// }
+// EXPECT_TRUE(metricIt != metricsManagerTimeBase4->mAllMetricProducers.end());
+// auto& metricProducerTimeBase4_1 = *metricIt;
+// EXPECT_FALSE(metricProducerTimeBase4_1->isActive());
+//
+// metricIt = metricsManagerTimeBase4->mAllMetricProducers.begin();
+// for (; metricIt != metricsManagerTimeBase4->mAllMetricProducers.end(); metricIt++) {
+// if ((*metricIt)->getMetricId() == metricId2) {
+// break;
+// }
+// }
+// EXPECT_TRUE(metricIt != metricsManagerTimeBase4->mAllMetricProducers.end());
+// auto& metricProducerTimeBase4_2 = *metricIt;
+// EXPECT_TRUE(metricProducerTimeBase4_2->isActive());
+//
+// i = 0;
+// for (; i < metricsManagerTimeBase4->mAllAtomMatchers.size(); i++) {
+// if (metricsManagerTimeBase4->mAllAtomMatchers[i]->getId() ==
+// metric1ActivationTrigger1->atom_matcher_id()) {
+// break;
+// }
+// }
+// const auto& activationTimeBase4_1 = metricProducerTimeBase4_1->mEventActivationMap.at(i);
+// EXPECT_EQ(100 * NS_PER_SEC, activationTimeBase4_1->ttl_ns);
+// EXPECT_EQ(0, activationTimeBase4_1->start_ns);
+// EXPECT_EQ(kNotActive, activationTimeBase4_1->state);
+//
+// i = 0;
+// for (; i < metricsManagerTimeBase4->mAllAtomMatchers.size(); i++) {
+// if (metricsManagerTimeBase4->mAllAtomMatchers[i]->getId() ==
+// metric1ActivationTrigger2->atom_matcher_id()) {
+// break;
+// }
+// }
+//
+// const auto& activationTimeBase4_2 = metricProducerTimeBase4_1->mEventActivationMap.at(i);
+// EXPECT_EQ(200 * NS_PER_SEC, activationTimeBase4_2->ttl_ns);
+// EXPECT_EQ(0, activationTimeBase4_2->start_ns);
+// EXPECT_EQ(kNotActive, activationTimeBase4_2->state);
+//
+// EXPECT_TRUE(metricProducerTimeBase4_2->isActive());
+// // }}}----------------------------------------------------------------------------------
+//
+// // Load saved state from disk.
+// processor4->LoadActiveConfigsFromDisk();
+//
+// // Metric 1 active: Activation 1 is not active, Activation 2 is not active
+// // Metric 2 is active.
+// // {{{---------------------------------------------------------------------------
+// EXPECT_FALSE(metricProducerTimeBase4_1->isActive());
+// EXPECT_EQ(kNotActive, activationTimeBase4_1->state);
+// EXPECT_EQ(kNotActive, activationTimeBase4_2->state);
+//
+// EXPECT_TRUE(metricProducerTimeBase4_2->isActive());
+// // }}}-------------------------------------------------------------------------------
+//}
+//
+//TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivationsDifferentActivationTypes) {
+// int uid = 1111;
+//
+// // Create config with 2 metrics:
+// // Metric 1: Activate on boot with 2 activations
+// // Metric 2: Always active
+// StatsdConfig config1;
+// config1.set_id(12341);
+// config1.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+// auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
+// auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
+// *config1.add_atom_matcher() = wakelockAcquireMatcher;
+// *config1.add_atom_matcher() = screenOnMatcher;
+//
+// long metricId1 = 1234561;
+// long metricId2 = 1234562;
+//
+// auto countMetric1 = config1.add_count_metric();
+// countMetric1->set_id(metricId1);
+// countMetric1->set_what(wakelockAcquireMatcher.id());
+// countMetric1->set_bucket(FIVE_MINUTES);
+//
+// auto countMetric2 = config1.add_count_metric();
+// countMetric2->set_id(metricId2);
+// countMetric2->set_what(wakelockAcquireMatcher.id());
+// countMetric2->set_bucket(FIVE_MINUTES);
+//
+// auto metric1Activation = config1.add_metric_activation();
+// metric1Activation->set_metric_id(metricId1);
+// metric1Activation->set_activation_type(ACTIVATE_ON_BOOT);
+// auto metric1ActivationTrigger1 = metric1Activation->add_event_activation();
+// metric1ActivationTrigger1->set_atom_matcher_id(wakelockAcquireMatcher.id());
+// metric1ActivationTrigger1->set_ttl_seconds(100);
+// auto metric1ActivationTrigger2 = metric1Activation->add_event_activation();
+// metric1ActivationTrigger2->set_atom_matcher_id(screenOnMatcher.id());
+// metric1ActivationTrigger2->set_ttl_seconds(200);
+// metric1ActivationTrigger2->set_activation_type(ACTIVATE_IMMEDIATELY);
+//
+// ConfigKey cfgKey1(uid, 12341);
+// long timeBase1 = 1;
+// sp<StatsLogProcessor> processor1 =
+// CreateStatsLogProcessor(timeBase1, timeBase1, config1, cfgKey1);
+//
+// // Metric 1 is not active.
+// // Metric 2 is active.
+// // {{{---------------------------------------------------------------------------
+// EXPECT_EQ(1, processor1->mMetricsManagers.size());
+// auto it = processor1->mMetricsManagers.find(cfgKey1);
+// EXPECT_TRUE(it != processor1->mMetricsManagers.end());
+// auto& metricsManager1 = it->second;
+// EXPECT_TRUE(metricsManager1->isActive());
+//
+// EXPECT_EQ(metricsManager1->mAllMetricProducers.size(), 2);
+// // We assume that the index of a MetricProducer within the mAllMetricProducers
+// // array follows the order in which metrics are added to the config.
+// auto& metricProducer1_1 = metricsManager1->mAllMetricProducers[0];
+// EXPECT_EQ(metricProducer1_1->getMetricId(), metricId1);
+// EXPECT_FALSE(metricProducer1_1->isActive()); // inactive due to associated MetricActivation
+//
+// auto& metricProducer1_2 = metricsManager1->mAllMetricProducers[1];
+// EXPECT_EQ(metricProducer1_2->getMetricId(), metricId2);
+// EXPECT_TRUE(metricProducer1_2->isActive());
+//
+// EXPECT_EQ(metricProducer1_1->mEventActivationMap.size(), 2);
+// // The key in mEventActivationMap is the index of the associated atom matcher. We assume
+// // that matchers are indexed in the order that they are added to the config.
+// const auto& activation1_1_1 = metricProducer1_1->mEventActivationMap.at(0);
+// EXPECT_EQ(100 * NS_PER_SEC, activation1_1_1->ttl_ns);
+// EXPECT_EQ(0, activation1_1_1->start_ns);
+// EXPECT_EQ(kNotActive, activation1_1_1->state);
+// EXPECT_EQ(ACTIVATE_ON_BOOT, activation1_1_1->activationType);
+//
+// const auto& activation1_1_2 = metricProducer1_1->mEventActivationMap.at(1);
+// EXPECT_EQ(200 * NS_PER_SEC, activation1_1_2->ttl_ns);
+// EXPECT_EQ(0, activation1_1_2->start_ns);
+// EXPECT_EQ(kNotActive, activation1_1_2->state);
+// EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation1_1_2->activationType);
+// // }}}------------------------------------------------------------------------------
+//
+// // Trigger Activation 1 for Metric 1
+// std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
+// auto event = CreateAcquireWakelockEvent(attributions1, "wl1", 100 + timeBase1);
+// processor1->OnLogEvent(event.get());
+//
+// // Metric 1 is not active; Activation 1 set to kActiveOnBoot
+// // Metric 2 is active.
+// // {{{---------------------------------------------------------------------------
+// EXPECT_FALSE(metricProducer1_1->isActive());
+// EXPECT_EQ(0, activation1_1_1->start_ns);
+// EXPECT_EQ(kActiveOnBoot, activation1_1_1->state);
+// EXPECT_EQ(0, activation1_1_2->start_ns);
+// EXPECT_EQ(kNotActive, activation1_1_2->state);
+//
+// EXPECT_TRUE(metricProducer1_2->isActive());
+// // }}}-----------------------------------------------------------------------------
+//
+// // Simulate shutdown by saving state to disk
+// int64_t shutDownTime = timeBase1 + 100 * NS_PER_SEC;
+// processor1->SaveActiveConfigsToDisk(shutDownTime);
+// EXPECT_FALSE(metricProducer1_1->isActive());
+//
+// // Simulate device restarted state by creating new instance of StatsLogProcessor with the
+// // same config.
+// long timeBase2 = 1000;
+// sp<StatsLogProcessor> processor2 =
+// CreateStatsLogProcessor(timeBase2, timeBase2, config1, cfgKey1);
+//
+// // Metric 1 is not active.
+// // Metric 2 is active.
+// // {{{---------------------------------------------------------------------------
+// EXPECT_EQ(1, processor2->mMetricsManagers.size());
+// it = processor2->mMetricsManagers.find(cfgKey1);
+// EXPECT_TRUE(it != processor2->mMetricsManagers.end());
+// auto& metricsManager2 = it->second;
+// EXPECT_TRUE(metricsManager2->isActive());
+//
+// EXPECT_EQ(metricsManager2->mAllMetricProducers.size(), 2);
+// // We assume that the index of a MetricProducer within the mAllMetricProducers
+// // array follows the order in which metrics are added to the config.
+// auto& metricProducer2_1 = metricsManager2->mAllMetricProducers[0];
+// EXPECT_EQ(metricProducer2_1->getMetricId(), metricId1);
+// EXPECT_FALSE(metricProducer2_1->isActive());
+//
+// auto& metricProducer2_2 = metricsManager2->mAllMetricProducers[1];
+// EXPECT_EQ(metricProducer2_2->getMetricId(), metricId2);
+// EXPECT_TRUE(metricProducer2_2->isActive());
+//
+// EXPECT_EQ(metricProducer2_1->mEventActivationMap.size(), 2);
+// // The key in mEventActivationMap is the index of the associated atom matcher. We assume
+// // that matchers are indexed in the order that they are added to the config.
+// const auto& activation2_1_1 = metricProducer2_1->mEventActivationMap.at(0);
+// EXPECT_EQ(100 * NS_PER_SEC, activation2_1_1->ttl_ns);
+// EXPECT_EQ(0, activation2_1_1->start_ns);
+// EXPECT_EQ(kNotActive, activation2_1_1->state);
+// EXPECT_EQ(ACTIVATE_ON_BOOT, activation2_1_1->activationType);
+//
+// const auto& activation2_1_2 = metricProducer2_1->mEventActivationMap.at(1);
+// EXPECT_EQ(200 * NS_PER_SEC, activation2_1_2->ttl_ns);
+// EXPECT_EQ(0, activation2_1_2->start_ns);
+// EXPECT_EQ(kNotActive, activation2_1_2->state);
+// EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation2_1_2->activationType);
+// // }}}-----------------------------------------------------------------------------------
+//
+// // Load saved state from disk.
+// processor2->LoadActiveConfigsFromDisk();
+//
+// // Metric 1 active; Activation 1 is active, Activation 2 is not active
+// // Metric 2 is active.
+// // {{{---------------------------------------------------------------------------
+// EXPECT_TRUE(metricProducer2_1->isActive());
+// int64_t ttl1 = metric1ActivationTrigger1->ttl_seconds() * NS_PER_SEC;
+// EXPECT_EQ(timeBase2 + ttl1 - activation2_1_1->ttl_ns, activation2_1_1->start_ns);
+// EXPECT_EQ(kActive, activation2_1_1->state);
+// EXPECT_EQ(0, activation2_1_2->start_ns);
+// EXPECT_EQ(kNotActive, activation2_1_2->state);
+//
+// EXPECT_TRUE(metricProducer2_2->isActive());
+// // }}}--------------------------------------------------------------------------------
+//
+// // Trigger Activation 2 for Metric 1.
+// auto screenOnEvent = CreateScreenStateChangedEvent(
+// android::view::DISPLAY_STATE_ON,
+// timeBase2 + 200
+// );
+// processor2->OnLogEvent(screenOnEvent.get());
+//
+// // Metric 1 active; Activation 1 is active, Activation 2 is active
+// // Metric 2 is active.
+// // {{{---------------------------------------------------------------------------
+// EXPECT_TRUE(metricProducer2_1->isActive());
+// EXPECT_EQ(timeBase2 + ttl1 - activation2_1_1->ttl_ns, activation2_1_1->start_ns);
+// EXPECT_EQ(kActive, activation2_1_1->state);
+// EXPECT_EQ(screenOnEvent->GetElapsedTimestampNs(), activation2_1_2->start_ns);
+// EXPECT_EQ(kActive, activation2_1_2->state);
+//
+// EXPECT_TRUE(metricProducer2_2->isActive());
+// // }}}---------------------------------------------------------------------------
+//
+// // Simulate shutdown by saving state to disk
+// shutDownTime = timeBase2 + 50 * NS_PER_SEC;
+// processor2->SaveActiveConfigsToDisk(shutDownTime);
+// EXPECT_TRUE(metricProducer2_1->isActive());
+// EXPECT_TRUE(metricProducer2_2->isActive());
+// ttl1 -= shutDownTime - timeBase2;
+// int64_t ttl2 = metric1ActivationTrigger2->ttl_seconds() * NS_PER_SEC
+// - (shutDownTime - screenOnEvent->GetElapsedTimestampNs());
+//
+// // Simulate device restarted state by creating new instance of StatsLogProcessor with the
+// // same config.
+// long timeBase3 = timeBase2 + 120 * NS_PER_SEC;
+// sp<StatsLogProcessor> processor3 =
+// CreateStatsLogProcessor(timeBase3, timeBase3, config1, cfgKey1);
+//
+// // Metric 1 is not active.
+// // Metric 2 is active.
+// // {{{---------------------------------------------------------------------------
+// EXPECT_EQ(1, processor3->mMetricsManagers.size());
+// it = processor3->mMetricsManagers.find(cfgKey1);
+// EXPECT_TRUE(it != processor3->mMetricsManagers.end());
+// auto& metricsManager3 = it->second;
+// EXPECT_TRUE(metricsManager3->isActive());
+//
+// EXPECT_EQ(metricsManager3->mAllMetricProducers.size(), 2);
+// // We assume that the index of a MetricProducer within the mAllMetricProducers
+// // array follows the order in which metrics are added to the config.
+// auto& metricProducer3_1 = metricsManager3->mAllMetricProducers[0];
+// EXPECT_EQ(metricProducer3_1->getMetricId(), metricId1);
+// EXPECT_FALSE(metricProducer3_1->isActive());
+//
+// auto& metricProducer3_2 = metricsManager3->mAllMetricProducers[1];
+// EXPECT_EQ(metricProducer3_2->getMetricId(), metricId2);
+// EXPECT_TRUE(metricProducer3_2->isActive());
+//
+// EXPECT_EQ(metricProducer3_1->mEventActivationMap.size(), 2);
+// // The key in mEventActivationMap is the index of the associated atom matcher. We assume
+// // that matchers are indexed in the order that they are added to the config.
+// const auto& activation3_1_1 = metricProducer3_1->mEventActivationMap.at(0);
+// EXPECT_EQ(100 * NS_PER_SEC, activation3_1_1->ttl_ns);
+// EXPECT_EQ(0, activation3_1_1->start_ns);
+// EXPECT_EQ(kNotActive, activation3_1_1->state);
+// EXPECT_EQ(ACTIVATE_ON_BOOT, activation3_1_1->activationType);
+//
+// const auto& activation3_1_2 = metricProducer3_1->mEventActivationMap.at(1);
+// EXPECT_EQ(200 * NS_PER_SEC, activation3_1_2->ttl_ns);
+// EXPECT_EQ(0, activation3_1_2->start_ns);
+// EXPECT_EQ(kNotActive, activation3_1_2->state);
+// EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation3_1_2->activationType);
+// // }}}----------------------------------------------------------------------------------
+//
+// // Load saved state from disk.
+// processor3->LoadActiveConfigsFromDisk();
+//
+// // Metric 1 active: Activation 1 is active, Activation 2 is active
+// // Metric 2 is active.
+// // {{{---------------------------------------------------------------------------
+// EXPECT_TRUE(metricProducer3_1->isActive());
+// EXPECT_EQ(timeBase3 + ttl1 - activation3_1_1->ttl_ns, activation3_1_1->start_ns);
+// EXPECT_EQ(kActive, activation3_1_1->state);
+// EXPECT_EQ(timeBase3 + ttl2 - activation3_1_2->ttl_ns, activation3_1_2->start_ns);
+// EXPECT_EQ(kActive, activation3_1_2->state);
+//
+// EXPECT_TRUE(metricProducer3_2->isActive());
+// // }}}-------------------------------------------------------------------------------
+//
+//
+// // Trigger Activation 2 for Metric 1 again.
+// screenOnEvent = CreateScreenStateChangedEvent(
+// android::view::DISPLAY_STATE_ON,
+// timeBase3 + 100 * NS_PER_SEC
+// );
+// processor3->OnLogEvent(screenOnEvent.get());
+//
+// // Metric 1 active; Activation 1 is inactive (above screenOnEvent causes ttl1 to expire),
+// // Activation 2 is set to active
+// // Metric 2 is active.
+// // {{{---------------------------------------------------------------------------
+// EXPECT_TRUE(metricProducer3_1->isActive());
+// EXPECT_EQ(kNotActive, activation3_1_1->state);
+// EXPECT_EQ(screenOnEvent->GetElapsedTimestampNs(), activation3_1_2->start_ns);
+// EXPECT_EQ(kActive, activation3_1_2->state);
+//
+// EXPECT_TRUE(metricProducer3_2->isActive());
+// // }}}---------------------------------------------------------------------------
+//}
+//
+//TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart) {
+// int uid = 9876;
+// long configId = 12341;
+//
+// // Create config with 3 metrics:
+// // Metric 1: Activate on 2 activations, 1 on boot, 1 immediate.
+// // Metric 2: Activate on 2 activations, 1 on boot, 1 immediate.
+// // Metric 3: Always active
+// StatsdConfig config1;
+// config1.set_id(configId);
+// config1.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+// auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
+// auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
+// auto jobStartMatcher = CreateStartScheduledJobAtomMatcher();
+// auto jobFinishMatcher = CreateFinishScheduledJobAtomMatcher();
+// *config1.add_atom_matcher() = wakelockAcquireMatcher;
+// *config1.add_atom_matcher() = screenOnMatcher;
+// *config1.add_atom_matcher() = jobStartMatcher;
+// *config1.add_atom_matcher() = jobFinishMatcher;
+//
+// long metricId1 = 1234561;
+// long metricId2 = 1234562;
+// long metricId3 = 1234563;
+//
+// auto countMetric1 = config1.add_count_metric();
+// countMetric1->set_id(metricId1);
+// countMetric1->set_what(wakelockAcquireMatcher.id());
+// countMetric1->set_bucket(FIVE_MINUTES);
+//
+// auto countMetric2 = config1.add_count_metric();
+// countMetric2->set_id(metricId2);
+// countMetric2->set_what(wakelockAcquireMatcher.id());
+// countMetric2->set_bucket(FIVE_MINUTES);
+//
+// auto countMetric3 = config1.add_count_metric();
+// countMetric3->set_id(metricId3);
+// countMetric3->set_what(wakelockAcquireMatcher.id());
+// countMetric3->set_bucket(FIVE_MINUTES);
+//
+// // Metric 1 activates on boot for wakelock acquire, immediately for screen on.
+// auto metric1Activation = config1.add_metric_activation();
+// metric1Activation->set_metric_id(metricId1);
+// auto metric1ActivationTrigger1 = metric1Activation->add_event_activation();
+// metric1ActivationTrigger1->set_atom_matcher_id(wakelockAcquireMatcher.id());
+// metric1ActivationTrigger1->set_ttl_seconds(100);
+// metric1ActivationTrigger1->set_activation_type(ACTIVATE_ON_BOOT);
+// auto metric1ActivationTrigger2 = metric1Activation->add_event_activation();
+// metric1ActivationTrigger2->set_atom_matcher_id(screenOnMatcher.id());
+// metric1ActivationTrigger2->set_ttl_seconds(200);
+// metric1ActivationTrigger2->set_activation_type(ACTIVATE_IMMEDIATELY);
+//
+// // Metric 2 activates on boot for scheduled job start, immediately for scheduled job finish.
+// auto metric2Activation = config1.add_metric_activation();
+// metric2Activation->set_metric_id(metricId2);
+// auto metric2ActivationTrigger1 = metric2Activation->add_event_activation();
+// metric2ActivationTrigger1->set_atom_matcher_id(jobStartMatcher.id());
+// metric2ActivationTrigger1->set_ttl_seconds(100);
+// metric2ActivationTrigger1->set_activation_type(ACTIVATE_ON_BOOT);
+// auto metric2ActivationTrigger2 = metric2Activation->add_event_activation();
+// metric2ActivationTrigger2->set_atom_matcher_id(jobFinishMatcher.id());
+// metric2ActivationTrigger2->set_ttl_seconds(200);
+// metric2ActivationTrigger2->set_activation_type(ACTIVATE_IMMEDIATELY);
+//
+// // Send the config.
+// shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
+// string serialized = config1.SerializeAsString();
+// service->addConfigurationChecked(uid, configId, {serialized.begin(), serialized.end()});
+//
+// // Make sure the config is stored on disk. Otherwise, we will not reset on system server death.
+// StatsdConfig tmpConfig;
+// ConfigKey cfgKey1(uid, configId);
+// EXPECT_TRUE(StorageManager::readConfigFromDisk(cfgKey1, &tmpConfig));
+//
+// // Metric 1 is not active.
+// // Metric 2 is not active.
+// // Metric 3 is active.
+// // {{{---------------------------------------------------------------------------
+// sp<StatsLogProcessor> processor = service->mProcessor;
+// EXPECT_EQ(1, processor->mMetricsManagers.size());
+// auto it = processor->mMetricsManagers.find(cfgKey1);
+// EXPECT_TRUE(it != processor->mMetricsManagers.end());
+// auto& metricsManager1 = it->second;
+// EXPECT_TRUE(metricsManager1->isActive());
+// EXPECT_EQ(3, metricsManager1->mAllMetricProducers.size());
+//
+// auto& metricProducer1 = metricsManager1->mAllMetricProducers[0];
+// EXPECT_EQ(metricId1, metricProducer1->getMetricId());
+// EXPECT_FALSE(metricProducer1->isActive());
+//
+// auto& metricProducer2 = metricsManager1->mAllMetricProducers[1];
+// EXPECT_EQ(metricId2, metricProducer2->getMetricId());
+// EXPECT_FALSE(metricProducer2->isActive());
+//
+// auto& metricProducer3 = metricsManager1->mAllMetricProducers[2];
+// EXPECT_EQ(metricId3, metricProducer3->getMetricId());
+// EXPECT_TRUE(metricProducer3->isActive());
+//
+// // Check event activations.
+// EXPECT_EQ(metricsManager1->mAllAtomMatchers.size(), 4);
+// EXPECT_EQ(metricsManager1->mAllAtomMatchers[0]->getId(),
+// metric1ActivationTrigger1->atom_matcher_id());
+// const auto& activation1 = metricProducer1->mEventActivationMap.at(0);
+// EXPECT_EQ(100 * NS_PER_SEC, activation1->ttl_ns);
+// EXPECT_EQ(0, activation1->start_ns);
+// EXPECT_EQ(kNotActive, activation1->state);
+// EXPECT_EQ(ACTIVATE_ON_BOOT, activation1->activationType);
+//
+// EXPECT_EQ(metricsManager1->mAllAtomMatchers[1]->getId(),
+// metric1ActivationTrigger2->atom_matcher_id());
+// const auto& activation2 = metricProducer1->mEventActivationMap.at(1);
+// EXPECT_EQ(200 * NS_PER_SEC, activation2->ttl_ns);
+// EXPECT_EQ(0, activation2->start_ns);
+// EXPECT_EQ(kNotActive, activation2->state);
+// EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation2->activationType);
+//
+// EXPECT_EQ(metricsManager1->mAllAtomMatchers[2]->getId(),
+// metric2ActivationTrigger1->atom_matcher_id());
+// const auto& activation3 = metricProducer2->mEventActivationMap.at(2);
+// EXPECT_EQ(100 * NS_PER_SEC, activation3->ttl_ns);
+// EXPECT_EQ(0, activation3->start_ns);
+// EXPECT_EQ(kNotActive, activation3->state);
+// EXPECT_EQ(ACTIVATE_ON_BOOT, activation3->activationType);
+//
+// EXPECT_EQ(metricsManager1->mAllAtomMatchers[3]->getId(),
+// metric2ActivationTrigger2->atom_matcher_id());
+// const auto& activation4 = metricProducer2->mEventActivationMap.at(3);
+// EXPECT_EQ(200 * NS_PER_SEC, activation4->ttl_ns);
+// EXPECT_EQ(0, activation4->start_ns);
+// EXPECT_EQ(kNotActive, activation4->state);
+// EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation4->activationType);
+// // }}}------------------------------------------------------------------------------
+//
+// // Trigger Activation 1 for Metric 1. Should activate on boot.
+// // Trigger Activation 4 for Metric 2. Should activate immediately.
+// long configAddedTimeNs = metricsManager1->mLastReportTimeNs;
+// std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
+// auto event = CreateAcquireWakelockEvent(attributions1, "wl1", 1 + configAddedTimeNs);
+// processor->OnLogEvent(event.get());
+//
+// event = CreateFinishScheduledJobEvent(attributions1, "finish1", 2 + configAddedTimeNs);
+// processor->OnLogEvent(event.get());
+//
+// // Metric 1 is not active; Activation 1 set to kActiveOnBoot
+// // Metric 2 is active. Activation 4 set to kActive
+// // Metric 3 is active.
+// // {{{---------------------------------------------------------------------------
+// EXPECT_FALSE(metricProducer1->isActive());
+// EXPECT_EQ(0, activation1->start_ns);
+// EXPECT_EQ(kActiveOnBoot, activation1->state);
+// EXPECT_EQ(0, activation2->start_ns);
+// EXPECT_EQ(kNotActive, activation2->state);
+//
+// EXPECT_TRUE(metricProducer2->isActive());
+// EXPECT_EQ(0, activation3->start_ns);
+// EXPECT_EQ(kNotActive, activation3->state);
+// EXPECT_EQ(2 + configAddedTimeNs, activation4->start_ns);
+// EXPECT_EQ(kActive, activation4->state);
+//
+// EXPECT_TRUE(metricProducer3->isActive());
+// // }}}-----------------------------------------------------------------------------
+//
+// // Can't fake time with StatsService.
+// // Lets get a time close to the system server death time and make sure it's sane.
+// int64_t approximateSystemServerDeath = getElapsedRealtimeNs();
+// EXPECT_TRUE(approximateSystemServerDeath > 2 + configAddedTimeNs);
+// EXPECT_TRUE(approximateSystemServerDeath < NS_PER_SEC + configAddedTimeNs);
+//
+// // System server dies.
+// service->statsCompanionServiceDiedImpl();
+//
+// // We should have a new metrics manager. Lets get it and ensure activation status is restored.
+// // {{{---------------------------------------------------------------------------
+// EXPECT_EQ(1, processor->mMetricsManagers.size());
+// it = processor->mMetricsManagers.find(cfgKey1);
+// EXPECT_TRUE(it != processor->mMetricsManagers.end());
+// auto& metricsManager2 = it->second;
+// EXPECT_TRUE(metricsManager2->isActive());
+// EXPECT_EQ(3, metricsManager2->mAllMetricProducers.size());
+//
+// auto& metricProducer1001 = metricsManager2->mAllMetricProducers[0];
+// EXPECT_EQ(metricId1, metricProducer1001->getMetricId());
+// EXPECT_FALSE(metricProducer1001->isActive());
+//
+// auto& metricProducer1002 = metricsManager2->mAllMetricProducers[1];
+// EXPECT_EQ(metricId2, metricProducer1002->getMetricId());
+// EXPECT_TRUE(metricProducer1002->isActive());
+//
+// auto& metricProducer1003 = metricsManager2->mAllMetricProducers[2];
+// EXPECT_EQ(metricId3, metricProducer1003->getMetricId());
+// EXPECT_TRUE(metricProducer1003->isActive());
+//
+// // Check event activations.
+// // Activation 1 is kActiveOnBoot.
+// // Activation 2 and 3 are not active.
+// // Activation 4 is active.
+// EXPECT_EQ(metricsManager2->mAllAtomMatchers.size(), 4);
+// EXPECT_EQ(metricsManager2->mAllAtomMatchers[0]->getId(),
+// metric1ActivationTrigger1->atom_matcher_id());
+// const auto& activation1001 = metricProducer1001->mEventActivationMap.at(0);
+// EXPECT_EQ(100 * NS_PER_SEC, activation1001->ttl_ns);
+// EXPECT_EQ(0, activation1001->start_ns);
+// EXPECT_EQ(kActiveOnBoot, activation1001->state);
+// EXPECT_EQ(ACTIVATE_ON_BOOT, activation1001->activationType);
+//
+// EXPECT_EQ(metricsManager2->mAllAtomMatchers[1]->getId(),
+// metric1ActivationTrigger2->atom_matcher_id());
+// const auto& activation1002 = metricProducer1001->mEventActivationMap.at(1);
+// EXPECT_EQ(200 * NS_PER_SEC, activation1002->ttl_ns);
+// EXPECT_EQ(0, activation1002->start_ns);
+// EXPECT_EQ(kNotActive, activation1002->state);
+// EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation1002->activationType);
+//
+// EXPECT_EQ(metricsManager2->mAllAtomMatchers[2]->getId(),
+// metric2ActivationTrigger1->atom_matcher_id());
+// const auto& activation1003 = metricProducer1002->mEventActivationMap.at(2);
+// EXPECT_EQ(100 * NS_PER_SEC, activation1003->ttl_ns);
+// EXPECT_EQ(0, activation1003->start_ns);
+// EXPECT_EQ(kNotActive, activation1003->state);
+// EXPECT_EQ(ACTIVATE_ON_BOOT, activation1003->activationType);
+//
+// EXPECT_EQ(metricsManager2->mAllAtomMatchers[3]->getId(),
+// metric2ActivationTrigger2->atom_matcher_id());
+// const auto& activation1004 = metricProducer1002->mEventActivationMap.at(3);
+// EXPECT_EQ(200 * NS_PER_SEC, activation1004->ttl_ns);
+// EXPECT_EQ(2 + configAddedTimeNs, activation1004->start_ns);
+// EXPECT_EQ(kActive, activation1004->state);
+// EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation1004->activationType);
+// // }}}------------------------------------------------------------------------------
+//
+// // Clear the data stored on disk as a result of the system server death.
+// vector<uint8_t> buffer;
+// processor->onDumpReport(cfgKey1, configAddedTimeNs + NS_PER_SEC, false, true,
+// ADB_DUMP, FAST, &buffer);
+//}
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
diff --git a/cmds/statsd/tests/UidMap_test.cpp b/cmds/statsd/tests/UidMap_test.cpp
index d9fa4e9..af6de06 100644
--- a/cmds/statsd/tests/UidMap_test.cpp
+++ b/cmds/statsd/tests/UidMap_test.cpp
@@ -39,34 +39,35 @@
const string kApp1 = "app1.sharing.1";
const string kApp2 = "app2.sharing.1";
-TEST(UidMapTest, TestIsolatedUID) {
- sp<UidMap> m = new UidMap();
- sp<StatsPullerManager> pullerManager = new StatsPullerManager();
- sp<AlarmMonitor> anomalyAlarmMonitor;
- sp<AlarmMonitor> subscriberAlarmMonitor;
- // Construct the processor with a dummy sendBroadcast function that does nothing.
- StatsLogProcessor p(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor, 0,
- [](const ConfigKey& key) { return true; },
- [](const int&, const vector<int64_t>&) {return true;});
- LogEvent addEvent(android::util::ISOLATED_UID_CHANGED, 1);
- addEvent.write(100); // parent UID
- addEvent.write(101); // isolated UID
- addEvent.write(1); // Indicates creation.
- addEvent.init();
-
- EXPECT_EQ(101, m->getHostUidOrSelf(101));
-
- p.OnLogEvent(&addEvent);
- EXPECT_EQ(100, m->getHostUidOrSelf(101));
-
- LogEvent removeEvent(android::util::ISOLATED_UID_CHANGED, 1);
- removeEvent.write(100); // parent UID
- removeEvent.write(101); // isolated UID
- removeEvent.write(0); // Indicates removal.
- removeEvent.init();
- p.OnLogEvent(&removeEvent);
- EXPECT_EQ(101, m->getHostUidOrSelf(101));
-}
+// TODO(b/149590301): Update this test to use new socket schema.
+//TEST(UidMapTest, TestIsolatedUID) {
+// sp<UidMap> m = new UidMap();
+// sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+// sp<AlarmMonitor> anomalyAlarmMonitor;
+// sp<AlarmMonitor> subscriberAlarmMonitor;
+// // Construct the processor with a dummy sendBroadcast function that does nothing.
+// StatsLogProcessor p(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor, 0,
+// [](const ConfigKey& key) { return true; },
+// [](const int&, const vector<int64_t>&) {return true;});
+// LogEvent addEvent(android::util::ISOLATED_UID_CHANGED, 1);
+// addEvent.write(100); // parent UID
+// addEvent.write(101); // isolated UID
+// addEvent.write(1); // Indicates creation.
+// addEvent.init();
+//
+// EXPECT_EQ(101, m->getHostUidOrSelf(101));
+//
+// p.OnLogEvent(&addEvent);
+// EXPECT_EQ(100, m->getHostUidOrSelf(101));
+//
+// LogEvent removeEvent(android::util::ISOLATED_UID_CHANGED, 1);
+// removeEvent.write(100); // parent UID
+// removeEvent.write(101); // isolated UID
+// removeEvent.write(0); // Indicates removal.
+// removeEvent.init();
+// p.OnLogEvent(&removeEvent);
+// EXPECT_EQ(101, m->getHostUidOrSelf(101));
+//}
TEST(UidMapTest, TestMatching) {
UidMap m;
diff --git a/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp b/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp
index 6eaa231..36094b2 100644
--- a/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp
+++ b/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp
@@ -67,13 +67,14 @@
event->write(nodes); // attribution chain.
}
-void makeWakeLockEvent(
- LogEvent* event, const std::vector<int> &uids, const string& wl, int acquire) {
- writeAttributionNodesToEvent(event, uids);
- event->write(wl);
- event->write(acquire);
- event->init();
-}
+// TODO(b/149590301): Update this helper to use new socket schema.
+//void makeWakeLockEvent(
+// LogEvent* event, const std::vector<int> &uids, const string& wl, int acquire) {
+// writeAttributionNodesToEvent(event, uids);
+// event->write(wl);
+// event->write(acquire);
+// event->init();
+//}
std::map<int64_t, HashableDimensionKey> getWakeLockQueryKey(
const Position position,
@@ -264,377 +265,378 @@
EXPECT_TRUE(changedCache[0]);
}
-TEST(SimpleConditionTrackerTest, TestSlicedCondition) {
- std::vector<sp<ConditionTracker>> allConditions;
- for (Position position :
- { Position::FIRST, Position::LAST}) {
-
- SimplePredicate simplePredicate = getWakeLockHeldCondition(
- true /*nesting*/, true /*default to false*/, true /*output slice by uid*/,
- position);
- string conditionName = "WL_HELD_BY_UID2";
-
- unordered_map<int64_t, int> trackerNameIndexMap;
- trackerNameIndexMap[StringToId("WAKE_LOCK_ACQUIRE")] = 0;
- trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
- trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
-
- SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
- 0 /*condition tracker index*/, simplePredicate,
- trackerNameIndexMap);
-
- std::vector<int> uids = {111, 222, 333};
-
- LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
- makeWakeLockEvent(&event, uids, "wl1", 1);
-
- // one matched start
- vector<MatchingState> matcherState;
- matcherState.push_back(MatchingState::kMatched);
- matcherState.push_back(MatchingState::kNotMatched);
- matcherState.push_back(MatchingState::kNotMatched);
- vector<sp<ConditionTracker>> allPredicates;
- vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
- vector<bool> changedCache(1, false);
-
- conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
- changedCache);
-
- if (position == Position::FIRST ||
- position == Position::LAST) {
- EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
- } else {
- EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
- }
- EXPECT_TRUE(changedCache[0]);
- if (position == Position::FIRST ||
- position == Position::LAST) {
- EXPECT_EQ(conditionTracker.getChangedToTrueDimensions(allConditions)->size(), 1u);
- EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
- } else {
- EXPECT_EQ(conditionTracker.getChangedToTrueDimensions(allConditions)->size(), uids.size());
- }
-
- // Now test query
- const auto queryKey = getWakeLockQueryKey(position, uids, conditionName);
- conditionCache[0] = ConditionState::kNotEvaluated;
-
- conditionTracker.isConditionMet(queryKey, allPredicates,
- false,
- conditionCache);
- EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
-
- // another wake lock acquired by this uid
- LogEvent event2(1 /*tagId*/, 0 /*timestamp*/);
- makeWakeLockEvent(&event2, uids, "wl2", 1);
- matcherState.clear();
- matcherState.push_back(MatchingState::kMatched);
- matcherState.push_back(MatchingState::kNotMatched);
- conditionCache[0] = ConditionState::kNotEvaluated;
- changedCache[0] = false;
- conditionTracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache,
- changedCache);
- EXPECT_FALSE(changedCache[0]);
- if (position == Position::FIRST ||
- position == Position::LAST) {
- EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
- } else {
- EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
- }
- EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
- EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
-
-
- // wake lock 1 release
- LogEvent event3(1 /*tagId*/, 0 /*timestamp*/);
- makeWakeLockEvent(&event3, uids, "wl1", 0); // now release it.
- matcherState.clear();
- matcherState.push_back(MatchingState::kNotMatched);
- matcherState.push_back(MatchingState::kMatched);
- conditionCache[0] = ConditionState::kNotEvaluated;
- changedCache[0] = false;
- conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache,
- changedCache);
- // nothing changes, because wake lock 2 is still held for this uid
- EXPECT_FALSE(changedCache[0]);
- if (position == Position::FIRST ||
- position == Position::LAST) {
- EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
- } else {
- EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
- }
- EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
- EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
-
- LogEvent event4(1 /*tagId*/, 0 /*timestamp*/);
- makeWakeLockEvent(&event4, uids, "wl2", 0); // now release it.
- matcherState.clear();
- matcherState.push_back(MatchingState::kNotMatched);
- matcherState.push_back(MatchingState::kMatched);
- conditionCache[0] = ConditionState::kNotEvaluated;
- changedCache[0] = false;
- conditionTracker.evaluateCondition(event4, matcherState, allPredicates, conditionCache,
- changedCache);
- EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
- EXPECT_TRUE(changedCache[0]);
- if (position == Position::FIRST ||
- position == Position::LAST) {
- EXPECT_EQ(conditionTracker.getChangedToFalseDimensions(allConditions)->size(), 1u);
- EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
- } else {
- EXPECT_EQ(conditionTracker.getChangedToFalseDimensions(allConditions)->size(), uids.size());
- }
-
- // query again
- conditionCache[0] = ConditionState::kNotEvaluated;
- conditionTracker.isConditionMet(queryKey, allPredicates,
- false,
- conditionCache);
- EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
- }
-
-}
-
-TEST(SimpleConditionTrackerTest, TestSlicedWithNoOutputDim) {
- std::vector<sp<ConditionTracker>> allConditions;
-
- SimplePredicate simplePredicate = getWakeLockHeldCondition(
- true /*nesting*/, true /*default to false*/, false /*slice output by uid*/,
- Position::ANY /* position */);
- string conditionName = "WL_HELD";
-
- unordered_map<int64_t, int> trackerNameIndexMap;
- trackerNameIndexMap[StringToId("WAKE_LOCK_ACQUIRE")] = 0;
- trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
- trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
-
- SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
- 0 /*condition tracker index*/, simplePredicate,
- trackerNameIndexMap);
-
- EXPECT_FALSE(conditionTracker.isSliced());
-
- std::vector<int> uid_list1 = {111, 1111, 11111};
- string uid1_wl1 = "wl1_1";
- std::vector<int> uid_list2 = {222, 2222, 22222};
- string uid2_wl1 = "wl2_1";
-
- LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
- makeWakeLockEvent(&event, uid_list1, uid1_wl1, 1);
-
- // one matched start for uid1
- vector<MatchingState> matcherState;
- matcherState.push_back(MatchingState::kMatched);
- matcherState.push_back(MatchingState::kNotMatched);
- matcherState.push_back(MatchingState::kNotMatched);
- vector<sp<ConditionTracker>> allPredicates;
- vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
- vector<bool> changedCache(1, false);
-
- conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
- changedCache);
-
- EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
- EXPECT_TRUE(changedCache[0]);
-
- // Now test query
- ConditionKey queryKey;
- conditionCache[0] = ConditionState::kNotEvaluated;
-
- conditionTracker.isConditionMet(queryKey, allPredicates,
- true,
- conditionCache);
- EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
-
- // another wake lock acquired by this uid
- LogEvent event2(1 /*tagId*/, 0 /*timestamp*/);
- makeWakeLockEvent(&event2, uid_list2, uid2_wl1, 1);
- matcherState.clear();
- matcherState.push_back(MatchingState::kMatched);
- matcherState.push_back(MatchingState::kNotMatched);
- conditionCache[0] = ConditionState::kNotEvaluated;
- changedCache[0] = false;
- conditionTracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache,
- changedCache);
- EXPECT_FALSE(changedCache[0]);
-
- // uid1 wake lock 1 release
- LogEvent event3(1 /*tagId*/, 0 /*timestamp*/);
- makeWakeLockEvent(&event3, uid_list1, uid1_wl1, 0); // now release it.
- matcherState.clear();
- matcherState.push_back(MatchingState::kNotMatched);
- matcherState.push_back(MatchingState::kMatched);
- conditionCache[0] = ConditionState::kNotEvaluated;
- changedCache[0] = false;
- conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache,
- changedCache);
- // nothing changes, because uid2 is still holding wl.
- EXPECT_FALSE(changedCache[0]);
-
- LogEvent event4(1 /*tagId*/, 0 /*timestamp*/);
- makeWakeLockEvent(&event4, uid_list2, uid2_wl1, 0); // now release it.
- matcherState.clear();
- matcherState.push_back(MatchingState::kNotMatched);
- matcherState.push_back(MatchingState::kMatched);
- conditionCache[0] = ConditionState::kNotEvaluated;
- changedCache[0] = false;
- conditionTracker.evaluateCondition(event4, matcherState, allPredicates, conditionCache,
- changedCache);
- EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
- EXPECT_TRUE(changedCache[0]);
-
- // query again
- conditionCache[0] = ConditionState::kNotEvaluated;
- conditionTracker.isConditionMet(queryKey, allPredicates,
- true,
- conditionCache);
- EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
-}
-
-TEST(SimpleConditionTrackerTest, TestStopAll) {
- std::vector<sp<ConditionTracker>> allConditions;
- for (Position position :
- { Position::FIRST, Position::LAST }) {
- SimplePredicate simplePredicate = getWakeLockHeldCondition(
- true /*nesting*/, true /*default to false*/, true /*output slice by uid*/,
- position);
- string conditionName = "WL_HELD_BY_UID3";
-
- unordered_map<int64_t, int> trackerNameIndexMap;
- trackerNameIndexMap[StringToId("WAKE_LOCK_ACQUIRE")] = 0;
- trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
- trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
-
- SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
- 0 /*condition tracker index*/, simplePredicate,
- trackerNameIndexMap);
-
- std::vector<int> uid_list1 = {111, 1111, 11111};
- std::vector<int> uid_list2 = {222, 2222, 22222};
-
- LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
- makeWakeLockEvent(&event, uid_list1, "wl1", 1);
-
- // one matched start
- vector<MatchingState> matcherState;
- matcherState.push_back(MatchingState::kMatched);
- matcherState.push_back(MatchingState::kNotMatched);
- matcherState.push_back(MatchingState::kNotMatched);
- vector<sp<ConditionTracker>> allPredicates;
- vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
- vector<bool> changedCache(1, false);
-
- conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
- changedCache);
- if (position == Position::FIRST ||
- position == Position::LAST) {
- EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
- } else {
- EXPECT_EQ(uid_list1.size(), conditionTracker.mSlicedConditionState.size());
- }
- EXPECT_TRUE(changedCache[0]);
- {
- if (position == Position::FIRST ||
- position == Position::LAST) {
- EXPECT_EQ(1UL, conditionTracker.getChangedToTrueDimensions(allConditions)->size());
- EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
- } else {
- EXPECT_EQ(uid_list1.size(), conditionTracker.getChangedToTrueDimensions(allConditions)->size());
- EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
- }
- }
-
- // Now test query
- const auto queryKey = getWakeLockQueryKey(position, uid_list1, conditionName);
- conditionCache[0] = ConditionState::kNotEvaluated;
-
- conditionTracker.isConditionMet(queryKey, allPredicates,
- false,
- conditionCache);
- EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
-
- // another wake lock acquired by uid2
- LogEvent event2(1 /*tagId*/, 0 /*timestamp*/);
- makeWakeLockEvent(&event2, uid_list2, "wl2", 1);
- matcherState.clear();
- matcherState.push_back(MatchingState::kMatched);
- matcherState.push_back(MatchingState::kNotMatched);
- matcherState.push_back(MatchingState::kNotMatched);
- conditionCache[0] = ConditionState::kNotEvaluated;
- changedCache[0] = false;
- conditionTracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache,
- changedCache);
- if (position == Position::FIRST ||
- position == Position::LAST) {
- EXPECT_EQ(2UL, conditionTracker.mSlicedConditionState.size());
- } else {
- EXPECT_EQ(uid_list1.size() + uid_list2.size(),
- conditionTracker.mSlicedConditionState.size());
- }
- EXPECT_TRUE(changedCache[0]);
- {
- if (position == Position::FIRST ||
- position == Position::LAST) {
- EXPECT_EQ(1UL, conditionTracker.getChangedToTrueDimensions(allConditions)->size());
- EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
- } else {
- EXPECT_EQ(uid_list2.size(), conditionTracker.getChangedToTrueDimensions(allConditions)->size());
- EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
- }
- }
-
-
- // TEST QUERY
- const auto queryKey2 = getWakeLockQueryKey(position, uid_list2, conditionName);
- conditionCache[0] = ConditionState::kNotEvaluated;
- conditionTracker.isConditionMet(queryKey, allPredicates,
- false,
- conditionCache);
-
- EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
-
-
- // stop all event
- LogEvent event3(2 /*tagId*/, 0 /*timestamp*/);
- matcherState.clear();
- matcherState.push_back(MatchingState::kNotMatched);
- matcherState.push_back(MatchingState::kNotMatched);
- matcherState.push_back(MatchingState::kMatched);
-
- conditionCache[0] = ConditionState::kNotEvaluated;
- changedCache[0] = false;
- conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache,
- changedCache);
- EXPECT_TRUE(changedCache[0]);
- EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
- {
- if (position == Position::FIRST || position == Position::LAST) {
- EXPECT_EQ(2UL, conditionTracker.getChangedToFalseDimensions(allConditions)->size());
- EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
- } else {
- EXPECT_EQ(uid_list1.size() + uid_list2.size(),
- conditionTracker.getChangedToFalseDimensions(allConditions)->size());
- EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
- }
- }
-
- // TEST QUERY
- const auto queryKey3 = getWakeLockQueryKey(position, uid_list1, conditionName);
- conditionCache[0] = ConditionState::kNotEvaluated;
- conditionTracker.isConditionMet(queryKey, allPredicates,
- false,
- conditionCache);
- EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
-
- // TEST QUERY
- const auto queryKey4 = getWakeLockQueryKey(position, uid_list2, conditionName);
- conditionCache[0] = ConditionState::kNotEvaluated;
- conditionTracker.isConditionMet(queryKey, allPredicates,
- false,
- conditionCache);
- EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
- }
-}
+// TODO(b/149590301): Update these tests to use new socket schema.
+//TEST(SimpleConditionTrackerTest, TestSlicedCondition) {
+// std::vector<sp<ConditionTracker>> allConditions;
+// for (Position position :
+// { Position::FIRST, Position::LAST}) {
+//
+// SimplePredicate simplePredicate = getWakeLockHeldCondition(
+// true /*nesting*/, true /*default to false*/, true /*output slice by uid*/,
+// position);
+// string conditionName = "WL_HELD_BY_UID2";
+//
+// unordered_map<int64_t, int> trackerNameIndexMap;
+// trackerNameIndexMap[StringToId("WAKE_LOCK_ACQUIRE")] = 0;
+// trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
+// trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
+//
+// SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
+// 0 /*condition tracker index*/, simplePredicate,
+// trackerNameIndexMap);
+//
+// std::vector<int> uids = {111, 222, 333};
+//
+// LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
+// makeWakeLockEvent(&event, uids, "wl1", 1);
+//
+// // one matched start
+// vector<MatchingState> matcherState;
+// matcherState.push_back(MatchingState::kMatched);
+// matcherState.push_back(MatchingState::kNotMatched);
+// matcherState.push_back(MatchingState::kNotMatched);
+// vector<sp<ConditionTracker>> allPredicates;
+// vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
+// vector<bool> changedCache(1, false);
+//
+// conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
+// changedCache);
+//
+// if (position == Position::FIRST ||
+// position == Position::LAST) {
+// EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
+// } else {
+// EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
+// }
+// EXPECT_TRUE(changedCache[0]);
+// if (position == Position::FIRST ||
+// position == Position::LAST) {
+// EXPECT_EQ(conditionTracker.getChangedToTrueDimensions(allConditions)->size(), 1u);
+// EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
+// } else {
+// EXPECT_EQ(conditionTracker.getChangedToTrueDimensions(allConditions)->size(), uids.size());
+// }
+//
+// // Now test query
+// const auto queryKey = getWakeLockQueryKey(position, uids, conditionName);
+// conditionCache[0] = ConditionState::kNotEvaluated;
+//
+// conditionTracker.isConditionMet(queryKey, allPredicates,
+// false,
+// conditionCache);
+// EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
+//
+// // another wake lock acquired by this uid
+// LogEvent event2(1 /*tagId*/, 0 /*timestamp*/);
+// makeWakeLockEvent(&event2, uids, "wl2", 1);
+// matcherState.clear();
+// matcherState.push_back(MatchingState::kMatched);
+// matcherState.push_back(MatchingState::kNotMatched);
+// conditionCache[0] = ConditionState::kNotEvaluated;
+// changedCache[0] = false;
+// conditionTracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache,
+// changedCache);
+// EXPECT_FALSE(changedCache[0]);
+// if (position == Position::FIRST ||
+// position == Position::LAST) {
+// EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
+// } else {
+// EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
+// }
+// EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
+// EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
+//
+//
+// // wake lock 1 release
+// LogEvent event3(1 /*tagId*/, 0 /*timestamp*/);
+// makeWakeLockEvent(&event3, uids, "wl1", 0); // now release it.
+// matcherState.clear();
+// matcherState.push_back(MatchingState::kNotMatched);
+// matcherState.push_back(MatchingState::kMatched);
+// conditionCache[0] = ConditionState::kNotEvaluated;
+// changedCache[0] = false;
+// conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache,
+// changedCache);
+// // nothing changes, because wake lock 2 is still held for this uid
+// EXPECT_FALSE(changedCache[0]);
+// if (position == Position::FIRST ||
+// position == Position::LAST) {
+// EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
+// } else {
+// EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
+// }
+// EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
+// EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
+//
+// LogEvent event4(1 /*tagId*/, 0 /*timestamp*/);
+// makeWakeLockEvent(&event4, uids, "wl2", 0); // now release it.
+// matcherState.clear();
+// matcherState.push_back(MatchingState::kNotMatched);
+// matcherState.push_back(MatchingState::kMatched);
+// conditionCache[0] = ConditionState::kNotEvaluated;
+// changedCache[0] = false;
+// conditionTracker.evaluateCondition(event4, matcherState, allPredicates, conditionCache,
+// changedCache);
+// EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
+// EXPECT_TRUE(changedCache[0]);
+// if (position == Position::FIRST ||
+// position == Position::LAST) {
+// EXPECT_EQ(conditionTracker.getChangedToFalseDimensions(allConditions)->size(), 1u);
+// EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
+// } else {
+// EXPECT_EQ(conditionTracker.getChangedToFalseDimensions(allConditions)->size(), uids.size());
+// }
+//
+// // query again
+// conditionCache[0] = ConditionState::kNotEvaluated;
+// conditionTracker.isConditionMet(queryKey, allPredicates,
+// false,
+// conditionCache);
+// EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
+// }
+//
+//}
+//
+//TEST(SimpleConditionTrackerTest, TestSlicedWithNoOutputDim) {
+// std::vector<sp<ConditionTracker>> allConditions;
+//
+// SimplePredicate simplePredicate = getWakeLockHeldCondition(
+// true /*nesting*/, true /*default to false*/, false /*slice output by uid*/,
+// Position::ANY /* position */);
+// string conditionName = "WL_HELD";
+//
+// unordered_map<int64_t, int> trackerNameIndexMap;
+// trackerNameIndexMap[StringToId("WAKE_LOCK_ACQUIRE")] = 0;
+// trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
+// trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
+//
+// SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
+// 0 /*condition tracker index*/, simplePredicate,
+// trackerNameIndexMap);
+//
+// EXPECT_FALSE(conditionTracker.isSliced());
+//
+// std::vector<int> uid_list1 = {111, 1111, 11111};
+// string uid1_wl1 = "wl1_1";
+// std::vector<int> uid_list2 = {222, 2222, 22222};
+// string uid2_wl1 = "wl2_1";
+//
+// LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
+// makeWakeLockEvent(&event, uid_list1, uid1_wl1, 1);
+//
+// // one matched start for uid1
+// vector<MatchingState> matcherState;
+// matcherState.push_back(MatchingState::kMatched);
+// matcherState.push_back(MatchingState::kNotMatched);
+// matcherState.push_back(MatchingState::kNotMatched);
+// vector<sp<ConditionTracker>> allPredicates;
+// vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
+// vector<bool> changedCache(1, false);
+//
+// conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
+// changedCache);
+//
+// EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
+// EXPECT_TRUE(changedCache[0]);
+//
+// // Now test query
+// ConditionKey queryKey;
+// conditionCache[0] = ConditionState::kNotEvaluated;
+//
+// conditionTracker.isConditionMet(queryKey, allPredicates,
+// true,
+// conditionCache);
+// EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
+//
+// // another wake lock acquired by this uid
+// LogEvent event2(1 /*tagId*/, 0 /*timestamp*/);
+// makeWakeLockEvent(&event2, uid_list2, uid2_wl1, 1);
+// matcherState.clear();
+// matcherState.push_back(MatchingState::kMatched);
+// matcherState.push_back(MatchingState::kNotMatched);
+// conditionCache[0] = ConditionState::kNotEvaluated;
+// changedCache[0] = false;
+// conditionTracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache,
+// changedCache);
+// EXPECT_FALSE(changedCache[0]);
+//
+// // uid1 wake lock 1 release
+// LogEvent event3(1 /*tagId*/, 0 /*timestamp*/);
+// makeWakeLockEvent(&event3, uid_list1, uid1_wl1, 0); // now release it.
+// matcherState.clear();
+// matcherState.push_back(MatchingState::kNotMatched);
+// matcherState.push_back(MatchingState::kMatched);
+// conditionCache[0] = ConditionState::kNotEvaluated;
+// changedCache[0] = false;
+// conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache,
+// changedCache);
+// // nothing changes, because uid2 is still holding wl.
+// EXPECT_FALSE(changedCache[0]);
+//
+// LogEvent event4(1 /*tagId*/, 0 /*timestamp*/);
+// makeWakeLockEvent(&event4, uid_list2, uid2_wl1, 0); // now release it.
+// matcherState.clear();
+// matcherState.push_back(MatchingState::kNotMatched);
+// matcherState.push_back(MatchingState::kMatched);
+// conditionCache[0] = ConditionState::kNotEvaluated;
+// changedCache[0] = false;
+// conditionTracker.evaluateCondition(event4, matcherState, allPredicates, conditionCache,
+// changedCache);
+// EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
+// EXPECT_TRUE(changedCache[0]);
+//
+// // query again
+// conditionCache[0] = ConditionState::kNotEvaluated;
+// conditionTracker.isConditionMet(queryKey, allPredicates,
+// true,
+// conditionCache);
+// EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
+//}
+//
+//TEST(SimpleConditionTrackerTest, TestStopAll) {
+// std::vector<sp<ConditionTracker>> allConditions;
+// for (Position position :
+// { Position::FIRST, Position::LAST }) {
+// SimplePredicate simplePredicate = getWakeLockHeldCondition(
+// true /*nesting*/, true /*default to false*/, true /*output slice by uid*/,
+// position);
+// string conditionName = "WL_HELD_BY_UID3";
+//
+// unordered_map<int64_t, int> trackerNameIndexMap;
+// trackerNameIndexMap[StringToId("WAKE_LOCK_ACQUIRE")] = 0;
+// trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
+// trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
+//
+// SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
+// 0 /*condition tracker index*/, simplePredicate,
+// trackerNameIndexMap);
+//
+// std::vector<int> uid_list1 = {111, 1111, 11111};
+// std::vector<int> uid_list2 = {222, 2222, 22222};
+//
+// LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
+// makeWakeLockEvent(&event, uid_list1, "wl1", 1);
+//
+// // one matched start
+// vector<MatchingState> matcherState;
+// matcherState.push_back(MatchingState::kMatched);
+// matcherState.push_back(MatchingState::kNotMatched);
+// matcherState.push_back(MatchingState::kNotMatched);
+// vector<sp<ConditionTracker>> allPredicates;
+// vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
+// vector<bool> changedCache(1, false);
+//
+// conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
+// changedCache);
+// if (position == Position::FIRST ||
+// position == Position::LAST) {
+// EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
+// } else {
+// EXPECT_EQ(uid_list1.size(), conditionTracker.mSlicedConditionState.size());
+// }
+// EXPECT_TRUE(changedCache[0]);
+// {
+// if (position == Position::FIRST ||
+// position == Position::LAST) {
+// EXPECT_EQ(1UL, conditionTracker.getChangedToTrueDimensions(allConditions)->size());
+// EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
+// } else {
+// EXPECT_EQ(uid_list1.size(), conditionTracker.getChangedToTrueDimensions(allConditions)->size());
+// EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
+// }
+// }
+//
+// // Now test query
+// const auto queryKey = getWakeLockQueryKey(position, uid_list1, conditionName);
+// conditionCache[0] = ConditionState::kNotEvaluated;
+//
+// conditionTracker.isConditionMet(queryKey, allPredicates,
+// false,
+// conditionCache);
+// EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
+//
+// // another wake lock acquired by uid2
+// LogEvent event2(1 /*tagId*/, 0 /*timestamp*/);
+// makeWakeLockEvent(&event2, uid_list2, "wl2", 1);
+// matcherState.clear();
+// matcherState.push_back(MatchingState::kMatched);
+// matcherState.push_back(MatchingState::kNotMatched);
+// matcherState.push_back(MatchingState::kNotMatched);
+// conditionCache[0] = ConditionState::kNotEvaluated;
+// changedCache[0] = false;
+// conditionTracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache,
+// changedCache);
+// if (position == Position::FIRST ||
+// position == Position::LAST) {
+// EXPECT_EQ(2UL, conditionTracker.mSlicedConditionState.size());
+// } else {
+// EXPECT_EQ(uid_list1.size() + uid_list2.size(),
+// conditionTracker.mSlicedConditionState.size());
+// }
+// EXPECT_TRUE(changedCache[0]);
+// {
+// if (position == Position::FIRST ||
+// position == Position::LAST) {
+// EXPECT_EQ(1UL, conditionTracker.getChangedToTrueDimensions(allConditions)->size());
+// EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
+// } else {
+// EXPECT_EQ(uid_list2.size(), conditionTracker.getChangedToTrueDimensions(allConditions)->size());
+// EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
+// }
+// }
+//
+//
+// // TEST QUERY
+// const auto queryKey2 = getWakeLockQueryKey(position, uid_list2, conditionName);
+// conditionCache[0] = ConditionState::kNotEvaluated;
+// conditionTracker.isConditionMet(queryKey, allPredicates,
+// false,
+// conditionCache);
+//
+// EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
+//
+//
+// // stop all event
+// LogEvent event3(2 /*tagId*/, 0 /*timestamp*/);
+// matcherState.clear();
+// matcherState.push_back(MatchingState::kNotMatched);
+// matcherState.push_back(MatchingState::kNotMatched);
+// matcherState.push_back(MatchingState::kMatched);
+//
+// conditionCache[0] = ConditionState::kNotEvaluated;
+// changedCache[0] = false;
+// conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache,
+// changedCache);
+// EXPECT_TRUE(changedCache[0]);
+// EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
+// {
+// if (position == Position::FIRST || position == Position::LAST) {
+// EXPECT_EQ(2UL, conditionTracker.getChangedToFalseDimensions(allConditions)->size());
+// EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
+// } else {
+// EXPECT_EQ(uid_list1.size() + uid_list2.size(),
+// conditionTracker.getChangedToFalseDimensions(allConditions)->size());
+// EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
+// }
+// }
+//
+// // TEST QUERY
+// const auto queryKey3 = getWakeLockQueryKey(position, uid_list1, conditionName);
+// conditionCache[0] = ConditionState::kNotEvaluated;
+// conditionTracker.isConditionMet(queryKey, allPredicates,
+// false,
+// conditionCache);
+// EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
+//
+// // TEST QUERY
+// const auto queryKey4 = getWakeLockQueryKey(position, uid_list2, conditionName);
+// conditionCache[0] = ConditionState::kNotEvaluated;
+// conditionTracker.isConditionMet(queryKey, allPredicates,
+// false,
+// conditionCache);
+// EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
+// }
+//}
} // namespace statsd
} // namespace os
diff --git a/cmds/statsd/tests/condition/StateConditionTracker_test.cpp b/cmds/statsd/tests/condition/StateConditionTracker_test.cpp
index fbf6efd..86b50ae8 100644
--- a/cmds/statsd/tests/condition/StateConditionTracker_test.cpp
+++ b/cmds/statsd/tests/condition/StateConditionTracker_test.cpp
@@ -44,65 +44,66 @@
return simplePredicate;
}
-void makeUidProcStateEvent(int32_t uid, int32_t state, LogEvent* event) {
- event->write(uid);
- event->write(state);
- event->init();
-}
-
-TEST(StateConditionTrackerTest, TestStateChange) {
- int uid1 = 111;
- int uid2 = 222;
-
- int state1 = 1001;
- int state2 = 1002;
- unordered_map<int64_t, int> trackerNameIndexMap;
- trackerNameIndexMap[StringToId("UidProcState")] = 0;
- vector<Matcher> primaryFields;
- primaryFields.push_back(getSimpleMatcher(kUidProcTag, 1));
- StateConditionTracker tracker(ConfigKey(12, 123), 123, 0, getUidProcStatePredicate(),
- trackerNameIndexMap, primaryFields);
-
- LogEvent event(kUidProcTag, 0 /*timestamp*/);
- makeUidProcStateEvent(uid1, state1, &event);
-
- vector<MatchingState> matcherState;
- matcherState.push_back(MatchingState::kMatched);
- vector<sp<ConditionTracker>> allPredicates;
- vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
- vector<bool> changedCache(1, false);
-
- tracker.evaluateCondition(event, matcherState, allPredicates, conditionCache, changedCache);
- EXPECT_EQ(1ULL, tracker.mLastChangedToTrueDimensions.size());
- EXPECT_EQ(0ULL, tracker.mLastChangedToFalseDimensions.size());
- EXPECT_TRUE(changedCache[0]);
-
- changedCache[0] = false;
- conditionCache[0] = ConditionState::kNotEvaluated;
- tracker.evaluateCondition(event, matcherState, allPredicates, conditionCache, changedCache);
- EXPECT_EQ(0ULL, tracker.mLastChangedToTrueDimensions.size());
- EXPECT_EQ(0ULL, tracker.mLastChangedToFalseDimensions.size());
- EXPECT_FALSE(changedCache[0]);
-
- LogEvent event2(kUidProcTag, 0 /*timestamp*/);
- makeUidProcStateEvent(uid1, state2, &event2);
-
- changedCache[0] = false;
- conditionCache[0] = ConditionState::kNotEvaluated;
- tracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache, changedCache);
- EXPECT_EQ(1ULL, tracker.mLastChangedToTrueDimensions.size());
- EXPECT_EQ(1ULL, tracker.mLastChangedToFalseDimensions.size());
- EXPECT_TRUE(changedCache[0]);
-
- LogEvent event3(kUidProcTag, 0 /*timestamp*/);
- makeUidProcStateEvent(uid2, state1, &event3);
- changedCache[0] = false;
- conditionCache[0] = ConditionState::kNotEvaluated;
- tracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache, changedCache);
- EXPECT_EQ(1ULL, tracker.mLastChangedToTrueDimensions.size());
- EXPECT_EQ(0ULL, tracker.mLastChangedToFalseDimensions.size());
- EXPECT_TRUE(changedCache[0]);
-}
+// TODO(b/149590301): Update these tests to use new socket schema.
+//void makeUidProcStateEvent(int32_t uid, int32_t state, LogEvent* event) {
+// event->write(uid);
+// event->write(state);
+// event->init();
+//}
+//
+//TEST(StateConditionTrackerTest, TestStateChange) {
+// int uid1 = 111;
+// int uid2 = 222;
+//
+// int state1 = 1001;
+// int state2 = 1002;
+// unordered_map<int64_t, int> trackerNameIndexMap;
+// trackerNameIndexMap[StringToId("UidProcState")] = 0;
+// vector<Matcher> primaryFields;
+// primaryFields.push_back(getSimpleMatcher(kUidProcTag, 1));
+// StateConditionTracker tracker(ConfigKey(12, 123), 123, 0, getUidProcStatePredicate(),
+// trackerNameIndexMap, primaryFields);
+//
+// LogEvent event(kUidProcTag, 0 /*timestamp*/);
+// makeUidProcStateEvent(uid1, state1, &event);
+//
+// vector<MatchingState> matcherState;
+// matcherState.push_back(MatchingState::kMatched);
+// vector<sp<ConditionTracker>> allPredicates;
+// vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
+// vector<bool> changedCache(1, false);
+//
+// tracker.evaluateCondition(event, matcherState, allPredicates, conditionCache, changedCache);
+// EXPECT_EQ(1ULL, tracker.mLastChangedToTrueDimensions.size());
+// EXPECT_EQ(0ULL, tracker.mLastChangedToFalseDimensions.size());
+// EXPECT_TRUE(changedCache[0]);
+//
+// changedCache[0] = false;
+// conditionCache[0] = ConditionState::kNotEvaluated;
+// tracker.evaluateCondition(event, matcherState, allPredicates, conditionCache, changedCache);
+// EXPECT_EQ(0ULL, tracker.mLastChangedToTrueDimensions.size());
+// EXPECT_EQ(0ULL, tracker.mLastChangedToFalseDimensions.size());
+// EXPECT_FALSE(changedCache[0]);
+//
+// LogEvent event2(kUidProcTag, 0 /*timestamp*/);
+// makeUidProcStateEvent(uid1, state2, &event2);
+//
+// changedCache[0] = false;
+// conditionCache[0] = ConditionState::kNotEvaluated;
+// tracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache, changedCache);
+// EXPECT_EQ(1ULL, tracker.mLastChangedToTrueDimensions.size());
+// EXPECT_EQ(1ULL, tracker.mLastChangedToFalseDimensions.size());
+// EXPECT_TRUE(changedCache[0]);
+//
+// LogEvent event3(kUidProcTag, 0 /*timestamp*/);
+// makeUidProcStateEvent(uid2, state1, &event3);
+// changedCache[0] = false;
+// conditionCache[0] = ConditionState::kNotEvaluated;
+// tracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache, changedCache);
+// EXPECT_EQ(1ULL, tracker.mLastChangedToTrueDimensions.size());
+// EXPECT_EQ(0ULL, tracker.mLastChangedToFalseDimensions.size());
+// EXPECT_TRUE(changedCache[0]);
+//}
} // namespace statsd
} // namespace os
diff --git a/cmds/statsd/tests/e2e/Anomaly_count_e2e_test.cpp b/cmds/statsd/tests/e2e/Anomaly_count_e2e_test.cpp
index c78d99e..1eaaf08 100644
--- a/cmds/statsd/tests/e2e/Anomaly_count_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/Anomaly_count_e2e_test.cpp
@@ -53,184 +53,185 @@
} // namespace
-TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_single_bucket) {
- const int num_buckets = 1;
- const int threshold = 3;
- auto config = CreateStatsdConfig(num_buckets, threshold);
- const uint64_t alert_id = config.alert(0).id();
- const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
-
- int64_t bucketStartTimeNs = 10000000000;
- int64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
-
- ConfigKey cfgKey;
- auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
- EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
- EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
- EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
-
- sp<AnomalyTracker> anomalyTracker =
- processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
-
- std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
- std::vector<AttributionNodeInternal> attributions2 = {
- CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1")};
- std::vector<AttributionNodeInternal> attributions3 = {
- CreateAttribution(111, "App1"), CreateAttribution(333, "App3")};
- std::vector<AttributionNodeInternal> attributions4 = {
- CreateAttribution(222, "GMSCoreModule1"), CreateAttribution(333, "App3")};
- std::vector<AttributionNodeInternal> attributions5 = {
- CreateAttribution(222, "GMSCoreModule1") };
-
- FieldValue fieldValue1(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
- Value((int32_t)111));
- HashableDimensionKey whatKey1({fieldValue1});
- MetricDimensionKey dimensionKey1(whatKey1, DEFAULT_DIMENSION_KEY);
-
- FieldValue fieldValue2(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
- Value((int32_t)222));
- HashableDimensionKey whatKey2({fieldValue2});
- MetricDimensionKey dimensionKey2(whatKey2, DEFAULT_DIMENSION_KEY);
-
- auto event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 2);
- processor->OnLogEvent(event.get());
- EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
-
- event = CreateAcquireWakelockEvent(attributions4, "wl2", bucketStartTimeNs + 2);
- processor->OnLogEvent(event.get());
- EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
-
- event = CreateAcquireWakelockEvent(attributions2, "wl1", bucketStartTimeNs + 3);
- processor->OnLogEvent(event.get());
- EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
-
- event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + 3);
- processor->OnLogEvent(event.get());
- EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
-
- event = CreateAcquireWakelockEvent(attributions3, "wl1", bucketStartTimeNs + 4);
- processor->OnLogEvent(event.get());
- EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
-
- event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + 4);
- processor->OnLogEvent(event.get());
- EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
-
- // Fired alarm and refractory period end timestamp updated.
- event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 5);
- processor->OnLogEvent(event.get());
- EXPECT_EQ(refractory_period_sec + bucketStartTimeNs / NS_PER_SEC + 1,
- anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
-
- event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 100);
- processor->OnLogEvent(event.get());
- EXPECT_EQ(refractory_period_sec + bucketStartTimeNs / NS_PER_SEC + 1,
- anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
-
- event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs - 1);
- processor->OnLogEvent(event.get());
- EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs - 1) / NS_PER_SEC + 1,
- anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
-
- event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 1);
- processor->OnLogEvent(event.get());
- EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs - 1) / NS_PER_SEC + 1,
- anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
-
- event = CreateAcquireWakelockEvent(attributions4, "wl2", bucketStartTimeNs + bucketSizeNs + 1);
- processor->OnLogEvent(event.get());
- EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
-
- event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + bucketSizeNs + 2);
- processor->OnLogEvent(event.get());
- EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
-
- event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + bucketSizeNs + 3);
- processor->OnLogEvent(event.get());
- EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
-
- event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + bucketSizeNs + 4);
- processor->OnLogEvent(event.get());
- EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 4) / NS_PER_SEC + 1,
- anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
-}
-
-TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_multiple_buckets) {
- const int num_buckets = 3;
- const int threshold = 3;
- auto config = CreateStatsdConfig(num_buckets, threshold);
- const uint64_t alert_id = config.alert(0).id();
- const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
-
- int64_t bucketStartTimeNs = 10000000000;
- int64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
-
- ConfigKey cfgKey;
- auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
- EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
- EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
- EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
-
- sp<AnomalyTracker> anomalyTracker =
- processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
-
- std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
- std::vector<AttributionNodeInternal> attributions2 = {
- CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1")};
- std::vector<AttributionNodeInternal> attributions3 = {
- CreateAttribution(111, "App1"), CreateAttribution(333, "App3")};
- std::vector<AttributionNodeInternal> attributions4 = {
- CreateAttribution(222, "GMSCoreModule1"), CreateAttribution(333, "App3")};
- std::vector<AttributionNodeInternal> attributions5 = {
- CreateAttribution(222, "GMSCoreModule1") };
-
- FieldValue fieldValue1(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
- Value((int32_t)111));
- HashableDimensionKey whatKey1({fieldValue1});
- MetricDimensionKey dimensionKey1(whatKey1, DEFAULT_DIMENSION_KEY);
-
- FieldValue fieldValue2(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
- Value((int32_t)222));
- HashableDimensionKey whatKey2({fieldValue2});
- MetricDimensionKey dimensionKey2(whatKey2, DEFAULT_DIMENSION_KEY);
-
- auto event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 2);
- processor->OnLogEvent(event.get());
- EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
-
- event = CreateAcquireWakelockEvent(attributions2, "wl1", bucketStartTimeNs + 3);
- processor->OnLogEvent(event.get());
- EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
-
- // Fired alarm and refractory period end timestamp updated.
- event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 4);
- processor->OnLogEvent(event.get());
- EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
-
- event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 1);
- processor->OnLogEvent(event.get());
- EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 1) / NS_PER_SEC + 1,
- anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
-
- event = CreateAcquireWakelockEvent(attributions2, "wl1", bucketStartTimeNs + bucketSizeNs + 2);
- processor->OnLogEvent(event.get());
- EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 1) / NS_PER_SEC + 1,
- anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
-
- event = CreateAcquireWakelockEvent(
- attributions2, "wl1", bucketStartTimeNs + 3 * bucketSizeNs + 1);
- processor->OnLogEvent(event.get());
- EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 1) / NS_PER_SEC + 1,
- anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
-
- event = CreateAcquireWakelockEvent(
- attributions2, "wl1", bucketStartTimeNs + 3 * bucketSizeNs + 2);
- processor->OnLogEvent(event.get());
- EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + 3 * bucketSizeNs + 2) / NS_PER_SEC + 1,
- anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
-}
+// TODO(b/149590301): Update these tests to use new socket schema.
+//TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_single_bucket) {
+// const int num_buckets = 1;
+// const int threshold = 3;
+// auto config = CreateStatsdConfig(num_buckets, threshold);
+// const uint64_t alert_id = config.alert(0).id();
+// const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
+//
+// int64_t bucketStartTimeNs = 10000000000;
+// int64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
+//
+// ConfigKey cfgKey;
+// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+// EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
+//
+// sp<AnomalyTracker> anomalyTracker =
+// processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
+//
+// std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
+// std::vector<AttributionNodeInternal> attributions2 = {
+// CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1")};
+// std::vector<AttributionNodeInternal> attributions3 = {
+// CreateAttribution(111, "App1"), CreateAttribution(333, "App3")};
+// std::vector<AttributionNodeInternal> attributions4 = {
+// CreateAttribution(222, "GMSCoreModule1"), CreateAttribution(333, "App3")};
+// std::vector<AttributionNodeInternal> attributions5 = {
+// CreateAttribution(222, "GMSCoreModule1") };
+//
+// FieldValue fieldValue1(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
+// Value((int32_t)111));
+// HashableDimensionKey whatKey1({fieldValue1});
+// MetricDimensionKey dimensionKey1(whatKey1, DEFAULT_DIMENSION_KEY);
+//
+// FieldValue fieldValue2(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
+// Value((int32_t)222));
+// HashableDimensionKey whatKey2({fieldValue2});
+// MetricDimensionKey dimensionKey2(whatKey2, DEFAULT_DIMENSION_KEY);
+//
+// auto event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 2);
+// processor->OnLogEvent(event.get());
+// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
+//
+// event = CreateAcquireWakelockEvent(attributions4, "wl2", bucketStartTimeNs + 2);
+// processor->OnLogEvent(event.get());
+// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
+//
+// event = CreateAcquireWakelockEvent(attributions2, "wl1", bucketStartTimeNs + 3);
+// processor->OnLogEvent(event.get());
+// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
+//
+// event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + 3);
+// processor->OnLogEvent(event.get());
+// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
+//
+// event = CreateAcquireWakelockEvent(attributions3, "wl1", bucketStartTimeNs + 4);
+// processor->OnLogEvent(event.get());
+// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
+//
+// event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + 4);
+// processor->OnLogEvent(event.get());
+// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
+//
+// // Fired alarm and refractory period end timestamp updated.
+// event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 5);
+// processor->OnLogEvent(event.get());
+// EXPECT_EQ(refractory_period_sec + bucketStartTimeNs / NS_PER_SEC + 1,
+// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
+//
+// event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 100);
+// processor->OnLogEvent(event.get());
+// EXPECT_EQ(refractory_period_sec + bucketStartTimeNs / NS_PER_SEC + 1,
+// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
+//
+// event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs - 1);
+// processor->OnLogEvent(event.get());
+// EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs - 1) / NS_PER_SEC + 1,
+// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
+//
+// event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 1);
+// processor->OnLogEvent(event.get());
+// EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs - 1) / NS_PER_SEC + 1,
+// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
+//
+// event = CreateAcquireWakelockEvent(attributions4, "wl2", bucketStartTimeNs + bucketSizeNs + 1);
+// processor->OnLogEvent(event.get());
+// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
+//
+// event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + bucketSizeNs + 2);
+// processor->OnLogEvent(event.get());
+// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
+//
+// event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + bucketSizeNs + 3);
+// processor->OnLogEvent(event.get());
+// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
+//
+// event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + bucketSizeNs + 4);
+// processor->OnLogEvent(event.get());
+// EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 4) / NS_PER_SEC + 1,
+// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
+//}
+//
+//TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_multiple_buckets) {
+// const int num_buckets = 3;
+// const int threshold = 3;
+// auto config = CreateStatsdConfig(num_buckets, threshold);
+// const uint64_t alert_id = config.alert(0).id();
+// const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
+//
+// int64_t bucketStartTimeNs = 10000000000;
+// int64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
+//
+// ConfigKey cfgKey;
+// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+// EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
+//
+// sp<AnomalyTracker> anomalyTracker =
+// processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
+//
+// std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
+// std::vector<AttributionNodeInternal> attributions2 = {
+// CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1")};
+// std::vector<AttributionNodeInternal> attributions3 = {
+// CreateAttribution(111, "App1"), CreateAttribution(333, "App3")};
+// std::vector<AttributionNodeInternal> attributions4 = {
+// CreateAttribution(222, "GMSCoreModule1"), CreateAttribution(333, "App3")};
+// std::vector<AttributionNodeInternal> attributions5 = {
+// CreateAttribution(222, "GMSCoreModule1") };
+//
+// FieldValue fieldValue1(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
+// Value((int32_t)111));
+// HashableDimensionKey whatKey1({fieldValue1});
+// MetricDimensionKey dimensionKey1(whatKey1, DEFAULT_DIMENSION_KEY);
+//
+// FieldValue fieldValue2(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
+// Value((int32_t)222));
+// HashableDimensionKey whatKey2({fieldValue2});
+// MetricDimensionKey dimensionKey2(whatKey2, DEFAULT_DIMENSION_KEY);
+//
+// auto event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 2);
+// processor->OnLogEvent(event.get());
+// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
+//
+// event = CreateAcquireWakelockEvent(attributions2, "wl1", bucketStartTimeNs + 3);
+// processor->OnLogEvent(event.get());
+// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
+//
+// // Fired alarm and refractory period end timestamp updated.
+// event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 4);
+// processor->OnLogEvent(event.get());
+// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
+//
+// event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 1);
+// processor->OnLogEvent(event.get());
+// EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 1) / NS_PER_SEC + 1,
+// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
+//
+// event = CreateAcquireWakelockEvent(attributions2, "wl1", bucketStartTimeNs + bucketSizeNs + 2);
+// processor->OnLogEvent(event.get());
+// EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 1) / NS_PER_SEC + 1,
+// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
+//
+// event = CreateAcquireWakelockEvent(
+// attributions2, "wl1", bucketStartTimeNs + 3 * bucketSizeNs + 1);
+// processor->OnLogEvent(event.get());
+// EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 1) / NS_PER_SEC + 1,
+// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
+//
+// event = CreateAcquireWakelockEvent(
+// attributions2, "wl1", bucketStartTimeNs + 3 * bucketSizeNs + 2);
+// processor->OnLogEvent(event.get());
+// EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + 3 * bucketSizeNs + 2) / NS_PER_SEC + 1,
+// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
+//}
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
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 50da9e2..03a209a 100644
--- a/cmds/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp
@@ -89,393 +89,394 @@
(int32_t)0x02010101), Value((int32_t)222))}),
DEFAULT_DIMENSION_KEY);
-TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
- const int num_buckets = 1;
- const uint64_t threshold_ns = NS_PER_SEC;
- auto config = CreateStatsdConfig(num_buckets, threshold_ns, DurationMetric::SUM, true);
- 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;
-
- ConfigKey cfgKey;
- auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
- EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
- EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
- EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
-
- sp<AnomalyTracker> anomalyTracker =
- processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
-
- auto screen_on_event = CreateScreenStateChangedEvent(
- android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 1);
- auto screen_off_event = CreateScreenStateChangedEvent(
- android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 10);
- processor->OnLogEvent(screen_on_event.get());
- processor->OnLogEvent(screen_off_event.get());
-
- // Acquire wakelock wl1.
- auto acquire_event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 11);
- processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + 11 + threshold_ns) / NS_PER_SEC + 1,
- anomalyTracker->getAlarmTimestampSec(dimensionKey));
- EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
- // Release wakelock wl1. No anomaly detected. Alarm cancelled at the "release" event.
- auto release_event = CreateReleaseWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 101);
- processor->OnLogEvent(release_event.get());
- EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
- EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
- // Acquire wakelock wl1 within bucket #0.
- acquire_event = CreateAcquireWakelockEvent(attributions2, "wl1", bucketStartTimeNs + 110);
- processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + 110 + threshold_ns - 90) / NS_PER_SEC + 1,
- anomalyTracker->getAlarmTimestampSec(dimensionKey));
- EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
- // Release wakelock wl1. One anomaly detected.
- release_event = CreateReleaseWakelockEvent(
- attributions2, "wl1", bucketStartTimeNs + NS_PER_SEC + 109);
- processor->OnLogEvent(release_event.get());
- EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
- EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + NS_PER_SEC + 109) / NS_PER_SEC + 1,
- anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
- // Acquire wakelock wl1.
- acquire_event = CreateAcquireWakelockEvent(
- attributions1, "wl1", bucketStartTimeNs + NS_PER_SEC + 112);
- processor->OnLogEvent(acquire_event.get());
- // Wakelock has been hold longer than the threshold in bucket #0. The alarm is set at the
- // end of the refractory period.
- const int64_t alarmFiredTimestampSec0 = anomalyTracker->getAlarmTimestampSec(dimensionKey);
- EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + NS_PER_SEC + 109) / NS_PER_SEC + 1,
- (uint32_t)alarmFiredTimestampSec0);
-
- // Anomaly alarm fired.
- auto alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
- static_cast<uint32_t>(alarmFiredTimestampSec0));
- EXPECT_EQ(1u, alarmSet.size());
- processor->onAnomalyAlarmFired(alarmFiredTimestampSec0 * NS_PER_SEC, alarmSet);
- EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
- EXPECT_EQ(refractory_period_sec + alarmFiredTimestampSec0,
- anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
- // Release wakelock wl1.
- release_event = CreateReleaseWakelockEvent(
- attributions1, "wl1", alarmFiredTimestampSec0 * NS_PER_SEC + NS_PER_SEC + 1);
- processor->OnLogEvent(release_event.get());
- EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
- // Within refractory period. No more anomaly detected.
- EXPECT_EQ(refractory_period_sec + alarmFiredTimestampSec0,
- anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
- // Acquire wakelock wl1.
- acquire_event = CreateAcquireWakelockEvent(
- attributions2, "wl1", bucketStartTimeNs + bucketSizeNs - 5 * NS_PER_SEC - 11);
- processor->OnLogEvent(acquire_event.get());
- const int64_t alarmFiredTimestampSec1 = anomalyTracker->getAlarmTimestampSec(dimensionKey);
- EXPECT_EQ((bucketStartTimeNs + bucketSizeNs - 5 * NS_PER_SEC) / NS_PER_SEC,
- (uint64_t)alarmFiredTimestampSec1);
-
- // Release wakelock wl1.
- release_event = CreateReleaseWakelockEvent(
- attributions2, "wl1", bucketStartTimeNs + bucketSizeNs - 4 * NS_PER_SEC - 10);
- processor->OnLogEvent(release_event.get());
- EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
- EXPECT_EQ(refractory_period_sec +
- (bucketStartTimeNs + bucketSizeNs - 4 * NS_PER_SEC - 10) / NS_PER_SEC + 1,
- anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
- alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
- static_cast<uint32_t>(alarmFiredTimestampSec1));
- EXPECT_EQ(0u, alarmSet.size());
-
- // Acquire wakelock wl1 near the end of bucket #0.
- acquire_event = CreateAcquireWakelockEvent(
- attributions1, "wl1", bucketStartTimeNs + bucketSizeNs - 2);
- processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC,
- anomalyTracker->getAlarmTimestampSec(dimensionKey));
-
- // Release the event at early bucket #1.
- release_event = CreateReleaseWakelockEvent(
- attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + NS_PER_SEC - 1);
- processor->OnLogEvent(release_event.get());
- EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
- // 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,
- anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
- // Condition changes to false.
- screen_on_event = CreateScreenStateChangedEvent(
- android::view::DisplayStateEnum::DISPLAY_STATE_ON,
- bucketStartTimeNs + 2 * bucketSizeNs + 20);
- processor->OnLogEvent(screen_on_event.get());
- EXPECT_EQ(refractory_period_sec +
- (bucketStartTimeNs + bucketSizeNs + NS_PER_SEC) / NS_PER_SEC,
- anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
- EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
-
- acquire_event = CreateAcquireWakelockEvent(
- attributions2, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 30);
- processor->OnLogEvent(acquire_event.get());
- // The condition is false. Do not start the alarm.
- EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
- EXPECT_EQ(refractory_period_sec +
- (bucketStartTimeNs + bucketSizeNs + NS_PER_SEC) / NS_PER_SEC,
- anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
- // Condition turns true.
- screen_off_event = CreateScreenStateChangedEvent(
- android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
- bucketStartTimeNs + 2 * bucketSizeNs + NS_PER_SEC);
- processor->OnLogEvent(screen_off_event.get());
- EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs + NS_PER_SEC + threshold_ns) / NS_PER_SEC,
- anomalyTracker->getAlarmTimestampSec(dimensionKey));
-
- // Condition turns to false.
- screen_on_event = CreateScreenStateChangedEvent(
- android::view::DisplayStateEnum::DISPLAY_STATE_ON,
- bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC + 1);
- processor->OnLogEvent(screen_on_event.get());
- // Condition turns to false. Cancelled the alarm.
- EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
- // Detected one anomaly.
- EXPECT_EQ(refractory_period_sec +
- (bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC + 1) / NS_PER_SEC + 1,
- anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
- // Condition turns to true again.
- screen_off_event = CreateScreenStateChangedEvent(
- android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
- bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC + 2);
- processor->OnLogEvent(screen_off_event.get());
- EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2 + 2 + 1,
- anomalyTracker->getAlarmTimestampSec(dimensionKey));
-
- release_event = CreateReleaseWakelockEvent(
- attributions2, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 5 * NS_PER_SEC);
- processor->OnLogEvent(release_event.get());
- EXPECT_EQ(refractory_period_sec +
- (bucketStartTimeNs + 2 * bucketSizeNs + 5 * NS_PER_SEC) / NS_PER_SEC,
- anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
- EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
-}
-
-TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets) {
- const int num_buckets = 3;
- const uint64_t threshold_ns = NS_PER_SEC;
- auto config = CreateStatsdConfig(num_buckets, threshold_ns, DurationMetric::SUM, true);
- 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;
-
- ConfigKey cfgKey;
- auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
- EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
- EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
- EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
-
- sp<AnomalyTracker> anomalyTracker =
- processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
-
- auto screen_off_event = CreateScreenStateChangedEvent(
- android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 1);
- processor->OnLogEvent(screen_off_event.get());
-
- // Acquire wakelock "wc1" in bucket #0.
- auto acquire_event = CreateAcquireWakelockEvent(
- attributions1, "wl1", bucketStartTimeNs + bucketSizeNs - NS_PER_SEC / 2 - 1);
- processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 1,
- anomalyTracker->getAlarmTimestampSec(dimensionKey));
- EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
- // Release wakelock "wc1" in bucket #0.
- auto release_event = CreateReleaseWakelockEvent(
- attributions1, "wl1", bucketStartTimeNs + bucketSizeNs - 1);
- processor->OnLogEvent(release_event.get());
- EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
- EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
- // Acquire wakelock "wc1" in bucket #1.
- acquire_event = CreateAcquireWakelockEvent(
- attributions2, "wl1", bucketStartTimeNs + bucketSizeNs + 1);
- processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 1,
- anomalyTracker->getAlarmTimestampSec(dimensionKey));
- EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
- release_event = CreateReleaseWakelockEvent(
- attributions2, "wl1", bucketStartTimeNs + bucketSizeNs + 100);
- processor->OnLogEvent(release_event.get());
- EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
- EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
- // Acquire wakelock "wc2" in bucket #2.
- acquire_event = CreateAcquireWakelockEvent(
- attributions3, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 1);
- processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2,
- anomalyTracker->getAlarmTimestampSec(dimensionKey2));
- EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
-
- // Release wakelock "wc2" in bucket #2.
- release_event = CreateReleaseWakelockEvent(
- attributions3, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC);
- processor->OnLogEvent(release_event.get());
- EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey2));
- EXPECT_EQ(refractory_period_sec +
- (bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC) / NS_PER_SEC,
- anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
-
- // Acquire wakelock "wc1" in bucket #2.
- acquire_event = CreateAcquireWakelockEvent(
- attributions2, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC);
- processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2 + 1,
- anomalyTracker->getAlarmTimestampSec(dimensionKey));
- EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
- // Release wakelock "wc1" in bucket #2.
- release_event = CreateReleaseWakelockEvent(
- attributions2, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 2.5 * NS_PER_SEC);
- processor->OnLogEvent(release_event.get());
- EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
- EXPECT_EQ(refractory_period_sec +
- (int64_t)(bucketStartTimeNs + 2 * bucketSizeNs + 2.5 * NS_PER_SEC) / NS_PER_SEC + 1,
- anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
- acquire_event = CreateAcquireWakelockEvent(
- attributions3, "wl2", bucketStartTimeNs + 6 * bucketSizeNs - NS_PER_SEC + 4);
- processor->OnLogEvent(acquire_event.get());
- acquire_event = CreateAcquireWakelockEvent(
- attributions1, "wl1", bucketStartTimeNs + 6 * bucketSizeNs - NS_PER_SEC + 5);
- processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 1,
- anomalyTracker->getAlarmTimestampSec(dimensionKey));
- EXPECT_EQ((bucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 1,
- anomalyTracker->getAlarmTimestampSec(dimensionKey2));
-
- release_event = CreateReleaseWakelockEvent(
- attributions3, "wl2", bucketStartTimeNs + 6 * bucketSizeNs + 2);
- processor->OnLogEvent(release_event.get());
- release_event = CreateReleaseWakelockEvent(
- attributions1, "wl1", bucketStartTimeNs + 6 * bucketSizeNs + 6);
- processor->OnLogEvent(release_event.get());
- EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
- 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 + 1,
- anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-}
-
-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();
- 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);
- EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
- EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
- EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
-
- sp<AnomalyTracker> anomalyTracker =
- processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
-
- auto screen_off_event = CreateScreenStateChangedEvent(
- android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 1);
- processor->OnLogEvent(screen_off_event.get());
-
- // Acquire wakelock "wc1" in bucket #0.
- auto acquire_event = CreateAcquireWakelockEvent(
- attributions1, "wl1", bucketStartTimeNs + bucketSizeNs - 100);
- processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 3,
- anomalyTracker->getAlarmTimestampSec(dimensionKey));
- EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
- // Acquire the wakelock "wc1" again.
- acquire_event = CreateAcquireWakelockEvent(
- attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 2 * NS_PER_SEC + 1);
- processor->OnLogEvent(acquire_event.get());
- // The alarm does not change.
- EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 3,
- anomalyTracker->getAlarmTimestampSec(dimensionKey));
- EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
- // 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));
- EXPECT_EQ(1u, alarmSet.size());
- processor->onAnomalyAlarmFired(firedAlarmTimestampNs, alarmSet);
- EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
- EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
- anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
- acquire_event = CreateAcquireWakelockEvent(
- attributions1, "wl1", bucketStartTimeNs + 2 * bucketSizeNs - 100);
- processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
- EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
- anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
- auto release_event = CreateReleaseWakelockEvent(
- attributions1, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 1);
- processor->OnLogEvent(release_event.get());
- EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
- // Within the refractory period. No anomaly.
- EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
- anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
- // A new wakelock, but still within refractory period.
- acquire_event = CreateAcquireWakelockEvent(
- attributions1, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 10 * NS_PER_SEC);
- processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
- anomalyTracker->getAlarmTimestampSec(dimensionKey));
-
- release_event = CreateReleaseWakelockEvent(
- attributions1, "wl1", bucketStartTimeNs + 3 * bucketSizeNs - NS_PER_SEC);
- // Still in the refractory period. No anomaly.
- processor->OnLogEvent(release_event.get());
- EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
- anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
- acquire_event = CreateAcquireWakelockEvent(
- attributions1, "wl1", bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 5);
- processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + 5 * bucketSizeNs) / NS_PER_SEC,
- anomalyTracker->getAlarmTimestampSec(dimensionKey));
-
- release_event = CreateReleaseWakelockEvent(
- attributions1, "wl1", bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 4);
- processor->OnLogEvent(release_event.get());
- EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
-
- acquire_event = CreateAcquireWakelockEvent(
- attributions1, "wl1", bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 3);
- processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + 5 * bucketSizeNs) / NS_PER_SEC,
- anomalyTracker->getAlarmTimestampSec(dimensionKey));
-}
+// TODO(b/149590301): Update these tests to use new socket schema.
+//TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
+// const int num_buckets = 1;
+// const uint64_t threshold_ns = NS_PER_SEC;
+// auto config = CreateStatsdConfig(num_buckets, threshold_ns, DurationMetric::SUM, true);
+// 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;
+//
+// ConfigKey cfgKey;
+// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+// EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
+//
+// sp<AnomalyTracker> anomalyTracker =
+// processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
+//
+// auto screen_on_event = CreateScreenStateChangedEvent(
+// android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 1);
+// auto screen_off_event = CreateScreenStateChangedEvent(
+// android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 10);
+// processor->OnLogEvent(screen_on_event.get());
+// processor->OnLogEvent(screen_off_event.get());
+//
+// // Acquire wakelock wl1.
+// auto acquire_event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 11);
+// processor->OnLogEvent(acquire_event.get());
+// EXPECT_EQ((bucketStartTimeNs + 11 + threshold_ns) / NS_PER_SEC + 1,
+// anomalyTracker->getAlarmTimestampSec(dimensionKey));
+// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+// // Release wakelock wl1. No anomaly detected. Alarm cancelled at the "release" event.
+// auto release_event = CreateReleaseWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 101);
+// processor->OnLogEvent(release_event.get());
+// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+// // Acquire wakelock wl1 within bucket #0.
+// acquire_event = CreateAcquireWakelockEvent(attributions2, "wl1", bucketStartTimeNs + 110);
+// processor->OnLogEvent(acquire_event.get());
+// EXPECT_EQ((bucketStartTimeNs + 110 + threshold_ns - 90) / NS_PER_SEC + 1,
+// anomalyTracker->getAlarmTimestampSec(dimensionKey));
+// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+// // Release wakelock wl1. One anomaly detected.
+// release_event = CreateReleaseWakelockEvent(
+// attributions2, "wl1", bucketStartTimeNs + NS_PER_SEC + 109);
+// processor->OnLogEvent(release_event.get());
+// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+// EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + NS_PER_SEC + 109) / NS_PER_SEC + 1,
+// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+// // Acquire wakelock wl1.
+// acquire_event = CreateAcquireWakelockEvent(
+// attributions1, "wl1", bucketStartTimeNs + NS_PER_SEC + 112);
+// processor->OnLogEvent(acquire_event.get());
+// // Wakelock has been hold longer than the threshold in bucket #0. The alarm is set at the
+// // end of the refractory period.
+// const int64_t alarmFiredTimestampSec0 = anomalyTracker->getAlarmTimestampSec(dimensionKey);
+// EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + NS_PER_SEC + 109) / NS_PER_SEC + 1,
+// (uint32_t)alarmFiredTimestampSec0);
+//
+// // Anomaly alarm fired.
+// auto alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
+// static_cast<uint32_t>(alarmFiredTimestampSec0));
+// EXPECT_EQ(1u, alarmSet.size());
+// processor->onAnomalyAlarmFired(alarmFiredTimestampSec0 * NS_PER_SEC, alarmSet);
+// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+// EXPECT_EQ(refractory_period_sec + alarmFiredTimestampSec0,
+// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+// // Release wakelock wl1.
+// release_event = CreateReleaseWakelockEvent(
+// attributions1, "wl1", alarmFiredTimestampSec0 * NS_PER_SEC + NS_PER_SEC + 1);
+// processor->OnLogEvent(release_event.get());
+// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+// // Within refractory period. No more anomaly detected.
+// EXPECT_EQ(refractory_period_sec + alarmFiredTimestampSec0,
+// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+// // Acquire wakelock wl1.
+// acquire_event = CreateAcquireWakelockEvent(
+// attributions2, "wl1", bucketStartTimeNs + bucketSizeNs - 5 * NS_PER_SEC - 11);
+// processor->OnLogEvent(acquire_event.get());
+// const int64_t alarmFiredTimestampSec1 = anomalyTracker->getAlarmTimestampSec(dimensionKey);
+// EXPECT_EQ((bucketStartTimeNs + bucketSizeNs - 5 * NS_PER_SEC) / NS_PER_SEC,
+// (uint64_t)alarmFiredTimestampSec1);
+//
+// // Release wakelock wl1.
+// release_event = CreateReleaseWakelockEvent(
+// attributions2, "wl1", bucketStartTimeNs + bucketSizeNs - 4 * NS_PER_SEC - 10);
+// processor->OnLogEvent(release_event.get());
+// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+// EXPECT_EQ(refractory_period_sec +
+// (bucketStartTimeNs + bucketSizeNs - 4 * NS_PER_SEC - 10) / NS_PER_SEC + 1,
+// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+// alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
+// static_cast<uint32_t>(alarmFiredTimestampSec1));
+// EXPECT_EQ(0u, alarmSet.size());
+//
+// // Acquire wakelock wl1 near the end of bucket #0.
+// acquire_event = CreateAcquireWakelockEvent(
+// attributions1, "wl1", bucketStartTimeNs + bucketSizeNs - 2);
+// processor->OnLogEvent(acquire_event.get());
+// EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC,
+// anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//
+// // Release the event at early bucket #1.
+// release_event = CreateReleaseWakelockEvent(
+// attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + NS_PER_SEC - 1);
+// processor->OnLogEvent(release_event.get());
+// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+// // 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,
+// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+// // Condition changes to false.
+// screen_on_event = CreateScreenStateChangedEvent(
+// android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+// bucketStartTimeNs + 2 * bucketSizeNs + 20);
+// processor->OnLogEvent(screen_on_event.get());
+// EXPECT_EQ(refractory_period_sec +
+// (bucketStartTimeNs + bucketSizeNs + NS_PER_SEC) / NS_PER_SEC,
+// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//
+// acquire_event = CreateAcquireWakelockEvent(
+// attributions2, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 30);
+// processor->OnLogEvent(acquire_event.get());
+// // The condition is false. Do not start the alarm.
+// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+// EXPECT_EQ(refractory_period_sec +
+// (bucketStartTimeNs + bucketSizeNs + NS_PER_SEC) / NS_PER_SEC,
+// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+// // Condition turns true.
+// screen_off_event = CreateScreenStateChangedEvent(
+// android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+// bucketStartTimeNs + 2 * bucketSizeNs + NS_PER_SEC);
+// processor->OnLogEvent(screen_off_event.get());
+// EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs + NS_PER_SEC + threshold_ns) / NS_PER_SEC,
+// anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//
+// // Condition turns to false.
+// screen_on_event = CreateScreenStateChangedEvent(
+// android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+// bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC + 1);
+// processor->OnLogEvent(screen_on_event.get());
+// // Condition turns to false. Cancelled the alarm.
+// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+// // Detected one anomaly.
+// EXPECT_EQ(refractory_period_sec +
+// (bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC + 1) / NS_PER_SEC + 1,
+// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+// // Condition turns to true again.
+// screen_off_event = CreateScreenStateChangedEvent(
+// android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+// bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC + 2);
+// processor->OnLogEvent(screen_off_event.get());
+// EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2 + 2 + 1,
+// anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//
+// release_event = CreateReleaseWakelockEvent(
+// attributions2, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 5 * NS_PER_SEC);
+// processor->OnLogEvent(release_event.get());
+// EXPECT_EQ(refractory_period_sec +
+// (bucketStartTimeNs + 2 * bucketSizeNs + 5 * NS_PER_SEC) / NS_PER_SEC,
+// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//}
+//
+//TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets) {
+// const int num_buckets = 3;
+// const uint64_t threshold_ns = NS_PER_SEC;
+// auto config = CreateStatsdConfig(num_buckets, threshold_ns, DurationMetric::SUM, true);
+// 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;
+//
+// ConfigKey cfgKey;
+// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+// EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
+//
+// sp<AnomalyTracker> anomalyTracker =
+// processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
+//
+// auto screen_off_event = CreateScreenStateChangedEvent(
+// android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 1);
+// processor->OnLogEvent(screen_off_event.get());
+//
+// // Acquire wakelock "wc1" in bucket #0.
+// auto acquire_event = CreateAcquireWakelockEvent(
+// attributions1, "wl1", bucketStartTimeNs + bucketSizeNs - NS_PER_SEC / 2 - 1);
+// processor->OnLogEvent(acquire_event.get());
+// EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 1,
+// anomalyTracker->getAlarmTimestampSec(dimensionKey));
+// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+// // Release wakelock "wc1" in bucket #0.
+// auto release_event = CreateReleaseWakelockEvent(
+// attributions1, "wl1", bucketStartTimeNs + bucketSizeNs - 1);
+// processor->OnLogEvent(release_event.get());
+// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+// // Acquire wakelock "wc1" in bucket #1.
+// acquire_event = CreateAcquireWakelockEvent(
+// attributions2, "wl1", bucketStartTimeNs + bucketSizeNs + 1);
+// processor->OnLogEvent(acquire_event.get());
+// EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 1,
+// anomalyTracker->getAlarmTimestampSec(dimensionKey));
+// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+// release_event = CreateReleaseWakelockEvent(
+// attributions2, "wl1", bucketStartTimeNs + bucketSizeNs + 100);
+// processor->OnLogEvent(release_event.get());
+// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+// // Acquire wakelock "wc2" in bucket #2.
+// acquire_event = CreateAcquireWakelockEvent(
+// attributions3, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 1);
+// processor->OnLogEvent(acquire_event.get());
+// EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2,
+// anomalyTracker->getAlarmTimestampSec(dimensionKey2));
+// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
+//
+// // Release wakelock "wc2" in bucket #2.
+// release_event = CreateReleaseWakelockEvent(
+// attributions3, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC);
+// processor->OnLogEvent(release_event.get());
+// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey2));
+// EXPECT_EQ(refractory_period_sec +
+// (bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC) / NS_PER_SEC,
+// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
+//
+// // Acquire wakelock "wc1" in bucket #2.
+// acquire_event = CreateAcquireWakelockEvent(
+// attributions2, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC);
+// processor->OnLogEvent(acquire_event.get());
+// EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2 + 1,
+// anomalyTracker->getAlarmTimestampSec(dimensionKey));
+// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+// // Release wakelock "wc1" in bucket #2.
+// release_event = CreateReleaseWakelockEvent(
+// attributions2, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 2.5 * NS_PER_SEC);
+// processor->OnLogEvent(release_event.get());
+// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+// EXPECT_EQ(refractory_period_sec +
+// (int64_t)(bucketStartTimeNs + 2 * bucketSizeNs + 2.5 * NS_PER_SEC) / NS_PER_SEC + 1,
+// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+// acquire_event = CreateAcquireWakelockEvent(
+// attributions3, "wl2", bucketStartTimeNs + 6 * bucketSizeNs - NS_PER_SEC + 4);
+// processor->OnLogEvent(acquire_event.get());
+// acquire_event = CreateAcquireWakelockEvent(
+// attributions1, "wl1", bucketStartTimeNs + 6 * bucketSizeNs - NS_PER_SEC + 5);
+// processor->OnLogEvent(acquire_event.get());
+// EXPECT_EQ((bucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 1,
+// anomalyTracker->getAlarmTimestampSec(dimensionKey));
+// EXPECT_EQ((bucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 1,
+// anomalyTracker->getAlarmTimestampSec(dimensionKey2));
+//
+// release_event = CreateReleaseWakelockEvent(
+// attributions3, "wl2", bucketStartTimeNs + 6 * bucketSizeNs + 2);
+// processor->OnLogEvent(release_event.get());
+// release_event = CreateReleaseWakelockEvent(
+// attributions1, "wl1", bucketStartTimeNs + 6 * bucketSizeNs + 6);
+// processor->OnLogEvent(release_event.get());
+// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+// 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 + 1,
+// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//}
+//
+//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();
+// 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);
+// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+// EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
+//
+// sp<AnomalyTracker> anomalyTracker =
+// processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
+//
+// auto screen_off_event = CreateScreenStateChangedEvent(
+// android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 1);
+// processor->OnLogEvent(screen_off_event.get());
+//
+// // Acquire wakelock "wc1" in bucket #0.
+// auto acquire_event = CreateAcquireWakelockEvent(
+// attributions1, "wl1", bucketStartTimeNs + bucketSizeNs - 100);
+// processor->OnLogEvent(acquire_event.get());
+// EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 3,
+// anomalyTracker->getAlarmTimestampSec(dimensionKey));
+// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+// // Acquire the wakelock "wc1" again.
+// acquire_event = CreateAcquireWakelockEvent(
+// attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 2 * NS_PER_SEC + 1);
+// processor->OnLogEvent(acquire_event.get());
+// // The alarm does not change.
+// EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 3,
+// anomalyTracker->getAlarmTimestampSec(dimensionKey));
+// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+// // 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));
+// EXPECT_EQ(1u, alarmSet.size());
+// processor->onAnomalyAlarmFired(firedAlarmTimestampNs, alarmSet);
+// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+// EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
+// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+// acquire_event = CreateAcquireWakelockEvent(
+// attributions1, "wl1", bucketStartTimeNs + 2 * bucketSizeNs - 100);
+// processor->OnLogEvent(acquire_event.get());
+// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+// EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
+// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+// auto release_event = CreateReleaseWakelockEvent(
+// attributions1, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 1);
+// processor->OnLogEvent(release_event.get());
+// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+// // Within the refractory period. No anomaly.
+// EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
+// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+// // A new wakelock, but still within refractory period.
+// acquire_event = CreateAcquireWakelockEvent(
+// attributions1, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 10 * NS_PER_SEC);
+// processor->OnLogEvent(acquire_event.get());
+// EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
+// anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//
+// release_event = CreateReleaseWakelockEvent(
+// attributions1, "wl1", bucketStartTimeNs + 3 * bucketSizeNs - NS_PER_SEC);
+// // Still in the refractory period. No anomaly.
+// processor->OnLogEvent(release_event.get());
+// EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
+// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+// acquire_event = CreateAcquireWakelockEvent(
+// attributions1, "wl1", bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 5);
+// processor->OnLogEvent(acquire_event.get());
+// EXPECT_EQ((bucketStartTimeNs + 5 * bucketSizeNs) / NS_PER_SEC,
+// anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//
+// release_event = CreateReleaseWakelockEvent(
+// attributions1, "wl1", bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 4);
+// processor->OnLogEvent(release_event.get());
+// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//
+// acquire_event = CreateAcquireWakelockEvent(
+// attributions1, "wl1", bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 3);
+// processor->OnLogEvent(acquire_event.get());
+// EXPECT_EQ((bucketStartTimeNs + 5 * bucketSizeNs) / NS_PER_SEC,
+// anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//}
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
diff --git a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
index 3382525..6051174 100644
--- a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
@@ -55,364 +55,365 @@
} // namespace
-TEST(AttributionE2eTest, TestAttributionMatchAndSliceByFirstUid) {
- auto config = CreateStatsdConfig(Position::FIRST);
- int64_t bucketStartTimeNs = 10000000000;
- int64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
-
- ConfigKey cfgKey;
- auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
- EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
- EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-
- // Here it assumes that GMS core has two uids.
- processor->getUidMap()->updateMap(
- 1, {222, 444, 111, 333}, {1, 1, 2, 2},
- {String16("v1"), String16("v1"), String16("v2"), String16("v2")},
- {String16("com.android.gmscore"), String16("com.android.gmscore"), String16("app1"),
- String16("APP3")},
- {String16(""), String16(""), String16(""), String16("")});
-
- // GMS core node is in the middle.
- std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"),
- CreateAttribution(222, "GMSCoreModule1"),
- CreateAttribution(333, "App3")};
-
- // GMS core node is the last one.
- std::vector<AttributionNodeInternal> attributions2 = {CreateAttribution(111, "App1"),
- CreateAttribution(333, "App3"),
- CreateAttribution(222, "GMSCoreModule1")};
-
- // GMS core node is the first one.
- std::vector<AttributionNodeInternal> attributions3 = {CreateAttribution(222, "GMSCoreModule1"),
- CreateAttribution(333, "App3")};
-
- // Single GMS core node.
- std::vector<AttributionNodeInternal> attributions4 = {CreateAttribution(222, "GMSCoreModule1")};
-
- // GMS core has another uid.
- std::vector<AttributionNodeInternal> attributions5 = {CreateAttribution(111, "App1"),
- CreateAttribution(444, "GMSCoreModule2"),
- CreateAttribution(333, "App3")};
-
- // Multiple GMS core nodes.
- std::vector<AttributionNodeInternal> attributions6 = {CreateAttribution(444, "GMSCoreModule2"),
- CreateAttribution(222, "GMSCoreModule1")};
-
- // No GMS core nodes.
- std::vector<AttributionNodeInternal> attributions7 = {CreateAttribution(111, "App1"),
- CreateAttribution(333, "App3")};
- std::vector<AttributionNodeInternal> attributions8 = {CreateAttribution(111, "App1")};
-
- // GMS core node with isolated uid.
- const int isolatedUid = 666;
- std::vector<AttributionNodeInternal> attributions9 = {
- CreateAttribution(isolatedUid, "GMSCoreModule3")};
-
- std::vector<std::unique_ptr<LogEvent>> events;
- // Events 1~4 are in the 1st bucket.
- events.push_back(CreateAcquireWakelockEvent(
- attributions1, "wl1", bucketStartTimeNs + 2));
- events.push_back(CreateAcquireWakelockEvent(
- attributions2, "wl1", bucketStartTimeNs + 200));
- events.push_back(CreateAcquireWakelockEvent(
- attributions3, "wl1", bucketStartTimeNs + bucketSizeNs - 1));
- events.push_back(CreateAcquireWakelockEvent(
- attributions4, "wl1", bucketStartTimeNs + bucketSizeNs));
-
- // Events 5~8 are in the 3rd bucket.
- events.push_back(CreateAcquireWakelockEvent(
- attributions5, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 1));
- events.push_back(CreateAcquireWakelockEvent(
- attributions6, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 100));
- events.push_back(CreateAcquireWakelockEvent(
- attributions7, "wl2", bucketStartTimeNs + 3 * bucketSizeNs - 2));
- events.push_back(CreateAcquireWakelockEvent(
- attributions8, "wl2", bucketStartTimeNs + 3 * bucketSizeNs));
- events.push_back(CreateAcquireWakelockEvent(
- attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 1));
- events.push_back(CreateAcquireWakelockEvent(
- attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 100));
- events.push_back(CreateIsolatedUidChangedEvent(
- isolatedUid, 222, true/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs - 1));
- events.push_back(CreateIsolatedUidChangedEvent(
- isolatedUid, 222, false/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs + 10));
-
- sortLogEventsByTimestamp(&events);
-
- for (const auto& event : events) {
- processor->OnLogEvent(event.get());
- }
- ConfigMetricsReportList reports;
- vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, false, true,
- ADB_DUMP, FAST, &buffer);
- EXPECT_TRUE(buffer.size() > 0);
- EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
- backfillDimensionPath(&reports);
- backfillStringInReport(&reports);
- backfillStartEndTimestamp(&reports);
- EXPECT_EQ(reports.reports_size(), 1);
- EXPECT_EQ(reports.reports(0).metrics_size(), 1);
-
- StatsLogReport::CountMetricDataWrapper countMetrics;
- sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
- EXPECT_EQ(countMetrics.data_size(), 4);
-
- auto data = countMetrics.data(0);
- ValidateAttributionUidAndTagDimension(
- data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 111,
- "App1");
- EXPECT_EQ(data.bucket_info_size(), 2);
- EXPECT_EQ(data.bucket_info(0).count(), 2);
- EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
- EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
- EXPECT_EQ(data.bucket_info(1).count(), 1);
- EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
- EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
-
- data = countMetrics.data(1);
- ValidateAttributionUidAndTagDimension(
- data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 222,
- "GMSCoreModule1");
- EXPECT_EQ(data.bucket_info_size(), 2);
- EXPECT_EQ(data.bucket_info(0).count(), 1);
- EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
- EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
- EXPECT_EQ(data.bucket_info(1).count(), 1);
- EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
- EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
-
- data = countMetrics.data(2);
- ValidateAttributionUidAndTagDimension(
- data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 222,
- "GMSCoreModule3");
- EXPECT_EQ(data.bucket_info_size(), 1);
- EXPECT_EQ(data.bucket_info(0).count(), 1);
- EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
- EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + 4 * bucketSizeNs);
-
- data = countMetrics.data(3);
- ValidateAttributionUidAndTagDimension(
- data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 444,
- "GMSCoreModule2");
- EXPECT_EQ(data.bucket_info_size(), 1);
- EXPECT_EQ(data.bucket_info(0).count(), 1);
- EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
- EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
-}
-
-TEST(AttributionE2eTest, TestAttributionMatchAndSliceByChain) {
- auto config = CreateStatsdConfig(Position::ALL);
- int64_t bucketStartTimeNs = 10000000000;
- int64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
-
- ConfigKey cfgKey;
- auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
- EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
- EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-
- // Here it assumes that GMS core has two uids.
- processor->getUidMap()->updateMap(
- 1, {222, 444, 111, 333}, {1, 1, 2, 2},
- {String16("v1"), String16("v1"), String16("v2"), String16("v2")},
- {String16("com.android.gmscore"), String16("com.android.gmscore"), String16("app1"),
- String16("APP3")},
- {String16(""), String16(""), String16(""), String16("")});
-
- // GMS core node is in the middle.
- std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"),
- CreateAttribution(222, "GMSCoreModule1"),
- CreateAttribution(333, "App3")};
-
- // GMS core node is the last one.
- std::vector<AttributionNodeInternal> attributions2 = {CreateAttribution(111, "App1"),
- CreateAttribution(333, "App3"),
- CreateAttribution(222, "GMSCoreModule1")};
-
- // GMS core node is the first one.
- std::vector<AttributionNodeInternal> attributions3 = {CreateAttribution(222, "GMSCoreModule1"),
- CreateAttribution(333, "App3")};
-
- // Single GMS core node.
- std::vector<AttributionNodeInternal> attributions4 = {CreateAttribution(222, "GMSCoreModule1")};
-
- // GMS core has another uid.
- std::vector<AttributionNodeInternal> attributions5 = {CreateAttribution(111, "App1"),
- CreateAttribution(444, "GMSCoreModule2"),
- CreateAttribution(333, "App3")};
-
- // Multiple GMS core nodes.
- std::vector<AttributionNodeInternal> attributions6 = {CreateAttribution(444, "GMSCoreModule2"),
- CreateAttribution(222, "GMSCoreModule1")};
-
- // No GMS core nodes.
- std::vector<AttributionNodeInternal> attributions7 = {CreateAttribution(111, "App1"),
- CreateAttribution(333, "App3")};
- std::vector<AttributionNodeInternal> attributions8 = {CreateAttribution(111, "App1")};
-
- // GMS core node with isolated uid.
- const int isolatedUid = 666;
- std::vector<AttributionNodeInternal> attributions9 = {
- CreateAttribution(isolatedUid, "GMSCoreModule1")};
-
- std::vector<std::unique_ptr<LogEvent>> events;
- // Events 1~4 are in the 1st bucket.
- events.push_back(CreateAcquireWakelockEvent(
- attributions1, "wl1", bucketStartTimeNs + 2));
- events.push_back(CreateAcquireWakelockEvent(
- attributions2, "wl1", bucketStartTimeNs + 200));
- events.push_back(CreateAcquireWakelockEvent(
- attributions3, "wl1", bucketStartTimeNs + bucketSizeNs - 1));
- events.push_back(CreateAcquireWakelockEvent(
- attributions4, "wl1", bucketStartTimeNs + bucketSizeNs));
-
- // Events 5~8 are in the 3rd bucket.
- events.push_back(CreateAcquireWakelockEvent(
- attributions5, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 1));
- events.push_back(CreateAcquireWakelockEvent(
- attributions6, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 100));
- events.push_back(CreateAcquireWakelockEvent(
- attributions7, "wl2", bucketStartTimeNs + 3 * bucketSizeNs - 2));
- events.push_back(CreateAcquireWakelockEvent(
- attributions8, "wl2", bucketStartTimeNs + 3 * bucketSizeNs));
- events.push_back(CreateAcquireWakelockEvent(
- attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 1));
- events.push_back(CreateAcquireWakelockEvent(
- attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 100));
- events.push_back(CreateIsolatedUidChangedEvent(
- isolatedUid, 222, true/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs - 1));
- events.push_back(CreateIsolatedUidChangedEvent(
- isolatedUid, 222, false/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs + 10));
-
- sortLogEventsByTimestamp(&events);
-
- for (const auto& event : events) {
- processor->OnLogEvent(event.get());
- }
- ConfigMetricsReportList reports;
- vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, false, true,
- ADB_DUMP, FAST, &buffer);
- EXPECT_TRUE(buffer.size() > 0);
- EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
- backfillDimensionPath(&reports);
- backfillStringInReport(&reports);
- backfillStartEndTimestamp(&reports);
- EXPECT_EQ(reports.reports_size(), 1);
- EXPECT_EQ(reports.reports(0).metrics_size(), 1);
-
- StatsLogReport::CountMetricDataWrapper countMetrics;
- sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
- EXPECT_EQ(countMetrics.data_size(), 6);
-
- auto data = countMetrics.data(0);
- ValidateAttributionUidAndTagDimension(
- data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
- EXPECT_EQ(2, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
- data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
- data.bucket_info(0).end_bucket_elapsed_nanos());
- EXPECT_EQ(1, data.bucket_info(1).count());
- EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
- data.bucket_info(1).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + 4 * bucketSizeNs,
- data.bucket_info(1).end_bucket_elapsed_nanos());
-
- data = countMetrics.data(1);
- ValidateUidDimension(
- data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 222);
- ValidateAttributionUidAndTagDimension(
- data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
- ValidateUidDimension(
- data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333);
- ValidateAttributionUidAndTagDimension(
- data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
- EXPECT_EQ(data.bucket_info_size(), 1);
- EXPECT_EQ(data.bucket_info(0).count(), 1);
- EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
- EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
-
- data = countMetrics.data(2);
- ValidateUidDimension(
- data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 444);
- ValidateAttributionUidAndTagDimension(
- data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 444, "GMSCoreModule2");
- ValidateUidDimension(
- data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222);
- ValidateAttributionUidAndTagDimension(
- data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
- EXPECT_EQ(data.bucket_info_size(), 1);
- EXPECT_EQ(data.bucket_info(0).count(), 1);
- EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
- data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
- data.bucket_info(0).end_bucket_elapsed_nanos());
-
- data = countMetrics.data(3);
- ValidateUidDimension(
- data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111);
- ValidateAttributionUidAndTagDimension(
- data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111, "App1");
- ValidateUidDimension(
- data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222);
- ValidateAttributionUidAndTagDimension(
- data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
- ValidateUidDimension(
- data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333);
- ValidateAttributionUidAndTagDimension(
- data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
- EXPECT_EQ(data.bucket_info_size(), 1);
- EXPECT_EQ(data.bucket_info(0).count(), 1);
- EXPECT_EQ(bucketStartTimeNs,
- data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
- data.bucket_info(0).end_bucket_elapsed_nanos());
-
- data = countMetrics.data(4);
- ValidateUidDimension(
- data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111);
- ValidateAttributionUidAndTagDimension(
- data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111, "App1");
- ValidateUidDimension(
- data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333);
- ValidateAttributionUidAndTagDimension(
- data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
- ValidateUidDimension(
- data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 222);
- ValidateAttributionUidAndTagDimension(
- data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
- EXPECT_EQ(data.bucket_info_size(), 1);
- EXPECT_EQ(data.bucket_info(0).count(), 1);
- EXPECT_EQ(bucketStartTimeNs,
- data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
- data.bucket_info(0).end_bucket_elapsed_nanos());
-
- data = countMetrics.data(5);
- ValidateUidDimension(
- data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111);
- ValidateAttributionUidAndTagDimension(
- data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111, "App1");
- ValidateUidDimension(
- data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 444);
- ValidateAttributionUidAndTagDimension(
- data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 444, "GMSCoreModule2");
- ValidateUidDimension(
- data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333);
- ValidateAttributionUidAndTagDimension(
- data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
- EXPECT_EQ(data.bucket_info_size(), 1);
- EXPECT_EQ(data.bucket_info(0).count(), 1);
- EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
- data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
- data.bucket_info(0).end_bucket_elapsed_nanos());
-}
+// TODO(b/149590301): Update these tests to use new socket schema.
+//TEST(AttributionE2eTest, TestAttributionMatchAndSliceByFirstUid) {
+// auto config = CreateStatsdConfig(Position::FIRST);
+// int64_t bucketStartTimeNs = 10000000000;
+// int64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
+//
+// ConfigKey cfgKey;
+// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+//
+// // Here it assumes that GMS core has two uids.
+// processor->getUidMap()->updateMap(
+// 1, {222, 444, 111, 333}, {1, 1, 2, 2},
+// {String16("v1"), String16("v1"), String16("v2"), String16("v2")},
+// {String16("com.android.gmscore"), String16("com.android.gmscore"), String16("app1"),
+// String16("APP3")},
+// {String16(""), String16(""), String16(""), String16("")});
+//
+// // GMS core node is in the middle.
+// std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"),
+// CreateAttribution(222, "GMSCoreModule1"),
+// CreateAttribution(333, "App3")};
+//
+// // GMS core node is the last one.
+// std::vector<AttributionNodeInternal> attributions2 = {CreateAttribution(111, "App1"),
+// CreateAttribution(333, "App3"),
+// CreateAttribution(222, "GMSCoreModule1")};
+//
+// // GMS core node is the first one.
+// std::vector<AttributionNodeInternal> attributions3 = {CreateAttribution(222, "GMSCoreModule1"),
+// CreateAttribution(333, "App3")};
+//
+// // Single GMS core node.
+// std::vector<AttributionNodeInternal> attributions4 = {CreateAttribution(222, "GMSCoreModule1")};
+//
+// // GMS core has another uid.
+// std::vector<AttributionNodeInternal> attributions5 = {CreateAttribution(111, "App1"),
+// CreateAttribution(444, "GMSCoreModule2"),
+// CreateAttribution(333, "App3")};
+//
+// // Multiple GMS core nodes.
+// std::vector<AttributionNodeInternal> attributions6 = {CreateAttribution(444, "GMSCoreModule2"),
+// CreateAttribution(222, "GMSCoreModule1")};
+//
+// // No GMS core nodes.
+// std::vector<AttributionNodeInternal> attributions7 = {CreateAttribution(111, "App1"),
+// CreateAttribution(333, "App3")};
+// std::vector<AttributionNodeInternal> attributions8 = {CreateAttribution(111, "App1")};
+//
+// // GMS core node with isolated uid.
+// const int isolatedUid = 666;
+// std::vector<AttributionNodeInternal> attributions9 = {
+// CreateAttribution(isolatedUid, "GMSCoreModule3")};
+//
+// std::vector<std::unique_ptr<LogEvent>> events;
+// // Events 1~4 are in the 1st bucket.
+// events.push_back(CreateAcquireWakelockEvent(
+// attributions1, "wl1", bucketStartTimeNs + 2));
+// events.push_back(CreateAcquireWakelockEvent(
+// attributions2, "wl1", bucketStartTimeNs + 200));
+// events.push_back(CreateAcquireWakelockEvent(
+// attributions3, "wl1", bucketStartTimeNs + bucketSizeNs - 1));
+// events.push_back(CreateAcquireWakelockEvent(
+// attributions4, "wl1", bucketStartTimeNs + bucketSizeNs));
+//
+// // Events 5~8 are in the 3rd bucket.
+// events.push_back(CreateAcquireWakelockEvent(
+// attributions5, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 1));
+// events.push_back(CreateAcquireWakelockEvent(
+// attributions6, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 100));
+// events.push_back(CreateAcquireWakelockEvent(
+// attributions7, "wl2", bucketStartTimeNs + 3 * bucketSizeNs - 2));
+// events.push_back(CreateAcquireWakelockEvent(
+// attributions8, "wl2", bucketStartTimeNs + 3 * bucketSizeNs));
+// events.push_back(CreateAcquireWakelockEvent(
+// attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 1));
+// events.push_back(CreateAcquireWakelockEvent(
+// attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 100));
+// events.push_back(CreateIsolatedUidChangedEvent(
+// isolatedUid, 222, true/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs - 1));
+// events.push_back(CreateIsolatedUidChangedEvent(
+// isolatedUid, 222, false/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs + 10));
+//
+// sortLogEventsByTimestamp(&events);
+//
+// for (const auto& event : events) {
+// processor->OnLogEvent(event.get());
+// }
+// ConfigMetricsReportList reports;
+// vector<uint8_t> buffer;
+// processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, false, true,
+// ADB_DUMP, FAST, &buffer);
+// EXPECT_TRUE(buffer.size() > 0);
+// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+// backfillDimensionPath(&reports);
+// backfillStringInReport(&reports);
+// backfillStartEndTimestamp(&reports);
+// EXPECT_EQ(reports.reports_size(), 1);
+// EXPECT_EQ(reports.reports(0).metrics_size(), 1);
+//
+// StatsLogReport::CountMetricDataWrapper countMetrics;
+// sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
+// EXPECT_EQ(countMetrics.data_size(), 4);
+//
+// auto data = countMetrics.data(0);
+// ValidateAttributionUidAndTagDimension(
+// data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 111,
+// "App1");
+// EXPECT_EQ(data.bucket_info_size(), 2);
+// EXPECT_EQ(data.bucket_info(0).count(), 2);
+// EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+// EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
+// EXPECT_EQ(data.bucket_info(1).count(), 1);
+// EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
+// EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
+//
+// data = countMetrics.data(1);
+// ValidateAttributionUidAndTagDimension(
+// data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 222,
+// "GMSCoreModule1");
+// EXPECT_EQ(data.bucket_info_size(), 2);
+// EXPECT_EQ(data.bucket_info(0).count(), 1);
+// EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+// EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
+// EXPECT_EQ(data.bucket_info(1).count(), 1);
+// EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
+// EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
+//
+// data = countMetrics.data(2);
+// ValidateAttributionUidAndTagDimension(
+// data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 222,
+// "GMSCoreModule3");
+// EXPECT_EQ(data.bucket_info_size(), 1);
+// EXPECT_EQ(data.bucket_info(0).count(), 1);
+// EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
+// EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + 4 * bucketSizeNs);
+//
+// data = countMetrics.data(3);
+// ValidateAttributionUidAndTagDimension(
+// data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 444,
+// "GMSCoreModule2");
+// EXPECT_EQ(data.bucket_info_size(), 1);
+// EXPECT_EQ(data.bucket_info(0).count(), 1);
+// EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
+// EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
+//}
+//
+//TEST(AttributionE2eTest, TestAttributionMatchAndSliceByChain) {
+// auto config = CreateStatsdConfig(Position::ALL);
+// int64_t bucketStartTimeNs = 10000000000;
+// int64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
+//
+// ConfigKey cfgKey;
+// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+//
+// // Here it assumes that GMS core has two uids.
+// processor->getUidMap()->updateMap(
+// 1, {222, 444, 111, 333}, {1, 1, 2, 2},
+// {String16("v1"), String16("v1"), String16("v2"), String16("v2")},
+// {String16("com.android.gmscore"), String16("com.android.gmscore"), String16("app1"),
+// String16("APP3")},
+// {String16(""), String16(""), String16(""), String16("")});
+//
+// // GMS core node is in the middle.
+// std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"),
+// CreateAttribution(222, "GMSCoreModule1"),
+// CreateAttribution(333, "App3")};
+//
+// // GMS core node is the last one.
+// std::vector<AttributionNodeInternal> attributions2 = {CreateAttribution(111, "App1"),
+// CreateAttribution(333, "App3"),
+// CreateAttribution(222, "GMSCoreModule1")};
+//
+// // GMS core node is the first one.
+// std::vector<AttributionNodeInternal> attributions3 = {CreateAttribution(222, "GMSCoreModule1"),
+// CreateAttribution(333, "App3")};
+//
+// // Single GMS core node.
+// std::vector<AttributionNodeInternal> attributions4 = {CreateAttribution(222, "GMSCoreModule1")};
+//
+// // GMS core has another uid.
+// std::vector<AttributionNodeInternal> attributions5 = {CreateAttribution(111, "App1"),
+// CreateAttribution(444, "GMSCoreModule2"),
+// CreateAttribution(333, "App3")};
+//
+// // Multiple GMS core nodes.
+// std::vector<AttributionNodeInternal> attributions6 = {CreateAttribution(444, "GMSCoreModule2"),
+// CreateAttribution(222, "GMSCoreModule1")};
+//
+// // No GMS core nodes.
+// std::vector<AttributionNodeInternal> attributions7 = {CreateAttribution(111, "App1"),
+// CreateAttribution(333, "App3")};
+// std::vector<AttributionNodeInternal> attributions8 = {CreateAttribution(111, "App1")};
+//
+// // GMS core node with isolated uid.
+// const int isolatedUid = 666;
+// std::vector<AttributionNodeInternal> attributions9 = {
+// CreateAttribution(isolatedUid, "GMSCoreModule1")};
+//
+// std::vector<std::unique_ptr<LogEvent>> events;
+// // Events 1~4 are in the 1st bucket.
+// events.push_back(CreateAcquireWakelockEvent(
+// attributions1, "wl1", bucketStartTimeNs + 2));
+// events.push_back(CreateAcquireWakelockEvent(
+// attributions2, "wl1", bucketStartTimeNs + 200));
+// events.push_back(CreateAcquireWakelockEvent(
+// attributions3, "wl1", bucketStartTimeNs + bucketSizeNs - 1));
+// events.push_back(CreateAcquireWakelockEvent(
+// attributions4, "wl1", bucketStartTimeNs + bucketSizeNs));
+//
+// // Events 5~8 are in the 3rd bucket.
+// events.push_back(CreateAcquireWakelockEvent(
+// attributions5, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 1));
+// events.push_back(CreateAcquireWakelockEvent(
+// attributions6, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 100));
+// events.push_back(CreateAcquireWakelockEvent(
+// attributions7, "wl2", bucketStartTimeNs + 3 * bucketSizeNs - 2));
+// events.push_back(CreateAcquireWakelockEvent(
+// attributions8, "wl2", bucketStartTimeNs + 3 * bucketSizeNs));
+// events.push_back(CreateAcquireWakelockEvent(
+// attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 1));
+// events.push_back(CreateAcquireWakelockEvent(
+// attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 100));
+// events.push_back(CreateIsolatedUidChangedEvent(
+// isolatedUid, 222, true/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs - 1));
+// events.push_back(CreateIsolatedUidChangedEvent(
+// isolatedUid, 222, false/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs + 10));
+//
+// sortLogEventsByTimestamp(&events);
+//
+// for (const auto& event : events) {
+// processor->OnLogEvent(event.get());
+// }
+// ConfigMetricsReportList reports;
+// vector<uint8_t> buffer;
+// processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, false, true,
+// ADB_DUMP, FAST, &buffer);
+// EXPECT_TRUE(buffer.size() > 0);
+// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+// backfillDimensionPath(&reports);
+// backfillStringInReport(&reports);
+// backfillStartEndTimestamp(&reports);
+// EXPECT_EQ(reports.reports_size(), 1);
+// EXPECT_EQ(reports.reports(0).metrics_size(), 1);
+//
+// StatsLogReport::CountMetricDataWrapper countMetrics;
+// sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
+// EXPECT_EQ(countMetrics.data_size(), 6);
+//
+// auto data = countMetrics.data(0);
+// ValidateAttributionUidAndTagDimension(
+// data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
+// EXPECT_EQ(2, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
+// data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+// data.bucket_info(0).end_bucket_elapsed_nanos());
+// EXPECT_EQ(1, data.bucket_info(1).count());
+// EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
+// data.bucket_info(1).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + 4 * bucketSizeNs,
+// data.bucket_info(1).end_bucket_elapsed_nanos());
+//
+// data = countMetrics.data(1);
+// ValidateUidDimension(
+// data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 222);
+// ValidateAttributionUidAndTagDimension(
+// data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
+// ValidateUidDimension(
+// data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333);
+// ValidateAttributionUidAndTagDimension(
+// data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
+// EXPECT_EQ(data.bucket_info_size(), 1);
+// EXPECT_EQ(data.bucket_info(0).count(), 1);
+// EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+// EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
+//
+// data = countMetrics.data(2);
+// ValidateUidDimension(
+// data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 444);
+// ValidateAttributionUidAndTagDimension(
+// data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 444, "GMSCoreModule2");
+// ValidateUidDimension(
+// data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222);
+// ValidateAttributionUidAndTagDimension(
+// data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
+// EXPECT_EQ(data.bucket_info_size(), 1);
+// EXPECT_EQ(data.bucket_info(0).count(), 1);
+// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+// data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
+// data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+// data = countMetrics.data(3);
+// ValidateUidDimension(
+// data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111);
+// ValidateAttributionUidAndTagDimension(
+// data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111, "App1");
+// ValidateUidDimension(
+// data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222);
+// ValidateAttributionUidAndTagDimension(
+// data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
+// ValidateUidDimension(
+// data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333);
+// ValidateAttributionUidAndTagDimension(
+// data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
+// EXPECT_EQ(data.bucket_info_size(), 1);
+// EXPECT_EQ(data.bucket_info(0).count(), 1);
+// EXPECT_EQ(bucketStartTimeNs,
+// data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
+// data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+// data = countMetrics.data(4);
+// ValidateUidDimension(
+// data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111);
+// ValidateAttributionUidAndTagDimension(
+// data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111, "App1");
+// ValidateUidDimension(
+// data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333);
+// ValidateAttributionUidAndTagDimension(
+// data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
+// ValidateUidDimension(
+// data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 222);
+// ValidateAttributionUidAndTagDimension(
+// data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
+// EXPECT_EQ(data.bucket_info_size(), 1);
+// EXPECT_EQ(data.bucket_info(0).count(), 1);
+// EXPECT_EQ(bucketStartTimeNs,
+// data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
+// data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+// data = countMetrics.data(5);
+// ValidateUidDimension(
+// data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111);
+// ValidateAttributionUidAndTagDimension(
+// data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111, "App1");
+// ValidateUidDimension(
+// data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 444);
+// ValidateAttributionUidAndTagDimension(
+// data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 444, "GMSCoreModule2");
+// ValidateUidDimension(
+// data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333);
+// ValidateAttributionUidAndTagDimension(
+// data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
+// EXPECT_EQ(data.bucket_info_size(), 1);
+// EXPECT_EQ(data.bucket_info(0).count(), 1);
+// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+// data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
+// data.bucket_info(0).end_bucket_elapsed_nanos());
+//}
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
diff --git a/cmds/statsd/tests/e2e/ConfigTtl_e2e_test.cpp b/cmds/statsd/tests/e2e/ConfigTtl_e2e_test.cpp
index 325e869..f8edee5 100644
--- a/cmds/statsd/tests/e2e/ConfigTtl_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/ConfigTtl_e2e_test.cpp
@@ -56,52 +56,53 @@
} // namespace
-TEST(ConfigTtlE2eTest, TestCountMetric) {
- const int num_buckets = 1;
- const int threshold = 3;
- auto config = CreateStatsdConfig(num_buckets, threshold);
- const uint64_t alert_id = config.alert(0).id();
- const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
-
- int64_t bucketStartTimeNs = 10000000000;
- int64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
-
- ConfigKey cfgKey;
- auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
- EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
- EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-
- std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
-
- FieldValue fieldValue1(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
- Value((int32_t)111));
- HashableDimensionKey whatKey1({fieldValue1});
- MetricDimensionKey dimensionKey1(whatKey1, DEFAULT_DIMENSION_KEY);
-
- FieldValue fieldValue2(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
- Value((int32_t)222));
- HashableDimensionKey whatKey2({fieldValue2});
- MetricDimensionKey dimensionKey2(whatKey2, DEFAULT_DIMENSION_KEY);
-
- auto event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 2);
- processor->OnLogEvent(event.get());
-
- event = CreateAcquireWakelockEvent(attributions1, "wl2", bucketStartTimeNs + bucketSizeNs + 2);
- processor->OnLogEvent(event.get());
-
- event = CreateAcquireWakelockEvent(
- attributions1, "wl1", bucketStartTimeNs + 25 * bucketSizeNs + 2);
- processor->OnLogEvent(event.get());
-
- EXPECT_EQ((int64_t)(bucketStartTimeNs + 25 * bucketSizeNs + 2 + 2 * 3600 * NS_PER_SEC),
- processor->mMetricsManagers.begin()->second->getTtlEndNs());
-
- // Clear the data stored on disk as a result of the ttl.
- vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 25 * bucketSizeNs + 3, false, true,
- ADB_DUMP, FAST, &buffer);
-}
+// TODO(b/149590301): Update this test to use new socket schema.
+//TEST(ConfigTtlE2eTest, TestCountMetric) {
+// const int num_buckets = 1;
+// const int threshold = 3;
+// auto config = CreateStatsdConfig(num_buckets, threshold);
+// const uint64_t alert_id = config.alert(0).id();
+// const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
+//
+// int64_t bucketStartTimeNs = 10000000000;
+// int64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
+//
+// ConfigKey cfgKey;
+// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+//
+// std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
+//
+// FieldValue fieldValue1(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
+// Value((int32_t)111));
+// HashableDimensionKey whatKey1({fieldValue1});
+// MetricDimensionKey dimensionKey1(whatKey1, DEFAULT_DIMENSION_KEY);
+//
+// FieldValue fieldValue2(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
+// Value((int32_t)222));
+// HashableDimensionKey whatKey2({fieldValue2});
+// MetricDimensionKey dimensionKey2(whatKey2, DEFAULT_DIMENSION_KEY);
+//
+// auto event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 2);
+// processor->OnLogEvent(event.get());
+//
+// event = CreateAcquireWakelockEvent(attributions1, "wl2", bucketStartTimeNs + bucketSizeNs + 2);
+// processor->OnLogEvent(event.get());
+//
+// event = CreateAcquireWakelockEvent(
+// attributions1, "wl1", bucketStartTimeNs + 25 * bucketSizeNs + 2);
+// processor->OnLogEvent(event.get());
+//
+// EXPECT_EQ((int64_t)(bucketStartTimeNs + 25 * bucketSizeNs + 2 + 2 * 3600 * NS_PER_SEC),
+// processor->mMetricsManagers.begin()->second->getTtlEndNs());
+//
+// // Clear the data stored on disk as a result of the ttl.
+// vector<uint8_t> buffer;
+// processor->onDumpReport(cfgKey, bucketStartTimeNs + 25 * bucketSizeNs + 3, false, true,
+// ADB_DUMP, FAST, &buffer);
+//}
#else
diff --git a/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp b/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp
index 15fc468..a1f74a6 100644
--- a/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp
@@ -27,772 +27,773 @@
#ifdef __ANDROID__
-/**
- * Test a count metric that has one slice_by_state with no primary fields.
- *
- * Once the CountMetricProducer is initialized, it has one atom id in
- * mSlicedStateAtoms and no entries in mStateGroupMap.
-
- * One StateTracker tracks the state atom, and it has one listener which is the
- * CountMetricProducer that was initialized.
- */
-TEST(CountMetricE2eTest, TestSlicedState) {
- // Initialize config.
- StatsdConfig config;
- config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
-
- auto syncStartMatcher = CreateSyncStartAtomMatcher();
- *config.add_atom_matcher() = syncStartMatcher;
-
- auto state = CreateScreenState();
- *config.add_state() = state;
-
- // Create count metric that slices by screen state.
- int64_t metricId = 123456;
- auto countMetric = config.add_count_metric();
- countMetric->set_id(metricId);
- countMetric->set_what(syncStartMatcher.id());
- countMetric->set_bucket(TimeUnit::FIVE_MINUTES);
- countMetric->add_slice_by_state(state.id());
-
- // Initialize StatsLogProcessor.
- const uint64_t bucketStartTimeNs = 10000000000; // 0:10
- const uint64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
- int uid = 12345;
- int64_t cfgId = 98765;
- ConfigKey cfgKey(uid, cfgId);
- auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-
- // Check that CountMetricProducer was initialized correctly.
- EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
- sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
- EXPECT_TRUE(metricsManager->isConfigValid());
- EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
- sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
- EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
- EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), SCREEN_STATE_ATOM_ID);
- EXPECT_EQ(metricProducer->mStateGroupMap.size(), 0);
-
- // Check that StateTrackers were initialized correctly.
- EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
- EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
-
- /*
- bucket #1 bucket #2
- | 1 2 3 4 5 6 7 8 9 10 (minutes)
- |-----------------------------|-----------------------------|--
- x x x x x x (syncStartEvents)
- | | (ScreenIsOnEvent)
- | | (ScreenIsOffEvent)
- | (ScreenUnknownEvent)
- */
- // Initialize log events - first bucket.
- int appUid = 123;
- std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(appUid, "App1")};
- std::vector<std::unique_ptr<LogEvent>> events;
- events.push_back(
- CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
- bucketStartTimeNs + 50 * NS_PER_SEC)); // 1:00
- events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
- bucketStartTimeNs + 75 * NS_PER_SEC)); // 1:25
- events.push_back(
- CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
- bucketStartTimeNs + 150 * NS_PER_SEC)); // 2:40
- events.push_back(
- CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
- bucketStartTimeNs + 200 * NS_PER_SEC)); // 3:30
- events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
- bucketStartTimeNs + 250 * NS_PER_SEC)); // 4:20
-
- // Initialize log events - second bucket.
- events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
- bucketStartTimeNs + 350 * NS_PER_SEC)); // 6:00
- events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
- bucketStartTimeNs + 400 * NS_PER_SEC)); // 6:50
- events.push_back(
- CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
- bucketStartTimeNs + 450 * NS_PER_SEC)); // 7:40
- events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
- bucketStartTimeNs + 475 * NS_PER_SEC)); // 8:05
- events.push_back(
- CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_UNKNOWN,
- bucketStartTimeNs + 500 * NS_PER_SEC)); // 8:30
- events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
- bucketStartTimeNs + 520 * NS_PER_SEC)); // 8:50
-
- // Send log events to StatsLogProcessor.
- for (auto& event : events) {
- processor->OnLogEvent(event.get());
- }
-
- // Check dump report.
- vector<uint8_t> buffer;
- ConfigMetricsReportList reports;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs * 2 + 1, false, true, ADB_DUMP,
- FAST, &buffer);
- EXPECT_GT(buffer.size(), 0);
- EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
- backfillDimensionPath(&reports);
- backfillStringInReport(&reports);
- backfillStartEndTimestamp(&reports);
-
- EXPECT_EQ(1, reports.reports_size());
- EXPECT_EQ(1, reports.reports(0).metrics_size());
- EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
- EXPECT_EQ(3, reports.reports(0).metrics(0).count_metrics().data_size());
-
- // For each CountMetricData, check StateValue info is correct and buckets
- // have correct counts.
- auto data = reports.reports(0).metrics(0).count_metrics().data(0);
- EXPECT_EQ(1, data.slice_by_state_size());
- EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
- EXPECT_TRUE(data.slice_by_state(0).has_value());
- EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON, data.slice_by_state(0).value());
- EXPECT_EQ(2, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
- EXPECT_EQ(1, data.bucket_info(1).count());
-
- data = reports.reports(0).metrics(0).count_metrics().data(1);
- EXPECT_EQ(1, data.slice_by_state_size());
- EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
- EXPECT_TRUE(data.slice_by_state(0).has_value());
- EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_UNKNOWN, data.slice_by_state(0).value());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
-
- data = reports.reports(0).metrics(0).count_metrics().data(2);
- EXPECT_EQ(1, data.slice_by_state_size());
- EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
- EXPECT_TRUE(data.slice_by_state(0).has_value());
- EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF, data.slice_by_state(0).value());
- EXPECT_EQ(2, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
- EXPECT_EQ(2, data.bucket_info(1).count());
-}
-
-/**
- * Test a count metric that has one slice_by_state with a mapping and no
- * primary fields.
- *
- * Once the CountMetricProducer is initialized, it has one atom id in
- * mSlicedStateAtoms and has one entry per state value in mStateGroupMap.
- *
- * One StateTracker tracks the state atom, and it has one listener which is the
- * CountMetricProducer that was initialized.
- */
-TEST(CountMetricE2eTest, TestSlicedStateWithMap) {
- // Initialize config.
- StatsdConfig config;
- config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
-
- auto syncStartMatcher = CreateSyncStartAtomMatcher();
- *config.add_atom_matcher() = syncStartMatcher;
-
- auto state = CreateScreenStateWithOnOffMap();
- *config.add_state() = state;
-
- // Create count metric that slices by screen state with on/off map.
- int64_t metricId = 123456;
- auto countMetric = config.add_count_metric();
- countMetric->set_id(metricId);
- countMetric->set_what(syncStartMatcher.id());
- countMetric->set_bucket(TimeUnit::FIVE_MINUTES);
- countMetric->add_slice_by_state(state.id());
-
- // Initialize StatsLogProcessor.
- const uint64_t bucketStartTimeNs = 10000000000; // 0:10
- const uint64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
- int uid = 12345;
- int64_t cfgId = 98765;
- ConfigKey cfgKey(uid, cfgId);
- auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-
- // Check that StateTrackers were initialized correctly.
- EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
- EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
-
- // Check that CountMetricProducer was initialized correctly.
- EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
- sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
- EXPECT_TRUE(metricsManager->isConfigValid());
- EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
- sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
- EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
- EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), SCREEN_STATE_ATOM_ID);
- EXPECT_EQ(metricProducer->mStateGroupMap.size(), 1);
-
- StateMap map = state.map();
- for (auto group : map.group()) {
- for (auto value : group.value()) {
- EXPECT_EQ(metricProducer->mStateGroupMap[SCREEN_STATE_ATOM_ID][value],
- group.group_id());
- }
- }
-
- /*
- bucket #1 bucket #2
- | 1 2 3 4 5 6 7 8 9 10 (minutes)
- |-----------------------------|-----------------------------|--
- x x x x x x x x x (syncStartEvents)
- -----------------------------------------------------------SCREEN_OFF events
- | (ScreenStateUnknownEvent = 0)
- | | (ScreenStateOffEvent = 1)
- | (ScreenStateDozeEvent = 3)
- | (ScreenStateDozeSuspendEvent = 4)
- -----------------------------------------------------------SCREEN_ON events
- | | (ScreenStateOnEvent = 2)
- | (ScreenStateVrEvent = 5)
- | (ScreenStateOnSuspendEvent = 6)
- */
- // Initialize log events - first bucket.
- int appUid = 123;
- std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(appUid, "App1")};
-
- std::vector<std::unique_ptr<LogEvent>> events;
- events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
- bucketStartTimeNs + 20 * NS_PER_SEC)); // 0:30
- events.push_back(
- CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_UNKNOWN,
- bucketStartTimeNs + 30 * NS_PER_SEC)); // 0:40
- events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
- bucketStartTimeNs + 60 * NS_PER_SEC)); // 1:10
- events.push_back(
- CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
- bucketStartTimeNs + 90 * NS_PER_SEC)); // 1:40
- events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
- bucketStartTimeNs + 120 * NS_PER_SEC)); // 2:10
- events.push_back(
- CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
- bucketStartTimeNs + 150 * NS_PER_SEC)); // 2:40
- events.push_back(
- CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_VR,
- bucketStartTimeNs + 180 * NS_PER_SEC)); // 3:10
- events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
- bucketStartTimeNs + 200 * NS_PER_SEC)); // 3:30
- events.push_back(
- CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_DOZE,
- bucketStartTimeNs + 210 * NS_PER_SEC)); // 3:40
- events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
- bucketStartTimeNs + 250 * NS_PER_SEC)); // 4:20
- events.push_back(
- CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
- bucketStartTimeNs + 280 * NS_PER_SEC)); // 4:50
- events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
- bucketStartTimeNs + 285 * NS_PER_SEC)); // 4:55
-
- // Initialize log events - second bucket.
- events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
- bucketStartTimeNs + 360 * NS_PER_SEC)); // 6:10
- events.push_back(
- CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON_SUSPEND,
- bucketStartTimeNs + 390 * NS_PER_SEC)); // 6:40
- events.push_back(CreateScreenStateChangedEvent(
- android::view::DisplayStateEnum::DISPLAY_STATE_DOZE_SUSPEND,
- bucketStartTimeNs + 430 * NS_PER_SEC)); // 7:20
- events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
- bucketStartTimeNs + 440 * NS_PER_SEC)); // 7:30
- events.push_back(
- CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
- bucketStartTimeNs + 540 * NS_PER_SEC)); // 9:10
- events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
- bucketStartTimeNs + 570 * NS_PER_SEC)); // 9:40
-
- // Send log events to StatsLogProcessor.
- for (auto& event : events) {
- processor->OnLogEvent(event.get());
- }
-
- // Check dump report.
- vector<uint8_t> buffer;
- ConfigMetricsReportList reports;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs * 2 + 1, false, true, ADB_DUMP,
- FAST, &buffer);
- EXPECT_GT(buffer.size(), 0);
- EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
- backfillDimensionPath(&reports);
- backfillStringInReport(&reports);
- backfillStartEndTimestamp(&reports);
-
- EXPECT_EQ(1, reports.reports_size());
- EXPECT_EQ(1, reports.reports(0).metrics_size());
- EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
- EXPECT_EQ(3, reports.reports(0).metrics(0).count_metrics().data_size());
-
- // For each CountMetricData, check StateValue info is correct and buckets
- // have correct counts.
- auto data = reports.reports(0).metrics(0).count_metrics().data(0);
- EXPECT_EQ(1, data.slice_by_state_size());
- EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
- EXPECT_TRUE(data.slice_by_state(0).has_value());
- EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, data.slice_by_state(0).value());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
-
- data = reports.reports(0).metrics(0).count_metrics().data(1);
- EXPECT_EQ(1, data.slice_by_state_size());
- EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
- EXPECT_TRUE(data.slice_by_state(0).has_group_id());
- EXPECT_EQ(StringToId("SCREEN_OFF"), data.slice_by_state(0).group_id());
- EXPECT_EQ(2, data.bucket_info_size());
- EXPECT_EQ(4, data.bucket_info(0).count());
- EXPECT_EQ(2, data.bucket_info(1).count());
-
- data = reports.reports(0).metrics(0).count_metrics().data(2);
- EXPECT_EQ(1, data.slice_by_state_size());
- EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
- EXPECT_TRUE(data.slice_by_state(0).has_group_id());
- EXPECT_EQ(StringToId("SCREEN_ON"), data.slice_by_state(0).group_id());
- EXPECT_EQ(2, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
- EXPECT_EQ(1, data.bucket_info(1).count());
-}
-
-/**
- * Test a count metric that has one slice_by_state with a primary field.
-
- * Once the CountMetricProducer is initialized, it should have one
- * MetricStateLink stored. State querying using a non-empty primary key
- * should also work as intended.
- */
-TEST(CountMetricE2eTest, TestSlicedStateWithPrimaryFields) {
- // Initialize config.
- StatsdConfig config;
- config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
-
- auto appCrashMatcher =
- CreateSimpleAtomMatcher("APP_CRASH_OCCURRED", android::util::APP_CRASH_OCCURRED);
- *config.add_atom_matcher() = appCrashMatcher;
-
- auto state = CreateUidProcessState();
- *config.add_state() = state;
-
- // Create count metric that slices by uid process state.
- int64_t metricId = 123456;
- auto countMetric = config.add_count_metric();
- countMetric->set_id(metricId);
- countMetric->set_what(appCrashMatcher.id());
- countMetric->set_bucket(TimeUnit::FIVE_MINUTES);
- countMetric->add_slice_by_state(state.id());
- MetricStateLink* stateLink = countMetric->add_state_link();
- stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
- auto fieldsInWhat = stateLink->mutable_fields_in_what();
- *fieldsInWhat = CreateDimensions(android::util::APP_CRASH_OCCURRED, {1 /* uid */});
- auto fieldsInState = stateLink->mutable_fields_in_state();
- *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
-
- // Initialize StatsLogProcessor.
- const uint64_t bucketStartTimeNs = 10000000000; // 0:10
- const uint64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
- int uid = 12345;
- int64_t cfgId = 98765;
- ConfigKey cfgKey(uid, cfgId);
- auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-
- // Check that StateTrackers were initialized correctly.
- EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
- EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
-
- // Check that CountMetricProducer was initialized correctly.
- EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
- sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
- EXPECT_TRUE(metricsManager->isConfigValid());
- EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
- sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
- EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
- EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), UID_PROCESS_STATE_ATOM_ID);
- EXPECT_EQ(metricProducer->mStateGroupMap.size(), 0);
- EXPECT_EQ(metricProducer->mMetric2StateLinks.size(), 1);
-
- /*
- NOTE: "1" or "2" represents the uid associated with the state/app crash event
- bucket #1 bucket #2
- | 1 2 3 4 5 6 7 8 9 10
- |-----------------------------|-----------------------------|--
- 1 1 1 1 1 2 1 1 2 (AppCrashEvents)
- -----------------------------------------------------------PROCESS STATE events
- 1 2 (ProcessStateTopEvent = 1002)
- 1 1 (ProcessStateForegroundServiceEvent = 1003)
- 2 (ProcessStateImportantBackgroundEvent = 1006)
- 1 1 1 (ProcessStateImportantForegroundEvent = 1005)
-
- Based on the diagram above, an AppCrashEvent querying for process state value would return:
- - StateTracker::kStateUnknown
- - Important foreground
- - Top
- - Important foreground
- - Foreground service
- - Top (both the app crash and state still have matching uid = 2)
-
- - Foreground service
- - Foreground service
- - Important background
- */
- // Initialize log events - first bucket.
- std::vector<std::unique_ptr<LogEvent>> events;
- events.push_back(
- CreateAppCrashOccurredEvent(1 /* uid */, bucketStartTimeNs + 20 * NS_PER_SEC)); // 0:30
- events.push_back(CreateUidProcessStateChangedEvent(
- 1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
- bucketStartTimeNs + 30 * NS_PER_SEC)); // 0:40
- events.push_back(
- CreateAppCrashOccurredEvent(1 /* uid */, bucketStartTimeNs + 60 * NS_PER_SEC)); // 1:10
- events.push_back(CreateUidProcessStateChangedEvent(
- 1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_TOP,
- bucketStartTimeNs + 90 * NS_PER_SEC)); // 1:40
- events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
- bucketStartTimeNs + 120 * NS_PER_SEC)); // 2:10
- events.push_back(CreateUidProcessStateChangedEvent(
- 1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
- bucketStartTimeNs + 150 * NS_PER_SEC)); // 2:40
- events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
- bucketStartTimeNs + 200 * NS_PER_SEC)); // 3:30
- events.push_back(CreateUidProcessStateChangedEvent(
- 1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE,
- bucketStartTimeNs + 210 * NS_PER_SEC)); // 3:40
- events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
- bucketStartTimeNs + 250 * NS_PER_SEC)); // 4:20
- events.push_back(CreateUidProcessStateChangedEvent(
- 2 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_TOP,
- bucketStartTimeNs + 280 * NS_PER_SEC)); // 4:50
- events.push_back(CreateAppCrashOccurredEvent(2 /* uid */,
- bucketStartTimeNs + 285 * NS_PER_SEC)); // 4:55
-
- // Initialize log events - second bucket.
- events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
- bucketStartTimeNs + 360 * NS_PER_SEC)); // 6:10
- events.push_back(CreateUidProcessStateChangedEvent(
- 1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE,
- bucketStartTimeNs + 390 * NS_PER_SEC)); // 6:40
- events.push_back(CreateUidProcessStateChangedEvent(
- 2 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
- bucketStartTimeNs + 430 * NS_PER_SEC)); // 7:20
- events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
- bucketStartTimeNs + 440 * NS_PER_SEC)); // 7:30
- events.push_back(CreateUidProcessStateChangedEvent(
- 1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
- bucketStartTimeNs + 540 * NS_PER_SEC)); // 9:10
- events.push_back(CreateAppCrashOccurredEvent(2 /* uid */,
- bucketStartTimeNs + 570 * NS_PER_SEC)); // 9:40
-
- // Send log events to StatsLogProcessor.
- for (auto& event : events) {
- processor->OnLogEvent(event.get());
- }
-
- // Check dump report.
- vector<uint8_t> buffer;
- ConfigMetricsReportList reports;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs * 2 + 1, false, true, ADB_DUMP,
- FAST, &buffer);
- EXPECT_GT(buffer.size(), 0);
- EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
- backfillDimensionPath(&reports);
- backfillStringInReport(&reports);
- backfillStartEndTimestamp(&reports);
-
- EXPECT_EQ(1, reports.reports_size());
- EXPECT_EQ(1, reports.reports(0).metrics_size());
- EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
- EXPECT_EQ(5, reports.reports(0).metrics(0).count_metrics().data_size());
-
- // For each CountMetricData, check StateValue info is correct and buckets
- // have correct counts.
- auto data = reports.reports(0).metrics(0).count_metrics().data(0);
- EXPECT_EQ(1, data.slice_by_state_size());
- EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
- EXPECT_TRUE(data.slice_by_state(0).has_value());
- EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, data.slice_by_state(0).value());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
-
- data = reports.reports(0).metrics(0).count_metrics().data(1);
- EXPECT_EQ(1, data.slice_by_state_size());
- EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
- EXPECT_TRUE(data.slice_by_state(0).has_value());
- EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, data.slice_by_state(0).value());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
-
- data = reports.reports(0).metrics(0).count_metrics().data(2);
- EXPECT_EQ(1, data.slice_by_state_size());
- EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
- EXPECT_TRUE(data.slice_by_state(0).has_value());
- EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, data.slice_by_state(0).value());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(2, data.bucket_info(0).count());
-
- data = reports.reports(0).metrics(0).count_metrics().data(3);
- EXPECT_EQ(1, data.slice_by_state_size());
- EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
- EXPECT_TRUE(data.slice_by_state(0).has_value());
- EXPECT_EQ(android::app::PROCESS_STATE_TOP, data.slice_by_state(0).value());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(2, data.bucket_info(0).count());
-
- data = reports.reports(0).metrics(0).count_metrics().data(4);
- EXPECT_EQ(1, data.slice_by_state_size());
- EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
- EXPECT_TRUE(data.slice_by_state(0).has_value());
- EXPECT_EQ(android::app::PROCESS_STATE_FOREGROUND_SERVICE, data.slice_by_state(0).value());
- EXPECT_EQ(2, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
- EXPECT_EQ(2, data.bucket_info(1).count());
-}
-
-TEST(CountMetricE2eTest, TestMultipleSlicedStates) {
- // Initialize config.
- StatsdConfig config;
- config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
-
- auto appCrashMatcher =
- CreateSimpleAtomMatcher("APP_CRASH_OCCURRED", android::util::APP_CRASH_OCCURRED);
- *config.add_atom_matcher() = appCrashMatcher;
-
- auto state1 = CreateScreenStateWithOnOffMap();
- *config.add_state() = state1;
- auto state2 = CreateUidProcessState();
- *config.add_state() = state2;
-
- // Create count metric that slices by screen state with on/off map and
- // slices by uid process state.
- int64_t metricId = 123456;
- auto countMetric = config.add_count_metric();
- countMetric->set_id(metricId);
- countMetric->set_what(appCrashMatcher.id());
- countMetric->set_bucket(TimeUnit::FIVE_MINUTES);
- countMetric->add_slice_by_state(state1.id());
- countMetric->add_slice_by_state(state2.id());
- MetricStateLink* stateLink = countMetric->add_state_link();
- stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
- auto fieldsInWhat = stateLink->mutable_fields_in_what();
- *fieldsInWhat = CreateDimensions(android::util::APP_CRASH_OCCURRED, {1 /* uid */});
- auto fieldsInState = stateLink->mutable_fields_in_state();
- *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
-
- // Initialize StatsLogProcessor.
- const uint64_t bucketStartTimeNs = 10000000000; // 0:10
- const uint64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
- int uid = 12345;
- int64_t cfgId = 98765;
- ConfigKey cfgKey(uid, cfgId);
- auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-
- // Check that StateTrackers were properly initialized.
- EXPECT_EQ(2, StateManager::getInstance().getStateTrackersCount());
- EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
- EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
-
- // Check that CountMetricProducer was initialized correctly.
- EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
- sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
- EXPECT_TRUE(metricsManager->isConfigValid());
- EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
- sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
- EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 2);
- EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), SCREEN_STATE_ATOM_ID);
- EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(1), UID_PROCESS_STATE_ATOM_ID);
- EXPECT_EQ(metricProducer->mStateGroupMap.size(), 1);
- EXPECT_EQ(metricProducer->mMetric2StateLinks.size(), 1);
-
- StateMap map = state1.map();
- for (auto group : map.group()) {
- for (auto value : group.value()) {
- EXPECT_EQ(metricProducer->mStateGroupMap[SCREEN_STATE_ATOM_ID][value],
- group.group_id());
- }
- }
-
- /*
- bucket #1 bucket #2
- | 1 2 3 4 5 6 7 8 9 10 (minutes)
- |-----------------------------|-----------------------------|--
- 1 1 1 1 1 2 1 1 2 (AppCrashEvents)
- -----------------------------------------------------------SCREEN_OFF events
- | (ScreenStateUnknownEvent = 0)
- | | (ScreenStateOffEvent = 1)
- | (ScreenStateDozeEvent = 3)
- -----------------------------------------------------------SCREEN_ON events
- | | (ScreenStateOnEvent = 2)
- | (ScreenStateOnSuspendEvent = 6)
- -----------------------------------------------------------PROCESS STATE events
- 1 2 (ProcessStateTopEvent = 1002)
- 1 (ProcessStateForegroundServiceEvent = 1003)
- 2 (ProcessStateImportantBackgroundEvent = 1006)
- 1 1 1 (ProcessStateImportantForegroundEvent = 1005)
-
- Based on the diagram above, Screen State / Process State pairs for each
- AppCrashEvent are:
- - StateTracker::kStateUnknown / important foreground
- - off / important foreground
- - off / Top
- - on / important foreground
- - off / important foreground
- - off / top
-
- - off / important foreground
- - off / foreground service
- - on / important background
-
- */
- // Initialize log events - first bucket.
- std::vector<std::unique_ptr<LogEvent>> events;
- events.push_back(CreateUidProcessStateChangedEvent(
- 1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
- bucketStartTimeNs + 5 * NS_PER_SEC)); // 0:15
- events.push_back(
- CreateAppCrashOccurredEvent(1 /* uid */, bucketStartTimeNs + 20 * NS_PER_SEC)); // 0:30
- events.push_back(
- CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_UNKNOWN,
- bucketStartTimeNs + 30 * NS_PER_SEC)); // 0:40
- events.push_back(
- CreateAppCrashOccurredEvent(1 /* uid */, bucketStartTimeNs + 60 * NS_PER_SEC)); // 1:10
- events.push_back(CreateUidProcessStateChangedEvent(
- 1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_TOP,
- bucketStartTimeNs + 90 * NS_PER_SEC)); // 1:40
- events.push_back(
- CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
- bucketStartTimeNs + 90 * NS_PER_SEC)); // 1:40
- events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
- bucketStartTimeNs + 120 * NS_PER_SEC)); // 2:10
- events.push_back(CreateUidProcessStateChangedEvent(
- 1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
- bucketStartTimeNs + 150 * NS_PER_SEC)); // 2:40
- events.push_back(
- CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
- bucketStartTimeNs + 160 * NS_PER_SEC)); // 2:50
- events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
- bucketStartTimeNs + 200 * NS_PER_SEC)); // 3:30
- events.push_back(
- CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_DOZE,
- bucketStartTimeNs + 210 * NS_PER_SEC)); // 3:40
- events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
- bucketStartTimeNs + 250 * NS_PER_SEC)); // 4:20
- events.push_back(CreateUidProcessStateChangedEvent(
- 2 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_TOP,
- bucketStartTimeNs + 280 * NS_PER_SEC)); // 4:50
- events.push_back(CreateAppCrashOccurredEvent(2 /* uid */,
- bucketStartTimeNs + 285 * NS_PER_SEC)); // 4:55
-
- // Initialize log events - second bucket.
- events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
- bucketStartTimeNs + 360 * NS_PER_SEC)); // 6:10
- events.push_back(CreateUidProcessStateChangedEvent(
- 1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE,
- bucketStartTimeNs + 380 * NS_PER_SEC)); // 6:30
- events.push_back(
- CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON_SUSPEND,
- bucketStartTimeNs + 390 * NS_PER_SEC)); // 6:40
- events.push_back(CreateUidProcessStateChangedEvent(
- 2 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
- bucketStartTimeNs + 420 * NS_PER_SEC)); // 7:10
- events.push_back(
- CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
- bucketStartTimeNs + 440 * NS_PER_SEC)); // 7:30
- events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
- bucketStartTimeNs + 450 * NS_PER_SEC)); // 7:40
- events.push_back(
- CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
- bucketStartTimeNs + 520 * NS_PER_SEC)); // 8:50
- events.push_back(CreateUidProcessStateChangedEvent(
- 1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
- bucketStartTimeNs + 540 * NS_PER_SEC)); // 9:10
- events.push_back(CreateAppCrashOccurredEvent(2 /* uid */,
- bucketStartTimeNs + 570 * NS_PER_SEC)); // 9:40
-
- // Send log events to StatsLogProcessor.
- for (auto& event : events) {
- processor->OnLogEvent(event.get());
- }
-
- // Check dump report.
- vector<uint8_t> buffer;
- ConfigMetricsReportList reports;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs * 2 + 1, false, true, ADB_DUMP,
- FAST, &buffer);
- EXPECT_GT(buffer.size(), 0);
- EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
- backfillDimensionPath(&reports);
- backfillStringInReport(&reports);
- backfillStartEndTimestamp(&reports);
-
- EXPECT_EQ(1, reports.reports_size());
- EXPECT_EQ(1, reports.reports(0).metrics_size());
- EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
- EXPECT_EQ(6, reports.reports(0).metrics(0).count_metrics().data_size());
-
- // For each CountMetricData, check StateValue info is correct and buckets
- // have correct counts.
- auto data = reports.reports(0).metrics(0).count_metrics().data(0);
- EXPECT_EQ(2, data.slice_by_state_size());
- EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
- EXPECT_TRUE(data.slice_by_state(0).has_group_id());
- EXPECT_EQ(StringToId("SCREEN_OFF"), data.slice_by_state(0).group_id());
- EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
- EXPECT_TRUE(data.slice_by_state(1).has_value());
- EXPECT_EQ(android::app::PROCESS_STATE_FOREGROUND_SERVICE, data.slice_by_state(1).value());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
-
- data = reports.reports(0).metrics(0).count_metrics().data(1);
- EXPECT_EQ(2, data.slice_by_state_size());
- EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
- EXPECT_TRUE(data.slice_by_state(0).has_value());
- EXPECT_EQ(-1, data.slice_by_state(0).value());
- EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
- EXPECT_TRUE(data.slice_by_state(1).has_value());
- EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, data.slice_by_state(1).value());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
-
- data = reports.reports(0).metrics(0).count_metrics().data(2);
- EXPECT_EQ(2, data.slice_by_state_size());
- EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
- EXPECT_TRUE(data.slice_by_state(0).has_group_id());
- EXPECT_EQ(StringToId("SCREEN_OFF"), data.slice_by_state(0).group_id());
- EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
- EXPECT_TRUE(data.slice_by_state(1).has_value());
- EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, data.slice_by_state(1).value());
- EXPECT_EQ(2, data.bucket_info_size());
- EXPECT_EQ(2, data.bucket_info(0).count());
- EXPECT_EQ(1, data.bucket_info(1).count());
-
- data = reports.reports(0).metrics(0).count_metrics().data(3);
- EXPECT_EQ(2, data.slice_by_state_size());
- EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
- EXPECT_TRUE(data.slice_by_state(0).has_group_id());
- EXPECT_EQ(StringToId("SCREEN_ON"), data.slice_by_state(0).group_id());
- EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
- EXPECT_TRUE(data.slice_by_state(1).has_value());
- EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, data.slice_by_state(1).value());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
-
- data = reports.reports(0).metrics(0).count_metrics().data(4);
- EXPECT_EQ(2, data.slice_by_state_size());
- EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
- EXPECT_TRUE(data.slice_by_state(0).has_group_id());
- EXPECT_EQ(StringToId("SCREEN_ON"), data.slice_by_state(0).group_id());
- EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
- EXPECT_TRUE(data.slice_by_state(1).has_value());
- EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, data.slice_by_state(1).value());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
-
- data = reports.reports(0).metrics(0).count_metrics().data(5);
- EXPECT_EQ(2, data.slice_by_state_size());
- EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
- EXPECT_TRUE(data.slice_by_state(0).has_group_id());
- EXPECT_EQ(StringToId("SCREEN_OFF"), data.slice_by_state(0).group_id());
- EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
- EXPECT_TRUE(data.slice_by_state(1).has_value());
- EXPECT_EQ(android::app::PROCESS_STATE_TOP, data.slice_by_state(1).value());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(2, data.bucket_info(0).count());
-}
+// TODO(b/149590301): Update these tests to use new socket schema.
+///**
+// * Test a count metric that has one slice_by_state with no primary fields.
+// *
+// * Once the CountMetricProducer is initialized, it has one atom id in
+// * mSlicedStateAtoms and no entries in mStateGroupMap.
+//
+// * One StateTracker tracks the state atom, and it has one listener which is the
+// * CountMetricProducer that was initialized.
+// */
+//TEST(CountMetricE2eTest, TestSlicedState) {
+// // Initialize config.
+// StatsdConfig config;
+// config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+//
+// auto syncStartMatcher = CreateSyncStartAtomMatcher();
+// *config.add_atom_matcher() = syncStartMatcher;
+//
+// auto state = CreateScreenState();
+// *config.add_state() = state;
+//
+// // Create count metric that slices by screen state.
+// int64_t metricId = 123456;
+// auto countMetric = config.add_count_metric();
+// countMetric->set_id(metricId);
+// countMetric->set_what(syncStartMatcher.id());
+// countMetric->set_bucket(TimeUnit::FIVE_MINUTES);
+// countMetric->add_slice_by_state(state.id());
+//
+// // Initialize StatsLogProcessor.
+// const uint64_t bucketStartTimeNs = 10000000000; // 0:10
+// const uint64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
+// int uid = 12345;
+// int64_t cfgId = 98765;
+// ConfigKey cfgKey(uid, cfgId);
+// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+//
+// // Check that CountMetricProducer was initialized correctly.
+// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+// sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+// EXPECT_TRUE(metricsManager->isConfigValid());
+// EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+// sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+// EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
+// EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), SCREEN_STATE_ATOM_ID);
+// EXPECT_EQ(metricProducer->mStateGroupMap.size(), 0);
+//
+// // Check that StateTrackers were initialized correctly.
+// EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
+// EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
+//
+// /*
+// bucket #1 bucket #2
+// | 1 2 3 4 5 6 7 8 9 10 (minutes)
+// |-----------------------------|-----------------------------|--
+// x x x x x x (syncStartEvents)
+// | | (ScreenIsOnEvent)
+// | | (ScreenIsOffEvent)
+// | (ScreenUnknownEvent)
+// */
+// // Initialize log events - first bucket.
+// int appUid = 123;
+// std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(appUid, "App1")};
+// std::vector<std::unique_ptr<LogEvent>> events;
+// events.push_back(
+// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+// bucketStartTimeNs + 50 * NS_PER_SEC)); // 1:00
+// events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
+// bucketStartTimeNs + 75 * NS_PER_SEC)); // 1:25
+// events.push_back(
+// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+// bucketStartTimeNs + 150 * NS_PER_SEC)); // 2:40
+// events.push_back(
+// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+// bucketStartTimeNs + 200 * NS_PER_SEC)); // 3:30
+// events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
+// bucketStartTimeNs + 250 * NS_PER_SEC)); // 4:20
+//
+// // Initialize log events - second bucket.
+// events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
+// bucketStartTimeNs + 350 * NS_PER_SEC)); // 6:00
+// events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
+// bucketStartTimeNs + 400 * NS_PER_SEC)); // 6:50
+// events.push_back(
+// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+// bucketStartTimeNs + 450 * NS_PER_SEC)); // 7:40
+// events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
+// bucketStartTimeNs + 475 * NS_PER_SEC)); // 8:05
+// events.push_back(
+// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_UNKNOWN,
+// bucketStartTimeNs + 500 * NS_PER_SEC)); // 8:30
+// events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
+// bucketStartTimeNs + 520 * NS_PER_SEC)); // 8:50
+//
+// // Send log events to StatsLogProcessor.
+// for (auto& event : events) {
+// processor->OnLogEvent(event.get());
+// }
+//
+// // Check dump report.
+// vector<uint8_t> buffer;
+// ConfigMetricsReportList reports;
+// processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs * 2 + 1, false, true, ADB_DUMP,
+// FAST, &buffer);
+// EXPECT_GT(buffer.size(), 0);
+// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+// backfillDimensionPath(&reports);
+// backfillStringInReport(&reports);
+// backfillStartEndTimestamp(&reports);
+//
+// EXPECT_EQ(1, reports.reports_size());
+// EXPECT_EQ(1, reports.reports(0).metrics_size());
+// EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
+// EXPECT_EQ(3, reports.reports(0).metrics(0).count_metrics().data_size());
+//
+// // For each CountMetricData, check StateValue info is correct and buckets
+// // have correct counts.
+// auto data = reports.reports(0).metrics(0).count_metrics().data(0);
+// EXPECT_EQ(1, data.slice_by_state_size());
+// EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+// EXPECT_TRUE(data.slice_by_state(0).has_value());
+// EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON, data.slice_by_state(0).value());
+// EXPECT_EQ(2, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+// EXPECT_EQ(1, data.bucket_info(1).count());
+//
+// data = reports.reports(0).metrics(0).count_metrics().data(1);
+// EXPECT_EQ(1, data.slice_by_state_size());
+// EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+// EXPECT_TRUE(data.slice_by_state(0).has_value());
+// EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_UNKNOWN, data.slice_by_state(0).value());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+//
+// data = reports.reports(0).metrics(0).count_metrics().data(2);
+// EXPECT_EQ(1, data.slice_by_state_size());
+// EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+// EXPECT_TRUE(data.slice_by_state(0).has_value());
+// EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF, data.slice_by_state(0).value());
+// EXPECT_EQ(2, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+// EXPECT_EQ(2, data.bucket_info(1).count());
+//}
+//
+///**
+// * Test a count metric that has one slice_by_state with a mapping and no
+// * primary fields.
+// *
+// * Once the CountMetricProducer is initialized, it has one atom id in
+// * mSlicedStateAtoms and has one entry per state value in mStateGroupMap.
+// *
+// * One StateTracker tracks the state atom, and it has one listener which is the
+// * CountMetricProducer that was initialized.
+// */
+//TEST(CountMetricE2eTest, TestSlicedStateWithMap) {
+// // Initialize config.
+// StatsdConfig config;
+// config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+//
+// auto syncStartMatcher = CreateSyncStartAtomMatcher();
+// *config.add_atom_matcher() = syncStartMatcher;
+//
+// auto state = CreateScreenStateWithOnOffMap();
+// *config.add_state() = state;
+//
+// // Create count metric that slices by screen state with on/off map.
+// int64_t metricId = 123456;
+// auto countMetric = config.add_count_metric();
+// countMetric->set_id(metricId);
+// countMetric->set_what(syncStartMatcher.id());
+// countMetric->set_bucket(TimeUnit::FIVE_MINUTES);
+// countMetric->add_slice_by_state(state.id());
+//
+// // Initialize StatsLogProcessor.
+// const uint64_t bucketStartTimeNs = 10000000000; // 0:10
+// const uint64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
+// int uid = 12345;
+// int64_t cfgId = 98765;
+// ConfigKey cfgKey(uid, cfgId);
+// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+//
+// // Check that StateTrackers were initialized correctly.
+// EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
+// EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
+//
+// // Check that CountMetricProducer was initialized correctly.
+// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+// sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+// EXPECT_TRUE(metricsManager->isConfigValid());
+// EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+// sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+// EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
+// EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), SCREEN_STATE_ATOM_ID);
+// EXPECT_EQ(metricProducer->mStateGroupMap.size(), 1);
+//
+// StateMap map = state.map();
+// for (auto group : map.group()) {
+// for (auto value : group.value()) {
+// EXPECT_EQ(metricProducer->mStateGroupMap[SCREEN_STATE_ATOM_ID][value],
+// group.group_id());
+// }
+// }
+//
+// /*
+// bucket #1 bucket #2
+// | 1 2 3 4 5 6 7 8 9 10 (minutes)
+// |-----------------------------|-----------------------------|--
+// x x x x x x x x x (syncStartEvents)
+// -----------------------------------------------------------SCREEN_OFF events
+// | (ScreenStateUnknownEvent = 0)
+// | | (ScreenStateOffEvent = 1)
+// | (ScreenStateDozeEvent = 3)
+// | (ScreenStateDozeSuspendEvent = 4)
+// -----------------------------------------------------------SCREEN_ON events
+// | | (ScreenStateOnEvent = 2)
+// | (ScreenStateVrEvent = 5)
+// | (ScreenStateOnSuspendEvent = 6)
+// */
+// // Initialize log events - first bucket.
+// int appUid = 123;
+// std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(appUid, "App1")};
+//
+// std::vector<std::unique_ptr<LogEvent>> events;
+// events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
+// bucketStartTimeNs + 20 * NS_PER_SEC)); // 0:30
+// events.push_back(
+// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_UNKNOWN,
+// bucketStartTimeNs + 30 * NS_PER_SEC)); // 0:40
+// events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
+// bucketStartTimeNs + 60 * NS_PER_SEC)); // 1:10
+// events.push_back(
+// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+// bucketStartTimeNs + 90 * NS_PER_SEC)); // 1:40
+// events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
+// bucketStartTimeNs + 120 * NS_PER_SEC)); // 2:10
+// events.push_back(
+// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+// bucketStartTimeNs + 150 * NS_PER_SEC)); // 2:40
+// events.push_back(
+// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_VR,
+// bucketStartTimeNs + 180 * NS_PER_SEC)); // 3:10
+// events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
+// bucketStartTimeNs + 200 * NS_PER_SEC)); // 3:30
+// events.push_back(
+// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_DOZE,
+// bucketStartTimeNs + 210 * NS_PER_SEC)); // 3:40
+// events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
+// bucketStartTimeNs + 250 * NS_PER_SEC)); // 4:20
+// events.push_back(
+// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+// bucketStartTimeNs + 280 * NS_PER_SEC)); // 4:50
+// events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
+// bucketStartTimeNs + 285 * NS_PER_SEC)); // 4:55
+//
+// // Initialize log events - second bucket.
+// events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
+// bucketStartTimeNs + 360 * NS_PER_SEC)); // 6:10
+// events.push_back(
+// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON_SUSPEND,
+// bucketStartTimeNs + 390 * NS_PER_SEC)); // 6:40
+// events.push_back(CreateScreenStateChangedEvent(
+// android::view::DisplayStateEnum::DISPLAY_STATE_DOZE_SUSPEND,
+// bucketStartTimeNs + 430 * NS_PER_SEC)); // 7:20
+// events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
+// bucketStartTimeNs + 440 * NS_PER_SEC)); // 7:30
+// events.push_back(
+// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+// bucketStartTimeNs + 540 * NS_PER_SEC)); // 9:10
+// events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
+// bucketStartTimeNs + 570 * NS_PER_SEC)); // 9:40
+//
+// // Send log events to StatsLogProcessor.
+// for (auto& event : events) {
+// processor->OnLogEvent(event.get());
+// }
+//
+// // Check dump report.
+// vector<uint8_t> buffer;
+// ConfigMetricsReportList reports;
+// processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs * 2 + 1, false, true, ADB_DUMP,
+// FAST, &buffer);
+// EXPECT_GT(buffer.size(), 0);
+// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+// backfillDimensionPath(&reports);
+// backfillStringInReport(&reports);
+// backfillStartEndTimestamp(&reports);
+//
+// EXPECT_EQ(1, reports.reports_size());
+// EXPECT_EQ(1, reports.reports(0).metrics_size());
+// EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
+// EXPECT_EQ(3, reports.reports(0).metrics(0).count_metrics().data_size());
+//
+// // For each CountMetricData, check StateValue info is correct and buckets
+// // have correct counts.
+// auto data = reports.reports(0).metrics(0).count_metrics().data(0);
+// EXPECT_EQ(1, data.slice_by_state_size());
+// EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+// EXPECT_TRUE(data.slice_by_state(0).has_value());
+// EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, data.slice_by_state(0).value());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+//
+// data = reports.reports(0).metrics(0).count_metrics().data(1);
+// EXPECT_EQ(1, data.slice_by_state_size());
+// EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+// EXPECT_TRUE(data.slice_by_state(0).has_group_id());
+// EXPECT_EQ(StringToId("SCREEN_OFF"), data.slice_by_state(0).group_id());
+// EXPECT_EQ(2, data.bucket_info_size());
+// EXPECT_EQ(4, data.bucket_info(0).count());
+// EXPECT_EQ(2, data.bucket_info(1).count());
+//
+// data = reports.reports(0).metrics(0).count_metrics().data(2);
+// EXPECT_EQ(1, data.slice_by_state_size());
+// EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+// EXPECT_TRUE(data.slice_by_state(0).has_group_id());
+// EXPECT_EQ(StringToId("SCREEN_ON"), data.slice_by_state(0).group_id());
+// EXPECT_EQ(2, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+// EXPECT_EQ(1, data.bucket_info(1).count());
+//}
+//
+///**
+// * Test a count metric that has one slice_by_state with a primary field.
+//
+// * Once the CountMetricProducer is initialized, it should have one
+// * MetricStateLink stored. State querying using a non-empty primary key
+// * should also work as intended.
+// */
+//TEST(CountMetricE2eTest, TestSlicedStateWithPrimaryFields) {
+// // Initialize config.
+// StatsdConfig config;
+// config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+//
+// auto appCrashMatcher =
+// CreateSimpleAtomMatcher("APP_CRASH_OCCURRED", android::util::APP_CRASH_OCCURRED);
+// *config.add_atom_matcher() = appCrashMatcher;
+//
+// auto state = CreateUidProcessState();
+// *config.add_state() = state;
+//
+// // Create count metric that slices by uid process state.
+// int64_t metricId = 123456;
+// auto countMetric = config.add_count_metric();
+// countMetric->set_id(metricId);
+// countMetric->set_what(appCrashMatcher.id());
+// countMetric->set_bucket(TimeUnit::FIVE_MINUTES);
+// countMetric->add_slice_by_state(state.id());
+// MetricStateLink* stateLink = countMetric->add_state_link();
+// stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
+// auto fieldsInWhat = stateLink->mutable_fields_in_what();
+// *fieldsInWhat = CreateDimensions(android::util::APP_CRASH_OCCURRED, {1 /* uid */});
+// auto fieldsInState = stateLink->mutable_fields_in_state();
+// *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
+//
+// // Initialize StatsLogProcessor.
+// const uint64_t bucketStartTimeNs = 10000000000; // 0:10
+// const uint64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
+// int uid = 12345;
+// int64_t cfgId = 98765;
+// ConfigKey cfgKey(uid, cfgId);
+// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+//
+// // Check that StateTrackers were initialized correctly.
+// EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
+// EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
+//
+// // Check that CountMetricProducer was initialized correctly.
+// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+// sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+// EXPECT_TRUE(metricsManager->isConfigValid());
+// EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+// sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+// EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
+// EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), UID_PROCESS_STATE_ATOM_ID);
+// EXPECT_EQ(metricProducer->mStateGroupMap.size(), 0);
+// EXPECT_EQ(metricProducer->mMetric2StateLinks.size(), 1);
+//
+// /*
+// NOTE: "1" or "2" represents the uid associated with the state/app crash event
+// bucket #1 bucket #2
+// | 1 2 3 4 5 6 7 8 9 10
+// |-----------------------------|-----------------------------|--
+// 1 1 1 1 1 2 1 1 2 (AppCrashEvents)
+// -----------------------------------------------------------PROCESS STATE events
+// 1 2 (ProcessStateTopEvent = 1002)
+// 1 1 (ProcessStateForegroundServiceEvent = 1003)
+// 2 (ProcessStateImportantBackgroundEvent = 1006)
+// 1 1 1 (ProcessStateImportantForegroundEvent = 1005)
+//
+// Based on the diagram above, an AppCrashEvent querying for process state value would return:
+// - StateTracker::kStateUnknown
+// - Important foreground
+// - Top
+// - Important foreground
+// - Foreground service
+// - Top (both the app crash and state still have matching uid = 2)
+//
+// - Foreground service
+// - Foreground service
+// - Important background
+// */
+// // Initialize log events - first bucket.
+// std::vector<std::unique_ptr<LogEvent>> events;
+// events.push_back(
+// CreateAppCrashOccurredEvent(1 /* uid */, bucketStartTimeNs + 20 * NS_PER_SEC)); // 0:30
+// events.push_back(CreateUidProcessStateChangedEvent(
+// 1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
+// bucketStartTimeNs + 30 * NS_PER_SEC)); // 0:40
+// events.push_back(
+// CreateAppCrashOccurredEvent(1 /* uid */, bucketStartTimeNs + 60 * NS_PER_SEC)); // 1:10
+// events.push_back(CreateUidProcessStateChangedEvent(
+// 1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_TOP,
+// bucketStartTimeNs + 90 * NS_PER_SEC)); // 1:40
+// events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
+// bucketStartTimeNs + 120 * NS_PER_SEC)); // 2:10
+// events.push_back(CreateUidProcessStateChangedEvent(
+// 1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
+// bucketStartTimeNs + 150 * NS_PER_SEC)); // 2:40
+// events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
+// bucketStartTimeNs + 200 * NS_PER_SEC)); // 3:30
+// events.push_back(CreateUidProcessStateChangedEvent(
+// 1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE,
+// bucketStartTimeNs + 210 * NS_PER_SEC)); // 3:40
+// events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
+// bucketStartTimeNs + 250 * NS_PER_SEC)); // 4:20
+// events.push_back(CreateUidProcessStateChangedEvent(
+// 2 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_TOP,
+// bucketStartTimeNs + 280 * NS_PER_SEC)); // 4:50
+// events.push_back(CreateAppCrashOccurredEvent(2 /* uid */,
+// bucketStartTimeNs + 285 * NS_PER_SEC)); // 4:55
+//
+// // Initialize log events - second bucket.
+// events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
+// bucketStartTimeNs + 360 * NS_PER_SEC)); // 6:10
+// events.push_back(CreateUidProcessStateChangedEvent(
+// 1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE,
+// bucketStartTimeNs + 390 * NS_PER_SEC)); // 6:40
+// events.push_back(CreateUidProcessStateChangedEvent(
+// 2 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
+// bucketStartTimeNs + 430 * NS_PER_SEC)); // 7:20
+// events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
+// bucketStartTimeNs + 440 * NS_PER_SEC)); // 7:30
+// events.push_back(CreateUidProcessStateChangedEvent(
+// 1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
+// bucketStartTimeNs + 540 * NS_PER_SEC)); // 9:10
+// events.push_back(CreateAppCrashOccurredEvent(2 /* uid */,
+// bucketStartTimeNs + 570 * NS_PER_SEC)); // 9:40
+//
+// // Send log events to StatsLogProcessor.
+// for (auto& event : events) {
+// processor->OnLogEvent(event.get());
+// }
+//
+// // Check dump report.
+// vector<uint8_t> buffer;
+// ConfigMetricsReportList reports;
+// processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs * 2 + 1, false, true, ADB_DUMP,
+// FAST, &buffer);
+// EXPECT_GT(buffer.size(), 0);
+// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+// backfillDimensionPath(&reports);
+// backfillStringInReport(&reports);
+// backfillStartEndTimestamp(&reports);
+//
+// EXPECT_EQ(1, reports.reports_size());
+// EXPECT_EQ(1, reports.reports(0).metrics_size());
+// EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
+// EXPECT_EQ(5, reports.reports(0).metrics(0).count_metrics().data_size());
+//
+// // For each CountMetricData, check StateValue info is correct and buckets
+// // have correct counts.
+// auto data = reports.reports(0).metrics(0).count_metrics().data(0);
+// EXPECT_EQ(1, data.slice_by_state_size());
+// EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+// EXPECT_TRUE(data.slice_by_state(0).has_value());
+// EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, data.slice_by_state(0).value());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+//
+// data = reports.reports(0).metrics(0).count_metrics().data(1);
+// EXPECT_EQ(1, data.slice_by_state_size());
+// EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+// EXPECT_TRUE(data.slice_by_state(0).has_value());
+// EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, data.slice_by_state(0).value());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+//
+// data = reports.reports(0).metrics(0).count_metrics().data(2);
+// EXPECT_EQ(1, data.slice_by_state_size());
+// EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+// EXPECT_TRUE(data.slice_by_state(0).has_value());
+// EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, data.slice_by_state(0).value());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(2, data.bucket_info(0).count());
+//
+// data = reports.reports(0).metrics(0).count_metrics().data(3);
+// EXPECT_EQ(1, data.slice_by_state_size());
+// EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+// EXPECT_TRUE(data.slice_by_state(0).has_value());
+// EXPECT_EQ(android::app::PROCESS_STATE_TOP, data.slice_by_state(0).value());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(2, data.bucket_info(0).count());
+//
+// data = reports.reports(0).metrics(0).count_metrics().data(4);
+// EXPECT_EQ(1, data.slice_by_state_size());
+// EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+// EXPECT_TRUE(data.slice_by_state(0).has_value());
+// EXPECT_EQ(android::app::PROCESS_STATE_FOREGROUND_SERVICE, data.slice_by_state(0).value());
+// EXPECT_EQ(2, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+// EXPECT_EQ(2, data.bucket_info(1).count());
+//}
+//
+//TEST(CountMetricE2eTest, TestMultipleSlicedStates) {
+// // Initialize config.
+// StatsdConfig config;
+// config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+//
+// auto appCrashMatcher =
+// CreateSimpleAtomMatcher("APP_CRASH_OCCURRED", android::util::APP_CRASH_OCCURRED);
+// *config.add_atom_matcher() = appCrashMatcher;
+//
+// auto state1 = CreateScreenStateWithOnOffMap();
+// *config.add_state() = state1;
+// auto state2 = CreateUidProcessState();
+// *config.add_state() = state2;
+//
+// // Create count metric that slices by screen state with on/off map and
+// // slices by uid process state.
+// int64_t metricId = 123456;
+// auto countMetric = config.add_count_metric();
+// countMetric->set_id(metricId);
+// countMetric->set_what(appCrashMatcher.id());
+// countMetric->set_bucket(TimeUnit::FIVE_MINUTES);
+// countMetric->add_slice_by_state(state1.id());
+// countMetric->add_slice_by_state(state2.id());
+// MetricStateLink* stateLink = countMetric->add_state_link();
+// stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
+// auto fieldsInWhat = stateLink->mutable_fields_in_what();
+// *fieldsInWhat = CreateDimensions(android::util::APP_CRASH_OCCURRED, {1 /* uid */});
+// auto fieldsInState = stateLink->mutable_fields_in_state();
+// *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
+//
+// // Initialize StatsLogProcessor.
+// const uint64_t bucketStartTimeNs = 10000000000; // 0:10
+// const uint64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
+// int uid = 12345;
+// int64_t cfgId = 98765;
+// ConfigKey cfgKey(uid, cfgId);
+// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+//
+// // Check that StateTrackers were properly initialized.
+// EXPECT_EQ(2, StateManager::getInstance().getStateTrackersCount());
+// EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
+// EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
+//
+// // Check that CountMetricProducer was initialized correctly.
+// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+// sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+// EXPECT_TRUE(metricsManager->isConfigValid());
+// EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+// sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+// EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 2);
+// EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), SCREEN_STATE_ATOM_ID);
+// EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(1), UID_PROCESS_STATE_ATOM_ID);
+// EXPECT_EQ(metricProducer->mStateGroupMap.size(), 1);
+// EXPECT_EQ(metricProducer->mMetric2StateLinks.size(), 1);
+//
+// StateMap map = state1.map();
+// for (auto group : map.group()) {
+// for (auto value : group.value()) {
+// EXPECT_EQ(metricProducer->mStateGroupMap[SCREEN_STATE_ATOM_ID][value],
+// group.group_id());
+// }
+// }
+//
+// /*
+// bucket #1 bucket #2
+// | 1 2 3 4 5 6 7 8 9 10 (minutes)
+// |-----------------------------|-----------------------------|--
+// 1 1 1 1 1 2 1 1 2 (AppCrashEvents)
+// -----------------------------------------------------------SCREEN_OFF events
+// | (ScreenStateUnknownEvent = 0)
+// | | (ScreenStateOffEvent = 1)
+// | (ScreenStateDozeEvent = 3)
+// -----------------------------------------------------------SCREEN_ON events
+// | | (ScreenStateOnEvent = 2)
+// | (ScreenStateOnSuspendEvent = 6)
+// -----------------------------------------------------------PROCESS STATE events
+// 1 2 (ProcessStateTopEvent = 1002)
+// 1 (ProcessStateForegroundServiceEvent = 1003)
+// 2 (ProcessStateImportantBackgroundEvent = 1006)
+// 1 1 1 (ProcessStateImportantForegroundEvent = 1005)
+//
+// Based on the diagram above, Screen State / Process State pairs for each
+// AppCrashEvent are:
+// - StateTracker::kStateUnknown / important foreground
+// - off / important foreground
+// - off / Top
+// - on / important foreground
+// - off / important foreground
+// - off / top
+//
+// - off / important foreground
+// - off / foreground service
+// - on / important background
+//
+// */
+// // Initialize log events - first bucket.
+// std::vector<std::unique_ptr<LogEvent>> events;
+// events.push_back(CreateUidProcessStateChangedEvent(
+// 1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
+// bucketStartTimeNs + 5 * NS_PER_SEC)); // 0:15
+// events.push_back(
+// CreateAppCrashOccurredEvent(1 /* uid */, bucketStartTimeNs + 20 * NS_PER_SEC)); // 0:30
+// events.push_back(
+// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_UNKNOWN,
+// bucketStartTimeNs + 30 * NS_PER_SEC)); // 0:40
+// events.push_back(
+// CreateAppCrashOccurredEvent(1 /* uid */, bucketStartTimeNs + 60 * NS_PER_SEC)); // 1:10
+// events.push_back(CreateUidProcessStateChangedEvent(
+// 1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_TOP,
+// bucketStartTimeNs + 90 * NS_PER_SEC)); // 1:40
+// events.push_back(
+// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+// bucketStartTimeNs + 90 * NS_PER_SEC)); // 1:40
+// events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
+// bucketStartTimeNs + 120 * NS_PER_SEC)); // 2:10
+// events.push_back(CreateUidProcessStateChangedEvent(
+// 1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
+// bucketStartTimeNs + 150 * NS_PER_SEC)); // 2:40
+// events.push_back(
+// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+// bucketStartTimeNs + 160 * NS_PER_SEC)); // 2:50
+// events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
+// bucketStartTimeNs + 200 * NS_PER_SEC)); // 3:30
+// events.push_back(
+// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_DOZE,
+// bucketStartTimeNs + 210 * NS_PER_SEC)); // 3:40
+// events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
+// bucketStartTimeNs + 250 * NS_PER_SEC)); // 4:20
+// events.push_back(CreateUidProcessStateChangedEvent(
+// 2 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_TOP,
+// bucketStartTimeNs + 280 * NS_PER_SEC)); // 4:50
+// events.push_back(CreateAppCrashOccurredEvent(2 /* uid */,
+// bucketStartTimeNs + 285 * NS_PER_SEC)); // 4:55
+//
+// // Initialize log events - second bucket.
+// events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
+// bucketStartTimeNs + 360 * NS_PER_SEC)); // 6:10
+// events.push_back(CreateUidProcessStateChangedEvent(
+// 1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE,
+// bucketStartTimeNs + 380 * NS_PER_SEC)); // 6:30
+// events.push_back(
+// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON_SUSPEND,
+// bucketStartTimeNs + 390 * NS_PER_SEC)); // 6:40
+// events.push_back(CreateUidProcessStateChangedEvent(
+// 2 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
+// bucketStartTimeNs + 420 * NS_PER_SEC)); // 7:10
+// events.push_back(
+// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+// bucketStartTimeNs + 440 * NS_PER_SEC)); // 7:30
+// events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
+// bucketStartTimeNs + 450 * NS_PER_SEC)); // 7:40
+// events.push_back(
+// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+// bucketStartTimeNs + 520 * NS_PER_SEC)); // 8:50
+// events.push_back(CreateUidProcessStateChangedEvent(
+// 1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
+// bucketStartTimeNs + 540 * NS_PER_SEC)); // 9:10
+// events.push_back(CreateAppCrashOccurredEvent(2 /* uid */,
+// bucketStartTimeNs + 570 * NS_PER_SEC)); // 9:40
+//
+// // Send log events to StatsLogProcessor.
+// for (auto& event : events) {
+// processor->OnLogEvent(event.get());
+// }
+//
+// // Check dump report.
+// vector<uint8_t> buffer;
+// ConfigMetricsReportList reports;
+// processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs * 2 + 1, false, true, ADB_DUMP,
+// FAST, &buffer);
+// EXPECT_GT(buffer.size(), 0);
+// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+// backfillDimensionPath(&reports);
+// backfillStringInReport(&reports);
+// backfillStartEndTimestamp(&reports);
+//
+// EXPECT_EQ(1, reports.reports_size());
+// EXPECT_EQ(1, reports.reports(0).metrics_size());
+// EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
+// EXPECT_EQ(6, reports.reports(0).metrics(0).count_metrics().data_size());
+//
+// // For each CountMetricData, check StateValue info is correct and buckets
+// // have correct counts.
+// auto data = reports.reports(0).metrics(0).count_metrics().data(0);
+// EXPECT_EQ(2, data.slice_by_state_size());
+// EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+// EXPECT_TRUE(data.slice_by_state(0).has_group_id());
+// EXPECT_EQ(StringToId("SCREEN_OFF"), data.slice_by_state(0).group_id());
+// EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
+// EXPECT_TRUE(data.slice_by_state(1).has_value());
+// EXPECT_EQ(android::app::PROCESS_STATE_FOREGROUND_SERVICE, data.slice_by_state(1).value());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+//
+// data = reports.reports(0).metrics(0).count_metrics().data(1);
+// EXPECT_EQ(2, data.slice_by_state_size());
+// EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+// EXPECT_TRUE(data.slice_by_state(0).has_value());
+// EXPECT_EQ(-1, data.slice_by_state(0).value());
+// EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
+// EXPECT_TRUE(data.slice_by_state(1).has_value());
+// EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, data.slice_by_state(1).value());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+//
+// data = reports.reports(0).metrics(0).count_metrics().data(2);
+// EXPECT_EQ(2, data.slice_by_state_size());
+// EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+// EXPECT_TRUE(data.slice_by_state(0).has_group_id());
+// EXPECT_EQ(StringToId("SCREEN_OFF"), data.slice_by_state(0).group_id());
+// EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
+// EXPECT_TRUE(data.slice_by_state(1).has_value());
+// EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, data.slice_by_state(1).value());
+// EXPECT_EQ(2, data.bucket_info_size());
+// EXPECT_EQ(2, data.bucket_info(0).count());
+// EXPECT_EQ(1, data.bucket_info(1).count());
+//
+// data = reports.reports(0).metrics(0).count_metrics().data(3);
+// EXPECT_EQ(2, data.slice_by_state_size());
+// EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+// EXPECT_TRUE(data.slice_by_state(0).has_group_id());
+// EXPECT_EQ(StringToId("SCREEN_ON"), data.slice_by_state(0).group_id());
+// EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
+// EXPECT_TRUE(data.slice_by_state(1).has_value());
+// EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, data.slice_by_state(1).value());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+//
+// data = reports.reports(0).metrics(0).count_metrics().data(4);
+// EXPECT_EQ(2, data.slice_by_state_size());
+// EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+// EXPECT_TRUE(data.slice_by_state(0).has_group_id());
+// EXPECT_EQ(StringToId("SCREEN_ON"), data.slice_by_state(0).group_id());
+// EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
+// EXPECT_TRUE(data.slice_by_state(1).has_value());
+// EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, data.slice_by_state(1).value());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+//
+// data = reports.reports(0).metrics(0).count_metrics().data(5);
+// EXPECT_EQ(2, data.slice_by_state_size());
+// EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+// EXPECT_TRUE(data.slice_by_state(0).has_group_id());
+// EXPECT_EQ(StringToId("SCREEN_OFF"), data.slice_by_state(0).group_id());
+// EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
+// EXPECT_TRUE(data.slice_by_state(1).has_value());
+// EXPECT_EQ(android::app::PROCESS_STATE_TOP, data.slice_by_state(1).value());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(2, data.bucket_info(0).count());
+//}
} // namespace statsd
} // namespace os
diff --git a/cmds/statsd/tests/e2e/DurationMetric_e2e_test.cpp b/cmds/statsd/tests/e2e/DurationMetric_e2e_test.cpp
index 9093155..8eb5f69 100644
--- a/cmds/statsd/tests/e2e/DurationMetric_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/DurationMetric_e2e_test.cpp
@@ -26,687 +26,688 @@
#ifdef __ANDROID__
-TEST(DurationMetricE2eTest, TestOneBucket) {
- StatsdConfig config;
- config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
-
- auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
- auto screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
- *config.add_atom_matcher() = screenOnMatcher;
- *config.add_atom_matcher() = screenOffMatcher;
-
- auto durationPredicate = CreateScreenIsOnPredicate();
- *config.add_predicate() = durationPredicate;
-
- int64_t metricId = 123456;
- auto durationMetric = config.add_duration_metric();
- durationMetric->set_id(metricId);
- durationMetric->set_what(durationPredicate.id());
- durationMetric->set_bucket(FIVE_MINUTES);
- durationMetric->set_aggregation_type(DurationMetric_AggregationType_SUM);
-
-
- const int64_t baseTimeNs = 0; // 0:00
- const int64_t configAddedTimeNs = baseTimeNs + 1 * NS_PER_SEC; // 0:01
- const int64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000LL * 1000LL;
-
- int uid = 12345;
- int64_t cfgId = 98765;
- ConfigKey cfgKey(uid, cfgId);
-
- auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey);
-
- EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
- sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
- EXPECT_TRUE(metricsManager->isConfigValid());
- EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
- sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
- EXPECT_TRUE(metricsManager->isActive());
- EXPECT_TRUE(metricProducer->mIsActive);
-
- std::unique_ptr<LogEvent> event;
-
- // Screen is off at start of bucket.
- event = CreateScreenStateChangedEvent(
- android::view::DISPLAY_STATE_OFF, configAddedTimeNs); // 0:01
- processor->OnLogEvent(event.get());
-
- // Turn screen on.
- const int64_t durationStartNs = configAddedTimeNs + 10 * NS_PER_SEC; // 0:11
- event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, durationStartNs);
- processor->OnLogEvent(event.get());
-
- // Turn off screen 30 seconds after turning on.
- const int64_t durationEndNs = durationStartNs + 30 * NS_PER_SEC; // 0:41
- event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, durationEndNs);
- processor->OnLogEvent(event.get());
-
- event = CreateScreenBrightnessChangedEvent(64, durationEndNs + 1 * NS_PER_SEC); // 0:42
- processor->OnLogEvent(event.get());
-
- ConfigMetricsReportList reports;
- vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, configAddedTimeNs + bucketSizeNs + 1 * NS_PER_SEC, false, true,
- ADB_DUMP, FAST, &buffer); // 5:01
- EXPECT_TRUE(buffer.size() > 0);
- EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
- backfillDimensionPath(&reports);
- backfillStartEndTimestamp(&reports);
- EXPECT_EQ(1, reports.reports_size());
- EXPECT_EQ(1, reports.reports(0).metrics_size());
- EXPECT_EQ(metricId, reports.reports(0).metrics(0).metric_id());
- EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
-
- const StatsLogReport::DurationMetricDataWrapper& durationMetrics =
- reports.reports(0).metrics(0).duration_metrics();
- EXPECT_EQ(1, durationMetrics.data_size());
-
- auto data = durationMetrics.data(0);
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(durationEndNs - durationStartNs, data.bucket_info(0).duration_nanos());
- EXPECT_EQ(configAddedTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(baseTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
-}
-
-TEST(DurationMetricE2eTest, TestTwoBuckets) {
- StatsdConfig config;
- config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
-
- auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
- auto screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
- *config.add_atom_matcher() = screenOnMatcher;
- *config.add_atom_matcher() = screenOffMatcher;
-
- auto durationPredicate = CreateScreenIsOnPredicate();
- *config.add_predicate() = durationPredicate;
-
- int64_t metricId = 123456;
- auto durationMetric = config.add_duration_metric();
- durationMetric->set_id(metricId);
- durationMetric->set_what(durationPredicate.id());
- durationMetric->set_bucket(FIVE_MINUTES);
- durationMetric->set_aggregation_type(DurationMetric_AggregationType_SUM);
-
-
- const int64_t baseTimeNs = 0; // 0:00
- const int64_t configAddedTimeNs = baseTimeNs + 1 * NS_PER_SEC; // 0:01
- const int64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000LL * 1000LL;
-
- int uid = 12345;
- int64_t cfgId = 98765;
- ConfigKey cfgKey(uid, cfgId);
-
- auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey);
-
- EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
- sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
- EXPECT_TRUE(metricsManager->isConfigValid());
- EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
- sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
- EXPECT_TRUE(metricsManager->isActive());
- EXPECT_TRUE(metricProducer->mIsActive);
-
- std::unique_ptr<LogEvent> event;
-
- // Screen is off at start of bucket.
- event = CreateScreenStateChangedEvent(
- android::view::DISPLAY_STATE_OFF, configAddedTimeNs); // 0:01
- processor->OnLogEvent(event.get());
-
- // Turn screen on.
- const int64_t durationStartNs = configAddedTimeNs + 10 * NS_PER_SEC; // 0:11
- event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, durationStartNs);
- processor->OnLogEvent(event.get());
-
- // Turn off screen 30 seconds after turning on.
- const int64_t durationEndNs = durationStartNs + 30 * NS_PER_SEC; // 0:41
- event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, durationEndNs);
- processor->OnLogEvent(event.get());
-
- event = CreateScreenBrightnessChangedEvent(64, durationEndNs + 1 * NS_PER_SEC); // 0:42
- processor->OnLogEvent(event.get());
-
- ConfigMetricsReportList reports;
- vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, configAddedTimeNs + 2 * bucketSizeNs + 1 * NS_PER_SEC, false, true,
- ADB_DUMP, FAST, &buffer); // 10:01
- EXPECT_TRUE(buffer.size() > 0);
- EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
- backfillDimensionPath(&reports);
- backfillStartEndTimestamp(&reports);
- EXPECT_EQ(1, reports.reports_size());
- EXPECT_EQ(1, reports.reports(0).metrics_size());
- EXPECT_EQ(metricId, reports.reports(0).metrics(0).metric_id());
- EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
-
- const StatsLogReport::DurationMetricDataWrapper& durationMetrics =
- reports.reports(0).metrics(0).duration_metrics();
- EXPECT_EQ(1, durationMetrics.data_size());
-
- auto data = durationMetrics.data(0);
- EXPECT_EQ(1, data.bucket_info_size());
-
- auto bucketInfo = data.bucket_info(0);
- EXPECT_EQ(0, bucketInfo.bucket_num());
- EXPECT_EQ(durationEndNs - durationStartNs, bucketInfo.duration_nanos());
- EXPECT_EQ(configAddedTimeNs, bucketInfo.start_bucket_elapsed_nanos());
- EXPECT_EQ(baseTimeNs + bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
-}
-
-TEST(DurationMetricE2eTest, TestWithActivation) {
- StatsdConfig config;
- config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
-
- auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
- auto screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
- auto crashMatcher = CreateProcessCrashAtomMatcher();
- *config.add_atom_matcher() = screenOnMatcher;
- *config.add_atom_matcher() = screenOffMatcher;
- *config.add_atom_matcher() = crashMatcher;
-
- auto durationPredicate = CreateScreenIsOnPredicate();
- *config.add_predicate() = durationPredicate;
-
- int64_t metricId = 123456;
- auto durationMetric = config.add_duration_metric();
- durationMetric->set_id(metricId);
- durationMetric->set_what(durationPredicate.id());
- durationMetric->set_bucket(FIVE_MINUTES);
- durationMetric->set_aggregation_type(DurationMetric_AggregationType_SUM);
-
- auto metric_activation1 = config.add_metric_activation();
- metric_activation1->set_metric_id(metricId);
- auto event_activation1 = metric_activation1->add_event_activation();
- event_activation1->set_atom_matcher_id(crashMatcher.id());
- event_activation1->set_ttl_seconds(30); // 30 secs.
-
- const int64_t bucketStartTimeNs = 10000000000;
- const int64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000LL * 1000LL;
-
- int uid = 12345;
- int64_t cfgId = 98765;
- ConfigKey cfgKey(uid, cfgId);
-
- sp<UidMap> m = new UidMap();
- sp<StatsPullerManager> pullerManager = new StatsPullerManager();
- sp<AlarmMonitor> anomalyAlarmMonitor;
- sp<AlarmMonitor> subscriberAlarmMonitor;
- vector<int64_t> activeConfigsBroadcast;
-
- int broadcastCount = 0;
- StatsLogProcessor processor(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor,
- bucketStartTimeNs, [](const ConfigKey& key) { return true; },
- [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid,
- const vector<int64_t>& activeConfigs) {
- broadcastCount++;
- EXPECT_EQ(broadcastUid, uid);
- activeConfigsBroadcast.clear();
- activeConfigsBroadcast.insert(activeConfigsBroadcast.end(),
- activeConfigs.begin(), activeConfigs.end());
- return true;
- });
-
- processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config); // 0:00
-
- EXPECT_EQ(processor.mMetricsManagers.size(), 1u);
- sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
- EXPECT_TRUE(metricsManager->isConfigValid());
- EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
- sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
- auto& eventActivationMap = metricProducer->mEventActivationMap;
-
- EXPECT_FALSE(metricsManager->isActive());
- EXPECT_FALSE(metricProducer->mIsActive);
- EXPECT_EQ(eventActivationMap.size(), 1u);
- EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
-
- std::unique_ptr<LogEvent> event;
-
- // Turn screen off.
- event = CreateScreenStateChangedEvent(
- android::view::DISPLAY_STATE_OFF, bucketStartTimeNs + 2 * NS_PER_SEC); // 0:02
- processor.OnLogEvent(event.get(), bucketStartTimeNs + 2 * NS_PER_SEC);
-
- // Turn screen on.
- const int64_t durationStartNs = bucketStartTimeNs + 5 * NS_PER_SEC; // 0:05
- event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, durationStartNs);
- processor.OnLogEvent(event.get(), durationStartNs);
-
- // Activate metric.
- const int64_t activationStartNs = bucketStartTimeNs + 5 * NS_PER_SEC; // 0:10
- const int64_t activationEndNs =
- activationStartNs + event_activation1->ttl_seconds() * NS_PER_SEC; // 0:40
- event = CreateAppCrashEvent(111, activationStartNs);
- processor.OnLogEvent(event.get(), activationStartNs);
- EXPECT_TRUE(metricsManager->isActive());
- EXPECT_TRUE(metricProducer->mIsActive);
- EXPECT_EQ(broadcastCount, 1);
- EXPECT_EQ(activeConfigsBroadcast.size(), 1);
- EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, activationStartNs);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
-
- // Expire activation.
- const int64_t expirationNs = activationEndNs + 7 * NS_PER_SEC;
- event = CreateScreenBrightnessChangedEvent(64, expirationNs); // 0:47
- processor.OnLogEvent(event.get(), expirationNs);
- EXPECT_FALSE(metricsManager->isActive());
- EXPECT_FALSE(metricProducer->mIsActive);
- EXPECT_EQ(broadcastCount, 2);
- EXPECT_EQ(activeConfigsBroadcast.size(), 0);
- EXPECT_EQ(eventActivationMap.size(), 1u);
- EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, activationStartNs);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
-
- // Turn off screen 10 seconds after activation expiration.
- const int64_t durationEndNs = activationEndNs + 10 * NS_PER_SEC; // 0:50
- event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, durationEndNs);
- processor.OnLogEvent(event.get(),durationEndNs);
-
- // Turn screen on.
- const int64_t duration2StartNs = durationEndNs + 5 * NS_PER_SEC; // 0:55
- event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, duration2StartNs);
- processor.OnLogEvent(event.get(), duration2StartNs);
-
- // Turn off screen.
- const int64_t duration2EndNs = duration2StartNs + 10 * NS_PER_SEC; // 1:05
- event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, duration2EndNs);
- processor.OnLogEvent(event.get(), duration2EndNs);
-
- // Activate metric.
- const int64_t activation2StartNs = duration2EndNs + 5 * NS_PER_SEC; // 1:10
- const int64_t activation2EndNs =
- activation2StartNs + event_activation1->ttl_seconds() * NS_PER_SEC; // 1:40
- event = CreateAppCrashEvent(211, activation2StartNs);
- processor.OnLogEvent(event.get(), activation2StartNs);
- EXPECT_TRUE(metricsManager->isActive());
- EXPECT_TRUE(metricProducer->mIsActive);
- EXPECT_EQ(broadcastCount, 3);
- EXPECT_EQ(activeConfigsBroadcast.size(), 1);
- EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, activation2StartNs);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
-
- ConfigMetricsReportList reports;
- vector<uint8_t> buffer;
- processor.onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1 * NS_PER_SEC, false, true,
- ADB_DUMP, FAST, &buffer); // 5:01
- EXPECT_TRUE(buffer.size() > 0);
- EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
- backfillDimensionPath(&reports);
- backfillStartEndTimestamp(&reports);
- EXPECT_EQ(1, reports.reports_size());
- EXPECT_EQ(1, reports.reports(0).metrics_size());
- EXPECT_EQ(metricId, reports.reports(0).metrics(0).metric_id());
- EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
-
- const StatsLogReport::DurationMetricDataWrapper& durationMetrics =
- reports.reports(0).metrics(0).duration_metrics();
- EXPECT_EQ(1, durationMetrics.data_size());
-
- auto data = durationMetrics.data(0);
- EXPECT_EQ(1, data.bucket_info_size());
-
- auto bucketInfo = data.bucket_info(0);
- EXPECT_EQ(0, bucketInfo.bucket_num());
- EXPECT_EQ(bucketStartTimeNs, bucketInfo.start_bucket_elapsed_nanos());
- EXPECT_EQ(expirationNs, bucketInfo.end_bucket_elapsed_nanos());
- EXPECT_EQ(expirationNs - durationStartNs, bucketInfo.duration_nanos());
-}
-
-TEST(DurationMetricE2eTest, TestWithCondition) {
- StatsdConfig config;
- config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
- *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
- *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();
- *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher();
- *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher();
-
- auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
- *config.add_predicate() = holdingWakelockPredicate;
-
- auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
- *config.add_predicate() = isInBackgroundPredicate;
-
- auto durationMetric = config.add_duration_metric();
- durationMetric->set_id(StringToId("WakelockDuration"));
- durationMetric->set_what(holdingWakelockPredicate.id());
- durationMetric->set_condition(isInBackgroundPredicate.id());
- durationMetric->set_aggregation_type(DurationMetric::SUM);
- durationMetric->set_bucket(FIVE_MINUTES);
-
- ConfigKey cfgKey;
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
- auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
- EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
- sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
- EXPECT_TRUE(metricsManager->isConfigValid());
- EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
- sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
- auto& eventActivationMap = metricProducer->mEventActivationMap;
- EXPECT_TRUE(metricsManager->isActive());
- EXPECT_TRUE(metricProducer->mIsActive);
- EXPECT_TRUE(eventActivationMap.empty());
-
- int appUid = 123;
- std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(appUid, "App1")};
-
- auto event = CreateAcquireWakelockEvent(
- attributions1, "wl1", bucketStartTimeNs + 10 * NS_PER_SEC); // 0:10
- processor->OnLogEvent(event.get());
-
- event = CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 22 * NS_PER_SEC); // 0:22
- processor->OnLogEvent(event.get());
-
- event = CreateMoveToForegroundEvent(
- appUid, bucketStartTimeNs + (3 * 60 + 15) * NS_PER_SEC); // 3:15
- processor->OnLogEvent(event.get());
-
- event = CreateReleaseWakelockEvent(
- attributions1, "wl1", bucketStartTimeNs + 4 * 60 * NS_PER_SEC); // 4:00
- processor->OnLogEvent(event.get());
-
- vector<uint8_t> buffer;
- ConfigMetricsReportList reports;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true,
- ADB_DUMP, FAST, &buffer);
- EXPECT_GT(buffer.size(), 0);
- EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
- backfillDimensionPath(&reports);
- backfillStringInReport(&reports);
- backfillStartEndTimestamp(&reports);
-
- EXPECT_EQ(1, reports.reports_size());
- EXPECT_EQ(1, reports.reports(0).metrics_size());
- EXPECT_EQ(1, reports.reports(0).metrics(0).duration_metrics().data_size());
-
- auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
-
- // Validate bucket info.
- EXPECT_EQ(1, data.bucket_info_size());
-
- auto bucketInfo = data.bucket_info(0);
- EXPECT_EQ(bucketStartTimeNs, bucketInfo.start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
- EXPECT_EQ((2 * 60 + 53) * NS_PER_SEC, bucketInfo.duration_nanos());
-}
-
-TEST(DurationMetricE2eTest, TestWithSlicedCondition) {
- StatsdConfig config;
- config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
- auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
- *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
- *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();
- *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher();
- *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher();
-
- auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
- // The predicate is dimensioning by first attribution node by uid.
- FieldMatcher dimensions = CreateAttributionUidDimensions(
- android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
- *holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions() = dimensions;
- *config.add_predicate() = holdingWakelockPredicate;
-
- auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
- *isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() =
- CreateDimensions(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {Position::FIRST});
- *config.add_predicate() = isInBackgroundPredicate;
-
- auto durationMetric = config.add_duration_metric();
- durationMetric->set_id(StringToId("WakelockDuration"));
- durationMetric->set_what(holdingWakelockPredicate.id());
- durationMetric->set_condition(isInBackgroundPredicate.id());
- durationMetric->set_aggregation_type(DurationMetric::SUM);
- // The metric is dimensioning by first attribution node and only by uid.
- *durationMetric->mutable_dimensions_in_what() =
- CreateAttributionUidDimensions(
- android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
- durationMetric->set_bucket(FIVE_MINUTES);
-
- // Links between wakelock state atom and condition of app is in background.
- auto links = durationMetric->add_links();
- links->set_condition(isInBackgroundPredicate.id());
- auto dimensionWhat = links->mutable_fields_in_what();
- dimensionWhat->set_field(android::util::WAKELOCK_STATE_CHANGED);
- dimensionWhat->add_child()->set_field(1); // uid field.
- *links->mutable_fields_in_condition() = CreateAttributionUidDimensions(
- android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, { Position::FIRST });
-
- ConfigKey cfgKey;
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
- auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
- EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
- sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
- EXPECT_TRUE(metricsManager->isConfigValid());
- EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
- sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
- auto& eventActivationMap = metricProducer->mEventActivationMap;
- EXPECT_TRUE(metricsManager->isActive());
- EXPECT_TRUE(metricProducer->mIsActive);
- EXPECT_TRUE(eventActivationMap.empty());
-
- int appUid = 123;
- std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(appUid, "App1")};
-
- auto event = CreateAcquireWakelockEvent(
- attributions1, "wl1", bucketStartTimeNs + 10 * NS_PER_SEC); // 0:10
- processor->OnLogEvent(event.get());
-
- event = CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 22 * NS_PER_SEC); // 0:22
- processor->OnLogEvent(event.get());
-
- event = CreateReleaseWakelockEvent(
- attributions1, "wl1", bucketStartTimeNs + 60 * NS_PER_SEC); // 1:00
- processor->OnLogEvent(event.get());
-
-
- event = CreateMoveToForegroundEvent(
- appUid, bucketStartTimeNs + (3 * 60 + 15) * NS_PER_SEC); // 3:15
- processor->OnLogEvent(event.get());
-
- vector<uint8_t> buffer;
- ConfigMetricsReportList reports;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true,
- ADB_DUMP, FAST, &buffer);
- EXPECT_GT(buffer.size(), 0);
- EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
- backfillDimensionPath(&reports);
- backfillStringInReport(&reports);
- backfillStartEndTimestamp(&reports);
-
- EXPECT_EQ(1, reports.reports_size());
- EXPECT_EQ(1, reports.reports(0).metrics_size());
- EXPECT_EQ(1, reports.reports(0).metrics(0).duration_metrics().data_size());
-
- auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
- // Validate dimension value.
- ValidateAttributionUidDimension(data.dimensions_in_what(),
- android::util::WAKELOCK_STATE_CHANGED, appUid);
- // Validate bucket info.
- EXPECT_EQ(1, data.bucket_info_size());
-
- auto bucketInfo = data.bucket_info(0);
- EXPECT_EQ(bucketStartTimeNs, bucketInfo.start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
- EXPECT_EQ(38 * NS_PER_SEC, bucketInfo.duration_nanos());
-}
-
-TEST(DurationMetricE2eTest, TestWithActivationAndSlicedCondition) {
- StatsdConfig config;
- config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
- auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
- *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
- *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();
- *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher();
- *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher();
- *config.add_atom_matcher() = screenOnMatcher;
-
- auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
- // The predicate is dimensioning by first attribution node by uid.
- FieldMatcher dimensions = CreateAttributionUidDimensions(
- android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
- *holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions() = dimensions;
- *config.add_predicate() = holdingWakelockPredicate;
-
- auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
- *isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() =
- CreateDimensions(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {Position::FIRST});
- *config.add_predicate() = isInBackgroundPredicate;
-
- auto durationMetric = config.add_duration_metric();
- durationMetric->set_id(StringToId("WakelockDuration"));
- durationMetric->set_what(holdingWakelockPredicate.id());
- durationMetric->set_condition(isInBackgroundPredicate.id());
- durationMetric->set_aggregation_type(DurationMetric::SUM);
- // The metric is dimensioning by first attribution node and only by uid.
- *durationMetric->mutable_dimensions_in_what() =
- CreateAttributionUidDimensions(
- android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
- durationMetric->set_bucket(FIVE_MINUTES);
-
- // Links between wakelock state atom and condition of app is in background.
- auto links = durationMetric->add_links();
- links->set_condition(isInBackgroundPredicate.id());
- auto dimensionWhat = links->mutable_fields_in_what();
- dimensionWhat->set_field(android::util::WAKELOCK_STATE_CHANGED);
- dimensionWhat->add_child()->set_field(1); // uid field.
- *links->mutable_fields_in_condition() = CreateAttributionUidDimensions(
- android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, { Position::FIRST });
-
- auto metric_activation1 = config.add_metric_activation();
- metric_activation1->set_metric_id(durationMetric->id());
- auto event_activation1 = metric_activation1->add_event_activation();
- event_activation1->set_atom_matcher_id(screenOnMatcher.id());
- event_activation1->set_ttl_seconds(60 * 2); // 2 minutes.
-
- ConfigKey cfgKey;
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
- auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
- EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
- sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
- EXPECT_TRUE(metricsManager->isConfigValid());
- EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
- sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
- auto& eventActivationMap = metricProducer->mEventActivationMap;
- EXPECT_FALSE(metricsManager->isActive());
- EXPECT_FALSE(metricProducer->mIsActive);
- EXPECT_EQ(eventActivationMap.size(), 1u);
- EXPECT_TRUE(eventActivationMap.find(4) != eventActivationMap.end());
- EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[4]->start_ns, 0);
- EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
-
- int appUid = 123;
- std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(appUid, "App1")};
-
- auto event = CreateAcquireWakelockEvent(
- attributions1, "wl1", bucketStartTimeNs + 10 * NS_PER_SEC); // 0:10
- processor->OnLogEvent(event.get());
- EXPECT_FALSE(metricsManager->isActive());
- EXPECT_FALSE(metricProducer->mIsActive);
- EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[4]->start_ns, 0);
- EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
-
- event = CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 22 * NS_PER_SEC); // 0:22
- processor->OnLogEvent(event.get());
- EXPECT_FALSE(metricsManager->isActive());
- EXPECT_FALSE(metricProducer->mIsActive);
- EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[4]->start_ns, 0);
- EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
-
- const int64_t durationStartNs = bucketStartTimeNs + 30 * NS_PER_SEC; // 0:30
- event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, durationStartNs);
- processor->OnLogEvent(event.get());
- EXPECT_TRUE(metricsManager->isActive());
- EXPECT_TRUE(metricProducer->mIsActive);
- EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[4]->start_ns, durationStartNs);
- EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
-
- const int64_t durationEndNs =
- durationStartNs + (event_activation1->ttl_seconds() + 30) * NS_PER_SEC; // 3:00
- event = CreateAppCrashEvent(333, durationEndNs);
- processor->OnLogEvent(event.get());
- EXPECT_FALSE(metricsManager->isActive());
- EXPECT_FALSE(metricProducer->mIsActive);
- EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[4]->start_ns, durationStartNs);
- EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
-
- event = CreateMoveToForegroundEvent(
- appUid, bucketStartTimeNs + (3 * 60 + 15) * NS_PER_SEC); // 3:15
- processor->OnLogEvent(event.get());
-
- event = CreateReleaseWakelockEvent(
- attributions1, "wl1", bucketStartTimeNs + (4 * 60 + 17) * NS_PER_SEC); // 4:17
- processor->OnLogEvent(event.get());
-
- event = CreateMoveToBackgroundEvent(
- appUid, bucketStartTimeNs + (4 * 60 + 20) * NS_PER_SEC); // 4:20
- processor->OnLogEvent(event.get());
-
- event = CreateAcquireWakelockEvent(
- attributions1, "wl1", bucketStartTimeNs + (4 * 60 + 25) * NS_PER_SEC); // 4:25
- processor->OnLogEvent(event.get());
-
- const int64_t duration2StartNs = bucketStartTimeNs + (4 * 60 + 30) * NS_PER_SEC; // 4:30
- event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, duration2StartNs);
- processor->OnLogEvent(event.get());
- EXPECT_TRUE(metricsManager->isActive());
- EXPECT_TRUE(metricProducer->mIsActive);
- EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[4]->start_ns, duration2StartNs);
- EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
-
- vector<uint8_t> buffer;
- ConfigMetricsReportList reports;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true,
- ADB_DUMP, FAST, &buffer);
- EXPECT_GT(buffer.size(), 0);
- EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
- backfillDimensionPath(&reports);
- backfillStringInReport(&reports);
- backfillStartEndTimestamp(&reports);
-
- EXPECT_EQ(1, reports.reports_size());
- EXPECT_EQ(1, reports.reports(0).metrics_size());
- EXPECT_EQ(1, reports.reports(0).metrics(0).duration_metrics().data_size());
-
- auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
- // Validate dimension value.
- ValidateAttributionUidDimension(data.dimensions_in_what(),
- android::util::WAKELOCK_STATE_CHANGED, appUid);
- // Validate bucket info.
- EXPECT_EQ(2, data.bucket_info_size());
-
- auto bucketInfo = data.bucket_info(0);
- EXPECT_EQ(bucketStartTimeNs, bucketInfo.start_bucket_elapsed_nanos());
- EXPECT_EQ(durationEndNs, bucketInfo.end_bucket_elapsed_nanos());
- EXPECT_EQ(durationEndNs - durationStartNs, bucketInfo.duration_nanos());
-
- bucketInfo = data.bucket_info(1);
- EXPECT_EQ(durationEndNs, bucketInfo.start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - duration2StartNs, bucketInfo.duration_nanos());
-}
+// TODO(b/149590301): Update these tests to use new socket schema.
+//TEST(DurationMetricE2eTest, TestOneBucket) {
+// StatsdConfig config;
+// config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+//
+// auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
+// auto screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
+// *config.add_atom_matcher() = screenOnMatcher;
+// *config.add_atom_matcher() = screenOffMatcher;
+//
+// auto durationPredicate = CreateScreenIsOnPredicate();
+// *config.add_predicate() = durationPredicate;
+//
+// int64_t metricId = 123456;
+// auto durationMetric = config.add_duration_metric();
+// durationMetric->set_id(metricId);
+// durationMetric->set_what(durationPredicate.id());
+// durationMetric->set_bucket(FIVE_MINUTES);
+// durationMetric->set_aggregation_type(DurationMetric_AggregationType_SUM);
+//
+//
+// const int64_t baseTimeNs = 0; // 0:00
+// const int64_t configAddedTimeNs = baseTimeNs + 1 * NS_PER_SEC; // 0:01
+// const int64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000LL * 1000LL;
+//
+// int uid = 12345;
+// int64_t cfgId = 98765;
+// ConfigKey cfgKey(uid, cfgId);
+//
+// auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey);
+//
+// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+// sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+// EXPECT_TRUE(metricsManager->isConfigValid());
+// EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+// sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+// EXPECT_TRUE(metricsManager->isActive());
+// EXPECT_TRUE(metricProducer->mIsActive);
+//
+// std::unique_ptr<LogEvent> event;
+//
+// // Screen is off at start of bucket.
+// event = CreateScreenStateChangedEvent(
+// android::view::DISPLAY_STATE_OFF, configAddedTimeNs); // 0:01
+// processor->OnLogEvent(event.get());
+//
+// // Turn screen on.
+// const int64_t durationStartNs = configAddedTimeNs + 10 * NS_PER_SEC; // 0:11
+// event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, durationStartNs);
+// processor->OnLogEvent(event.get());
+//
+// // Turn off screen 30 seconds after turning on.
+// const int64_t durationEndNs = durationStartNs + 30 * NS_PER_SEC; // 0:41
+// event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, durationEndNs);
+// processor->OnLogEvent(event.get());
+//
+// event = CreateScreenBrightnessChangedEvent(64, durationEndNs + 1 * NS_PER_SEC); // 0:42
+// processor->OnLogEvent(event.get());
+//
+// ConfigMetricsReportList reports;
+// vector<uint8_t> buffer;
+// processor->onDumpReport(cfgKey, configAddedTimeNs + bucketSizeNs + 1 * NS_PER_SEC, false, true,
+// ADB_DUMP, FAST, &buffer); // 5:01
+// EXPECT_TRUE(buffer.size() > 0);
+// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+// backfillDimensionPath(&reports);
+// backfillStartEndTimestamp(&reports);
+// EXPECT_EQ(1, reports.reports_size());
+// EXPECT_EQ(1, reports.reports(0).metrics_size());
+// EXPECT_EQ(metricId, reports.reports(0).metrics(0).metric_id());
+// EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
+//
+// const StatsLogReport::DurationMetricDataWrapper& durationMetrics =
+// reports.reports(0).metrics(0).duration_metrics();
+// EXPECT_EQ(1, durationMetrics.data_size());
+//
+// auto data = durationMetrics.data(0);
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(durationEndNs - durationStartNs, data.bucket_info(0).duration_nanos());
+// EXPECT_EQ(configAddedTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(baseTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+//}
+//
+//TEST(DurationMetricE2eTest, TestTwoBuckets) {
+// StatsdConfig config;
+// config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+//
+// auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
+// auto screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
+// *config.add_atom_matcher() = screenOnMatcher;
+// *config.add_atom_matcher() = screenOffMatcher;
+//
+// auto durationPredicate = CreateScreenIsOnPredicate();
+// *config.add_predicate() = durationPredicate;
+//
+// int64_t metricId = 123456;
+// auto durationMetric = config.add_duration_metric();
+// durationMetric->set_id(metricId);
+// durationMetric->set_what(durationPredicate.id());
+// durationMetric->set_bucket(FIVE_MINUTES);
+// durationMetric->set_aggregation_type(DurationMetric_AggregationType_SUM);
+//
+//
+// const int64_t baseTimeNs = 0; // 0:00
+// const int64_t configAddedTimeNs = baseTimeNs + 1 * NS_PER_SEC; // 0:01
+// const int64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000LL * 1000LL;
+//
+// int uid = 12345;
+// int64_t cfgId = 98765;
+// ConfigKey cfgKey(uid, cfgId);
+//
+// auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey);
+//
+// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+// sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+// EXPECT_TRUE(metricsManager->isConfigValid());
+// EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+// sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+// EXPECT_TRUE(metricsManager->isActive());
+// EXPECT_TRUE(metricProducer->mIsActive);
+//
+// std::unique_ptr<LogEvent> event;
+//
+// // Screen is off at start of bucket.
+// event = CreateScreenStateChangedEvent(
+// android::view::DISPLAY_STATE_OFF, configAddedTimeNs); // 0:01
+// processor->OnLogEvent(event.get());
+//
+// // Turn screen on.
+// const int64_t durationStartNs = configAddedTimeNs + 10 * NS_PER_SEC; // 0:11
+// event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, durationStartNs);
+// processor->OnLogEvent(event.get());
+//
+// // Turn off screen 30 seconds after turning on.
+// const int64_t durationEndNs = durationStartNs + 30 * NS_PER_SEC; // 0:41
+// event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, durationEndNs);
+// processor->OnLogEvent(event.get());
+//
+// event = CreateScreenBrightnessChangedEvent(64, durationEndNs + 1 * NS_PER_SEC); // 0:42
+// processor->OnLogEvent(event.get());
+//
+// ConfigMetricsReportList reports;
+// vector<uint8_t> buffer;
+// processor->onDumpReport(cfgKey, configAddedTimeNs + 2 * bucketSizeNs + 1 * NS_PER_SEC, false, true,
+// ADB_DUMP, FAST, &buffer); // 10:01
+// EXPECT_TRUE(buffer.size() > 0);
+// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+// backfillDimensionPath(&reports);
+// backfillStartEndTimestamp(&reports);
+// EXPECT_EQ(1, reports.reports_size());
+// EXPECT_EQ(1, reports.reports(0).metrics_size());
+// EXPECT_EQ(metricId, reports.reports(0).metrics(0).metric_id());
+// EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
+//
+// const StatsLogReport::DurationMetricDataWrapper& durationMetrics =
+// reports.reports(0).metrics(0).duration_metrics();
+// EXPECT_EQ(1, durationMetrics.data_size());
+//
+// auto data = durationMetrics.data(0);
+// EXPECT_EQ(1, data.bucket_info_size());
+//
+// auto bucketInfo = data.bucket_info(0);
+// EXPECT_EQ(0, bucketInfo.bucket_num());
+// EXPECT_EQ(durationEndNs - durationStartNs, bucketInfo.duration_nanos());
+// EXPECT_EQ(configAddedTimeNs, bucketInfo.start_bucket_elapsed_nanos());
+// EXPECT_EQ(baseTimeNs + bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
+//}
+//
+//TEST(DurationMetricE2eTest, TestWithActivation) {
+// StatsdConfig config;
+// config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+//
+// auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
+// auto screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
+// auto crashMatcher = CreateProcessCrashAtomMatcher();
+// *config.add_atom_matcher() = screenOnMatcher;
+// *config.add_atom_matcher() = screenOffMatcher;
+// *config.add_atom_matcher() = crashMatcher;
+//
+// auto durationPredicate = CreateScreenIsOnPredicate();
+// *config.add_predicate() = durationPredicate;
+//
+// int64_t metricId = 123456;
+// auto durationMetric = config.add_duration_metric();
+// durationMetric->set_id(metricId);
+// durationMetric->set_what(durationPredicate.id());
+// durationMetric->set_bucket(FIVE_MINUTES);
+// durationMetric->set_aggregation_type(DurationMetric_AggregationType_SUM);
+//
+// auto metric_activation1 = config.add_metric_activation();
+// metric_activation1->set_metric_id(metricId);
+// auto event_activation1 = metric_activation1->add_event_activation();
+// event_activation1->set_atom_matcher_id(crashMatcher.id());
+// event_activation1->set_ttl_seconds(30); // 30 secs.
+//
+// const int64_t bucketStartTimeNs = 10000000000;
+// const int64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000LL * 1000LL;
+//
+// int uid = 12345;
+// int64_t cfgId = 98765;
+// ConfigKey cfgKey(uid, cfgId);
+//
+// sp<UidMap> m = new UidMap();
+// sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+// sp<AlarmMonitor> anomalyAlarmMonitor;
+// sp<AlarmMonitor> subscriberAlarmMonitor;
+// vector<int64_t> activeConfigsBroadcast;
+//
+// int broadcastCount = 0;
+// StatsLogProcessor processor(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor,
+// bucketStartTimeNs, [](const ConfigKey& key) { return true; },
+// [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid,
+// const vector<int64_t>& activeConfigs) {
+// broadcastCount++;
+// EXPECT_EQ(broadcastUid, uid);
+// activeConfigsBroadcast.clear();
+// activeConfigsBroadcast.insert(activeConfigsBroadcast.end(),
+// activeConfigs.begin(), activeConfigs.end());
+// return true;
+// });
+//
+// processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config); // 0:00
+//
+// EXPECT_EQ(processor.mMetricsManagers.size(), 1u);
+// sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
+// EXPECT_TRUE(metricsManager->isConfigValid());
+// EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+// sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+// auto& eventActivationMap = metricProducer->mEventActivationMap;
+//
+// EXPECT_FALSE(metricsManager->isActive());
+// EXPECT_FALSE(metricProducer->mIsActive);
+// EXPECT_EQ(eventActivationMap.size(), 1u);
+// EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
+//
+// std::unique_ptr<LogEvent> event;
+//
+// // Turn screen off.
+// event = CreateScreenStateChangedEvent(
+// android::view::DISPLAY_STATE_OFF, bucketStartTimeNs + 2 * NS_PER_SEC); // 0:02
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + 2 * NS_PER_SEC);
+//
+// // Turn screen on.
+// const int64_t durationStartNs = bucketStartTimeNs + 5 * NS_PER_SEC; // 0:05
+// event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, durationStartNs);
+// processor.OnLogEvent(event.get(), durationStartNs);
+//
+// // Activate metric.
+// const int64_t activationStartNs = bucketStartTimeNs + 5 * NS_PER_SEC; // 0:10
+// const int64_t activationEndNs =
+// activationStartNs + event_activation1->ttl_seconds() * NS_PER_SEC; // 0:40
+// event = CreateAppCrashEvent(111, activationStartNs);
+// processor.OnLogEvent(event.get(), activationStartNs);
+// EXPECT_TRUE(metricsManager->isActive());
+// EXPECT_TRUE(metricProducer->mIsActive);
+// EXPECT_EQ(broadcastCount, 1);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+// EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, activationStartNs);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
+//
+// // Expire activation.
+// const int64_t expirationNs = activationEndNs + 7 * NS_PER_SEC;
+// event = CreateScreenBrightnessChangedEvent(64, expirationNs); // 0:47
+// processor.OnLogEvent(event.get(), expirationNs);
+// EXPECT_FALSE(metricsManager->isActive());
+// EXPECT_FALSE(metricProducer->mIsActive);
+// EXPECT_EQ(broadcastCount, 2);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+// EXPECT_EQ(eventActivationMap.size(), 1u);
+// EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, activationStartNs);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
+//
+// // Turn off screen 10 seconds after activation expiration.
+// const int64_t durationEndNs = activationEndNs + 10 * NS_PER_SEC; // 0:50
+// event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, durationEndNs);
+// processor.OnLogEvent(event.get(),durationEndNs);
+//
+// // Turn screen on.
+// const int64_t duration2StartNs = durationEndNs + 5 * NS_PER_SEC; // 0:55
+// event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, duration2StartNs);
+// processor.OnLogEvent(event.get(), duration2StartNs);
+//
+// // Turn off screen.
+// const int64_t duration2EndNs = duration2StartNs + 10 * NS_PER_SEC; // 1:05
+// event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, duration2EndNs);
+// processor.OnLogEvent(event.get(), duration2EndNs);
+//
+// // Activate metric.
+// const int64_t activation2StartNs = duration2EndNs + 5 * NS_PER_SEC; // 1:10
+// const int64_t activation2EndNs =
+// activation2StartNs + event_activation1->ttl_seconds() * NS_PER_SEC; // 1:40
+// event = CreateAppCrashEvent(211, activation2StartNs);
+// processor.OnLogEvent(event.get(), activation2StartNs);
+// EXPECT_TRUE(metricsManager->isActive());
+// EXPECT_TRUE(metricProducer->mIsActive);
+// EXPECT_EQ(broadcastCount, 3);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+// EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, activation2StartNs);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
+//
+// ConfigMetricsReportList reports;
+// vector<uint8_t> buffer;
+// processor.onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1 * NS_PER_SEC, false, true,
+// ADB_DUMP, FAST, &buffer); // 5:01
+// EXPECT_TRUE(buffer.size() > 0);
+// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+// backfillDimensionPath(&reports);
+// backfillStartEndTimestamp(&reports);
+// EXPECT_EQ(1, reports.reports_size());
+// EXPECT_EQ(1, reports.reports(0).metrics_size());
+// EXPECT_EQ(metricId, reports.reports(0).metrics(0).metric_id());
+// EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
+//
+// const StatsLogReport::DurationMetricDataWrapper& durationMetrics =
+// reports.reports(0).metrics(0).duration_metrics();
+// EXPECT_EQ(1, durationMetrics.data_size());
+//
+// auto data = durationMetrics.data(0);
+// EXPECT_EQ(1, data.bucket_info_size());
+//
+// auto bucketInfo = data.bucket_info(0);
+// EXPECT_EQ(0, bucketInfo.bucket_num());
+// EXPECT_EQ(bucketStartTimeNs, bucketInfo.start_bucket_elapsed_nanos());
+// EXPECT_EQ(expirationNs, bucketInfo.end_bucket_elapsed_nanos());
+// EXPECT_EQ(expirationNs - durationStartNs, bucketInfo.duration_nanos());
+//}
+//
+//TEST(DurationMetricE2eTest, TestWithCondition) {
+// StatsdConfig config;
+// config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+// *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
+// *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();
+// *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher();
+// *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher();
+//
+// auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
+// *config.add_predicate() = holdingWakelockPredicate;
+//
+// auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
+// *config.add_predicate() = isInBackgroundPredicate;
+//
+// auto durationMetric = config.add_duration_metric();
+// durationMetric->set_id(StringToId("WakelockDuration"));
+// durationMetric->set_what(holdingWakelockPredicate.id());
+// durationMetric->set_condition(isInBackgroundPredicate.id());
+// durationMetric->set_aggregation_type(DurationMetric::SUM);
+// durationMetric->set_bucket(FIVE_MINUTES);
+//
+// ConfigKey cfgKey;
+// uint64_t bucketStartTimeNs = 10000000000;
+// uint64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+// sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+// EXPECT_TRUE(metricsManager->isConfigValid());
+// EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+// sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+// auto& eventActivationMap = metricProducer->mEventActivationMap;
+// EXPECT_TRUE(metricsManager->isActive());
+// EXPECT_TRUE(metricProducer->mIsActive);
+// EXPECT_TRUE(eventActivationMap.empty());
+//
+// int appUid = 123;
+// std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(appUid, "App1")};
+//
+// auto event = CreateAcquireWakelockEvent(
+// attributions1, "wl1", bucketStartTimeNs + 10 * NS_PER_SEC); // 0:10
+// processor->OnLogEvent(event.get());
+//
+// event = CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 22 * NS_PER_SEC); // 0:22
+// processor->OnLogEvent(event.get());
+//
+// event = CreateMoveToForegroundEvent(
+// appUid, bucketStartTimeNs + (3 * 60 + 15) * NS_PER_SEC); // 3:15
+// processor->OnLogEvent(event.get());
+//
+// event = CreateReleaseWakelockEvent(
+// attributions1, "wl1", bucketStartTimeNs + 4 * 60 * NS_PER_SEC); // 4:00
+// processor->OnLogEvent(event.get());
+//
+// vector<uint8_t> buffer;
+// ConfigMetricsReportList reports;
+// processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true,
+// ADB_DUMP, FAST, &buffer);
+// EXPECT_GT(buffer.size(), 0);
+// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+// backfillDimensionPath(&reports);
+// backfillStringInReport(&reports);
+// backfillStartEndTimestamp(&reports);
+//
+// EXPECT_EQ(1, reports.reports_size());
+// EXPECT_EQ(1, reports.reports(0).metrics_size());
+// EXPECT_EQ(1, reports.reports(0).metrics(0).duration_metrics().data_size());
+//
+// auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
+//
+// // Validate bucket info.
+// EXPECT_EQ(1, data.bucket_info_size());
+//
+// auto bucketInfo = data.bucket_info(0);
+// EXPECT_EQ(bucketStartTimeNs, bucketInfo.start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
+// EXPECT_EQ((2 * 60 + 53) * NS_PER_SEC, bucketInfo.duration_nanos());
+//}
+//
+//TEST(DurationMetricE2eTest, TestWithSlicedCondition) {
+// StatsdConfig config;
+// config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+// auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
+// *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
+// *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();
+// *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher();
+// *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher();
+//
+// auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
+// // The predicate is dimensioning by first attribution node by uid.
+// FieldMatcher dimensions = CreateAttributionUidDimensions(
+// android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+// *holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions() = dimensions;
+// *config.add_predicate() = holdingWakelockPredicate;
+//
+// auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
+// *isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() =
+// CreateDimensions(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {Position::FIRST});
+// *config.add_predicate() = isInBackgroundPredicate;
+//
+// auto durationMetric = config.add_duration_metric();
+// durationMetric->set_id(StringToId("WakelockDuration"));
+// durationMetric->set_what(holdingWakelockPredicate.id());
+// durationMetric->set_condition(isInBackgroundPredicate.id());
+// durationMetric->set_aggregation_type(DurationMetric::SUM);
+// // The metric is dimensioning by first attribution node and only by uid.
+// *durationMetric->mutable_dimensions_in_what() =
+// CreateAttributionUidDimensions(
+// android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+// durationMetric->set_bucket(FIVE_MINUTES);
+//
+// // Links between wakelock state atom and condition of app is in background.
+// auto links = durationMetric->add_links();
+// links->set_condition(isInBackgroundPredicate.id());
+// auto dimensionWhat = links->mutable_fields_in_what();
+// dimensionWhat->set_field(android::util::WAKELOCK_STATE_CHANGED);
+// dimensionWhat->add_child()->set_field(1); // uid field.
+// *links->mutable_fields_in_condition() = CreateAttributionUidDimensions(
+// android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, { Position::FIRST });
+//
+// ConfigKey cfgKey;
+// uint64_t bucketStartTimeNs = 10000000000;
+// uint64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+// sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+// EXPECT_TRUE(metricsManager->isConfigValid());
+// EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+// sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+// auto& eventActivationMap = metricProducer->mEventActivationMap;
+// EXPECT_TRUE(metricsManager->isActive());
+// EXPECT_TRUE(metricProducer->mIsActive);
+// EXPECT_TRUE(eventActivationMap.empty());
+//
+// int appUid = 123;
+// std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(appUid, "App1")};
+//
+// auto event = CreateAcquireWakelockEvent(
+// attributions1, "wl1", bucketStartTimeNs + 10 * NS_PER_SEC); // 0:10
+// processor->OnLogEvent(event.get());
+//
+// event = CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 22 * NS_PER_SEC); // 0:22
+// processor->OnLogEvent(event.get());
+//
+// event = CreateReleaseWakelockEvent(
+// attributions1, "wl1", bucketStartTimeNs + 60 * NS_PER_SEC); // 1:00
+// processor->OnLogEvent(event.get());
+//
+//
+// event = CreateMoveToForegroundEvent(
+// appUid, bucketStartTimeNs + (3 * 60 + 15) * NS_PER_SEC); // 3:15
+// processor->OnLogEvent(event.get());
+//
+// vector<uint8_t> buffer;
+// ConfigMetricsReportList reports;
+// processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true,
+// ADB_DUMP, FAST, &buffer);
+// EXPECT_GT(buffer.size(), 0);
+// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+// backfillDimensionPath(&reports);
+// backfillStringInReport(&reports);
+// backfillStartEndTimestamp(&reports);
+//
+// EXPECT_EQ(1, reports.reports_size());
+// EXPECT_EQ(1, reports.reports(0).metrics_size());
+// EXPECT_EQ(1, reports.reports(0).metrics(0).duration_metrics().data_size());
+//
+// auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
+// // Validate dimension value.
+// ValidateAttributionUidDimension(data.dimensions_in_what(),
+// android::util::WAKELOCK_STATE_CHANGED, appUid);
+// // Validate bucket info.
+// EXPECT_EQ(1, data.bucket_info_size());
+//
+// auto bucketInfo = data.bucket_info(0);
+// EXPECT_EQ(bucketStartTimeNs, bucketInfo.start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
+// EXPECT_EQ(38 * NS_PER_SEC, bucketInfo.duration_nanos());
+//}
+//
+//TEST(DurationMetricE2eTest, TestWithActivationAndSlicedCondition) {
+// StatsdConfig config;
+// config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+// auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
+// *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
+// *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();
+// *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher();
+// *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher();
+// *config.add_atom_matcher() = screenOnMatcher;
+//
+// auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
+// // The predicate is dimensioning by first attribution node by uid.
+// FieldMatcher dimensions = CreateAttributionUidDimensions(
+// android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+// *holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions() = dimensions;
+// *config.add_predicate() = holdingWakelockPredicate;
+//
+// auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
+// *isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() =
+// CreateDimensions(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {Position::FIRST});
+// *config.add_predicate() = isInBackgroundPredicate;
+//
+// auto durationMetric = config.add_duration_metric();
+// durationMetric->set_id(StringToId("WakelockDuration"));
+// durationMetric->set_what(holdingWakelockPredicate.id());
+// durationMetric->set_condition(isInBackgroundPredicate.id());
+// durationMetric->set_aggregation_type(DurationMetric::SUM);
+// // The metric is dimensioning by first attribution node and only by uid.
+// *durationMetric->mutable_dimensions_in_what() =
+// CreateAttributionUidDimensions(
+// android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+// durationMetric->set_bucket(FIVE_MINUTES);
+//
+// // Links between wakelock state atom and condition of app is in background.
+// auto links = durationMetric->add_links();
+// links->set_condition(isInBackgroundPredicate.id());
+// auto dimensionWhat = links->mutable_fields_in_what();
+// dimensionWhat->set_field(android::util::WAKELOCK_STATE_CHANGED);
+// dimensionWhat->add_child()->set_field(1); // uid field.
+// *links->mutable_fields_in_condition() = CreateAttributionUidDimensions(
+// android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, { Position::FIRST });
+//
+// auto metric_activation1 = config.add_metric_activation();
+// metric_activation1->set_metric_id(durationMetric->id());
+// auto event_activation1 = metric_activation1->add_event_activation();
+// event_activation1->set_atom_matcher_id(screenOnMatcher.id());
+// event_activation1->set_ttl_seconds(60 * 2); // 2 minutes.
+//
+// ConfigKey cfgKey;
+// uint64_t bucketStartTimeNs = 10000000000;
+// uint64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+// sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+// EXPECT_TRUE(metricsManager->isConfigValid());
+// EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+// sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+// auto& eventActivationMap = metricProducer->mEventActivationMap;
+// EXPECT_FALSE(metricsManager->isActive());
+// EXPECT_FALSE(metricProducer->mIsActive);
+// EXPECT_EQ(eventActivationMap.size(), 1u);
+// EXPECT_TRUE(eventActivationMap.find(4) != eventActivationMap.end());
+// EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[4]->start_ns, 0);
+// EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
+//
+// int appUid = 123;
+// std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(appUid, "App1")};
+//
+// auto event = CreateAcquireWakelockEvent(
+// attributions1, "wl1", bucketStartTimeNs + 10 * NS_PER_SEC); // 0:10
+// processor->OnLogEvent(event.get());
+// EXPECT_FALSE(metricsManager->isActive());
+// EXPECT_FALSE(metricProducer->mIsActive);
+// EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[4]->start_ns, 0);
+// EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
+//
+// event = CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 22 * NS_PER_SEC); // 0:22
+// processor->OnLogEvent(event.get());
+// EXPECT_FALSE(metricsManager->isActive());
+// EXPECT_FALSE(metricProducer->mIsActive);
+// EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[4]->start_ns, 0);
+// EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
+//
+// const int64_t durationStartNs = bucketStartTimeNs + 30 * NS_PER_SEC; // 0:30
+// event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, durationStartNs);
+// processor->OnLogEvent(event.get());
+// EXPECT_TRUE(metricsManager->isActive());
+// EXPECT_TRUE(metricProducer->mIsActive);
+// EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[4]->start_ns, durationStartNs);
+// EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
+//
+// const int64_t durationEndNs =
+// durationStartNs + (event_activation1->ttl_seconds() + 30) * NS_PER_SEC; // 3:00
+// event = CreateAppCrashEvent(333, durationEndNs);
+// processor->OnLogEvent(event.get());
+// EXPECT_FALSE(metricsManager->isActive());
+// EXPECT_FALSE(metricProducer->mIsActive);
+// EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[4]->start_ns, durationStartNs);
+// EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
+//
+// event = CreateMoveToForegroundEvent(
+// appUid, bucketStartTimeNs + (3 * 60 + 15) * NS_PER_SEC); // 3:15
+// processor->OnLogEvent(event.get());
+//
+// event = CreateReleaseWakelockEvent(
+// attributions1, "wl1", bucketStartTimeNs + (4 * 60 + 17) * NS_PER_SEC); // 4:17
+// processor->OnLogEvent(event.get());
+//
+// event = CreateMoveToBackgroundEvent(
+// appUid, bucketStartTimeNs + (4 * 60 + 20) * NS_PER_SEC); // 4:20
+// processor->OnLogEvent(event.get());
+//
+// event = CreateAcquireWakelockEvent(
+// attributions1, "wl1", bucketStartTimeNs + (4 * 60 + 25) * NS_PER_SEC); // 4:25
+// processor->OnLogEvent(event.get());
+//
+// const int64_t duration2StartNs = bucketStartTimeNs + (4 * 60 + 30) * NS_PER_SEC; // 4:30
+// event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, duration2StartNs);
+// processor->OnLogEvent(event.get());
+// EXPECT_TRUE(metricsManager->isActive());
+// EXPECT_TRUE(metricProducer->mIsActive);
+// EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[4]->start_ns, duration2StartNs);
+// EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
+//
+// vector<uint8_t> buffer;
+// ConfigMetricsReportList reports;
+// processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true,
+// ADB_DUMP, FAST, &buffer);
+// EXPECT_GT(buffer.size(), 0);
+// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+// backfillDimensionPath(&reports);
+// backfillStringInReport(&reports);
+// backfillStartEndTimestamp(&reports);
+//
+// EXPECT_EQ(1, reports.reports_size());
+// EXPECT_EQ(1, reports.reports(0).metrics_size());
+// EXPECT_EQ(1, reports.reports(0).metrics(0).duration_metrics().data_size());
+//
+// auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
+// // Validate dimension value.
+// ValidateAttributionUidDimension(data.dimensions_in_what(),
+// android::util::WAKELOCK_STATE_CHANGED, appUid);
+// // Validate bucket info.
+// EXPECT_EQ(2, data.bucket_info_size());
+//
+// auto bucketInfo = data.bucket_info(0);
+// EXPECT_EQ(bucketStartTimeNs, bucketInfo.start_bucket_elapsed_nanos());
+// EXPECT_EQ(durationEndNs, bucketInfo.end_bucket_elapsed_nanos());
+// EXPECT_EQ(durationEndNs - durationStartNs, bucketInfo.duration_nanos());
+//
+// bucketInfo = data.bucket_info(1);
+// EXPECT_EQ(durationEndNs, bucketInfo.start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - duration2StartNs, bucketInfo.duration_nanos());
+//}
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
index 9127be8..7f651d4 100644
--- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
+++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
@@ -63,483 +63,484 @@
return config;
}
-} // namespace
+} // namespaces
-TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvents) {
- auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE);
- int64_t baseTimeNs = getElapsedRealtimeNs();
- int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
- int64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
-
- ConfigKey cfgKey;
- auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
- SharedRefBase::make<FakeSubsystemSleepCallback>(),
- ATOM_TAG);
- EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
- EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
- processor->mPullerManager->ForceClearPullerCache();
-
- int startBucketNum = processor->mMetricsManagers.begin()->second->
- mAllMetricProducers[0]->getCurrentBucketNum();
- EXPECT_GT(startBucketNum, (int64_t)0);
-
- // When creating the config, the gauge metric producer should register the alarm at the
- // end of the current bucket.
- EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
- EXPECT_EQ(bucketSizeNs,
- processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
- int64_t& nextPullTimeNs =
- processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
- EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, nextPullTimeNs);
-
- auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
- configAddedTimeNs + 55);
- processor->OnLogEvent(screenOffEvent.get());
-
- // Pulling alarm arrives on time and reset the sequential pulling alarm.
- processor->informPullAlarmFired(nextPullTimeNs + 1);
- EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, nextPullTimeNs);
-
- auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
- configAddedTimeNs + bucketSizeNs + 10);
- processor->OnLogEvent(screenOnEvent.get());
-
- screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
- configAddedTimeNs + bucketSizeNs + 100);
- processor->OnLogEvent(screenOffEvent.get());
-
- processor->informPullAlarmFired(nextPullTimeNs + 1);
- EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs,
- nextPullTimeNs);
-
- processor->informPullAlarmFired(nextPullTimeNs + 1);
- EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, nextPullTimeNs);
-
- screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
- configAddedTimeNs + 3 * bucketSizeNs + 2);
- processor->OnLogEvent(screenOnEvent.get());
-
- processor->informPullAlarmFired(nextPullTimeNs + 3);
- EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, nextPullTimeNs);
-
- screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
- configAddedTimeNs + 5 * bucketSizeNs + 1);
- processor->OnLogEvent(screenOffEvent.get());
-
- processor->informPullAlarmFired(nextPullTimeNs + 2);
- EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, nextPullTimeNs);
-
- processor->informPullAlarmFired(nextPullTimeNs + 2);
-
- ConfigMetricsReportList reports;
- vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
- ADB_DUMP, FAST, &buffer);
- EXPECT_TRUE(buffer.size() > 0);
- EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
- backfillDimensionPath(&reports);
- backfillStringInReport(&reports);
- backfillStartEndTimestamp(&reports);
- EXPECT_EQ(1, reports.reports_size());
- EXPECT_EQ(1, reports.reports(0).metrics_size());
- StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
- sortMetricDataByDimensionsValue(
- reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
- EXPECT_GT((int)gaugeMetrics.data_size(), 1);
-
- auto data = gaugeMetrics.data(0);
- EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* subsystem name field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
- EXPECT_EQ(6, data.bucket_info_size());
-
- EXPECT_EQ(1, data.bucket_info(0).atom_size());
- EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
- EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
- EXPECT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
- EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
- EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty());
- EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0);
-
- EXPECT_EQ(1, data.bucket_info(1).atom_size());
- EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 1,
- data.bucket_info(1).elapsed_timestamp_nanos(0));
- EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 1, data.bucket_info(1).elapsed_timestamp_nanos(0));
- EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
- EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
- EXPECT_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty());
- EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 0);
-
- EXPECT_EQ(1, data.bucket_info(2).atom_size());
- EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
- EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs + 1,
- data.bucket_info(2).elapsed_timestamp_nanos(0));
- EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
- EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
- EXPECT_TRUE(data.bucket_info(2).atom(0).subsystem_sleep_state().subsystem_name().empty());
- EXPECT_GT(data.bucket_info(2).atom(0).subsystem_sleep_state().time_millis(), 0);
-
- EXPECT_EQ(1, data.bucket_info(3).atom_size());
- EXPECT_EQ(1, data.bucket_info(3).elapsed_timestamp_nanos_size());
- EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs + 1,
- data.bucket_info(3).elapsed_timestamp_nanos(0));
- EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(3).start_bucket_elapsed_nanos());
- EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(3).end_bucket_elapsed_nanos());
- EXPECT_TRUE(data.bucket_info(3).atom(0).subsystem_sleep_state().subsystem_name().empty());
- EXPECT_GT(data.bucket_info(3).atom(0).subsystem_sleep_state().time_millis(), 0);
-
- EXPECT_EQ(1, data.bucket_info(4).atom_size());
- EXPECT_EQ(1, data.bucket_info(4).elapsed_timestamp_nanos_size());
- EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs + 1,
- data.bucket_info(4).elapsed_timestamp_nanos(0));
- EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(4).start_bucket_elapsed_nanos());
- EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(4).end_bucket_elapsed_nanos());
- EXPECT_TRUE(data.bucket_info(4).atom(0).subsystem_sleep_state().subsystem_name().empty());
- EXPECT_GT(data.bucket_info(4).atom(0).subsystem_sleep_state().time_millis(), 0);
-
- EXPECT_EQ(1, data.bucket_info(5).atom_size());
- EXPECT_EQ(1, data.bucket_info(5).elapsed_timestamp_nanos_size());
- EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs + 2,
- data.bucket_info(5).elapsed_timestamp_nanos(0));
- EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(5).start_bucket_elapsed_nanos());
- EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(5).end_bucket_elapsed_nanos());
- EXPECT_TRUE(data.bucket_info(5).atom(0).subsystem_sleep_state().subsystem_name().empty());
- EXPECT_GT(data.bucket_info(5).atom(0).subsystem_sleep_state().time_millis(), 0);
-}
-
-TEST(GaugeMetricE2eTest, TestConditionChangeToTrueSamplePulledEvents) {
- auto config = CreateStatsdConfig(GaugeMetric::CONDITION_CHANGE_TO_TRUE);
- int64_t baseTimeNs = getElapsedRealtimeNs();
- int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
- int64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
-
- ConfigKey cfgKey;
- auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
- SharedRefBase::make<FakeSubsystemSleepCallback>(),
- ATOM_TAG);
- EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
- EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
- processor->mPullerManager->ForceClearPullerCache();
-
- int startBucketNum = processor->mMetricsManagers.begin()->second->
- mAllMetricProducers[0]->getCurrentBucketNum();
- EXPECT_GT(startBucketNum, (int64_t)0);
-
- auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
- configAddedTimeNs + 55);
- processor->OnLogEvent(screenOffEvent.get());
-
- auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
- configAddedTimeNs + bucketSizeNs + 10);
- processor->OnLogEvent(screenOnEvent.get());
-
- screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
- configAddedTimeNs + bucketSizeNs + 100);
- processor->OnLogEvent(screenOffEvent.get());
-
- screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
- configAddedTimeNs + 3 * bucketSizeNs + 2);
- processor->OnLogEvent(screenOnEvent.get());
-
- screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
- configAddedTimeNs + 5 * bucketSizeNs + 1);
- processor->OnLogEvent(screenOffEvent.get());
- screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
- configAddedTimeNs + 5 * bucketSizeNs + 3);
- processor->OnLogEvent(screenOnEvent.get());
- screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
- configAddedTimeNs + 5 * bucketSizeNs + 10);
- processor->OnLogEvent(screenOffEvent.get());
-
- ConfigMetricsReportList reports;
- vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, configAddedTimeNs + 8 * bucketSizeNs + 10, false, true,
- ADB_DUMP, FAST, &buffer);
- EXPECT_TRUE(buffer.size() > 0);
- EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
- backfillDimensionPath(&reports);
- backfillStringInReport(&reports);
- backfillStartEndTimestamp(&reports);
- EXPECT_EQ(1, reports.reports_size());
- EXPECT_EQ(1, reports.reports(0).metrics_size());
- StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
- sortMetricDataByDimensionsValue(
- reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
- EXPECT_GT((int)gaugeMetrics.data_size(), 1);
-
- auto data = gaugeMetrics.data(0);
- EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* subsystem name field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
- EXPECT_EQ(3, data.bucket_info_size());
-
- EXPECT_EQ(1, data.bucket_info(0).atom_size());
- EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
- EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
- EXPECT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
- EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
- EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty());
- EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0);
-
- EXPECT_EQ(1, data.bucket_info(1).atom_size());
- EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 100,
- data.bucket_info(1).elapsed_timestamp_nanos(0));
- EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
- EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
- EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
- EXPECT_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty());
- EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 0);
-
- EXPECT_EQ(2, data.bucket_info(2).atom_size());
- EXPECT_EQ(2, data.bucket_info(2).elapsed_timestamp_nanos_size());
- EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs + 1,
- data.bucket_info(2).elapsed_timestamp_nanos(0));
- EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs + 10,
- data.bucket_info(2).elapsed_timestamp_nanos(1));
- EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
- EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
- EXPECT_TRUE(data.bucket_info(2).atom(0).subsystem_sleep_state().subsystem_name().empty());
- EXPECT_GT(data.bucket_info(2).atom(0).subsystem_sleep_state().time_millis(), 0);
- EXPECT_TRUE(data.bucket_info(2).atom(1).subsystem_sleep_state().subsystem_name().empty());
- EXPECT_GT(data.bucket_info(2).atom(1).subsystem_sleep_state().time_millis(), 0);
-}
-
-
-TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvent_LateAlarm) {
- auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE);
- int64_t baseTimeNs = getElapsedRealtimeNs();
- int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
- int64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
-
- ConfigKey cfgKey;
- auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
- SharedRefBase::make<FakeSubsystemSleepCallback>(),
- ATOM_TAG);
- EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
- EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
- processor->mPullerManager->ForceClearPullerCache();
-
- int startBucketNum = processor->mMetricsManagers.begin()->second->
- mAllMetricProducers[0]->getCurrentBucketNum();
- EXPECT_GT(startBucketNum, (int64_t)0);
-
- // When creating the config, the gauge metric producer should register the alarm at the
- // end of the current bucket.
- EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
- EXPECT_EQ(bucketSizeNs,
- processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
- int64_t& nextPullTimeNs =
- processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
- EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, nextPullTimeNs);
-
- auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
- configAddedTimeNs + 55);
- processor->OnLogEvent(screenOffEvent.get());
-
- auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
- configAddedTimeNs + bucketSizeNs + 10);
- processor->OnLogEvent(screenOnEvent.get());
-
- // Pulling alarm arrives one bucket size late.
- processor->informPullAlarmFired(nextPullTimeNs + bucketSizeNs);
- EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs, nextPullTimeNs);
-
- screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
- configAddedTimeNs + 3 * bucketSizeNs + 11);
- processor->OnLogEvent(screenOffEvent.get());
-
- // Pulling alarm arrives more than one bucket size late.
- processor->informPullAlarmFired(nextPullTimeNs + bucketSizeNs + 12);
- EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, nextPullTimeNs);
-
- ConfigMetricsReportList reports;
- vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
- ADB_DUMP, FAST, &buffer);
- EXPECT_TRUE(buffer.size() > 0);
- EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
- backfillDimensionPath(&reports);
- backfillStringInReport(&reports);
- backfillStartEndTimestamp(&reports);
- EXPECT_EQ(1, reports.reports_size());
- EXPECT_EQ(1, reports.reports(0).metrics_size());
- StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
- sortMetricDataByDimensionsValue(
- reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
- EXPECT_GT((int)gaugeMetrics.data_size(), 1);
-
- auto data = gaugeMetrics.data(0);
- EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* subsystem name field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
- EXPECT_EQ(3, data.bucket_info_size());
-
- EXPECT_EQ(1, data.bucket_info(0).atom_size());
- EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
- EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
- EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
- EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty());
- EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0);
-
- EXPECT_EQ(1, data.bucket_info(1).atom_size());
- EXPECT_EQ(configAddedTimeNs + 3 * bucketSizeNs + 11,
- data.bucket_info(1).elapsed_timestamp_nanos(0));
- EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
- EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
- EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
- EXPECT_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty());
- EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 0);
-
- EXPECT_EQ(1, data.bucket_info(2).atom_size());
- EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
- EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs + 12,
- data.bucket_info(2).elapsed_timestamp_nanos(0));
- EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
- EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
- EXPECT_TRUE(data.bucket_info(2).atom(0).subsystem_sleep_state().subsystem_name().empty());
- EXPECT_GT(data.bucket_info(2).atom(0).subsystem_sleep_state().time_millis(), 0);
-}
-
-TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsWithActivation) {
- auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE, /*useCondition=*/false);
-
- int64_t baseTimeNs = getElapsedRealtimeNs();
- int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
- int64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
-
- auto batterySaverStartMatcher = CreateBatterySaverModeStartAtomMatcher();
- *config.add_atom_matcher() = batterySaverStartMatcher;
- const int64_t ttlNs = 2 * bucketSizeNs; // Two buckets.
- auto metric_activation = config.add_metric_activation();
- metric_activation->set_metric_id(metricId);
- metric_activation->set_activation_type(ACTIVATE_IMMEDIATELY);
- auto event_activation = metric_activation->add_event_activation();
- event_activation->set_atom_matcher_id(batterySaverStartMatcher.id());
- event_activation->set_ttl_seconds(ttlNs / 1000000000);
-
- ConfigKey cfgKey;
- auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
- SharedRefBase::make<FakeSubsystemSleepCallback>(),
- ATOM_TAG);
- EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
- EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
- processor->mPullerManager->ForceClearPullerCache();
-
- int startBucketNum = processor->mMetricsManagers.begin()->second->
- mAllMetricProducers[0]->getCurrentBucketNum();
- EXPECT_GT(startBucketNum, (int64_t)0);
- EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
-
- // When creating the config, the gauge metric producer should register the alarm at the
- // end of the current bucket.
- EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
- EXPECT_EQ(bucketSizeNs,
- processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
- int64_t& nextPullTimeNs =
- processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
- EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, nextPullTimeNs);
-
- // Pulling alarm arrives on time and reset the sequential pulling alarm.
- // Event should not be kept.
- processor->informPullAlarmFired(nextPullTimeNs + 1); // 15 mins + 1 ns.
- EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, nextPullTimeNs);
- EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
-
- // Activate the metric. A pull occurs upon activation.
- const int64_t activationNs = configAddedTimeNs + bucketSizeNs + (2 * 1000 * 1000); // 2 millis.
- auto batterySaverOnEvent = CreateBatterySaverOnEvent(activationNs);
- processor->OnLogEvent(batterySaverOnEvent.get()); // 15 mins + 2 ms.
- EXPECT_TRUE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
-
- // This event should be kept. 2 total.
- processor->informPullAlarmFired(nextPullTimeNs + 1); // 20 mins + 1 ns.
- EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs,
- nextPullTimeNs);
-
- // This event should be kept. 3 total.
- processor->informPullAlarmFired(nextPullTimeNs + 2); // 25 mins + 2 ns.
- EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, nextPullTimeNs);
-
- // Create random event to deactivate metric.
- auto deactivationEvent = CreateScreenBrightnessChangedEvent(50, activationNs + ttlNs + 1);
- processor->OnLogEvent(deactivationEvent.get());
- EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
-
- // Event should not be kept. 3 total.
- processor->informPullAlarmFired(nextPullTimeNs + 3);
- EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, nextPullTimeNs);
-
- processor->informPullAlarmFired(nextPullTimeNs + 2);
-
- ConfigMetricsReportList reports;
- vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
- ADB_DUMP, FAST, &buffer);
- EXPECT_TRUE(buffer.size() > 0);
- EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
- backfillDimensionPath(&reports);
- backfillStringInReport(&reports);
- backfillStartEndTimestamp(&reports);
- EXPECT_EQ(1, reports.reports_size());
- EXPECT_EQ(1, reports.reports(0).metrics_size());
- StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
- sortMetricDataByDimensionsValue(
- reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
- EXPECT_GT((int)gaugeMetrics.data_size(), 0);
-
- auto data = gaugeMetrics.data(0);
- EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* subsystem name field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
- EXPECT_EQ(3, data.bucket_info_size());
-
- auto bucketInfo = data.bucket_info(0);
- EXPECT_EQ(1, bucketInfo.atom_size());
- EXPECT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
- EXPECT_EQ(activationNs, bucketInfo.elapsed_timestamp_nanos(0));
- EXPECT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
- EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
- EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
- EXPECT_TRUE(bucketInfo.atom(0).subsystem_sleep_state().subsystem_name().empty());
- EXPECT_GT(bucketInfo.atom(0).subsystem_sleep_state().time_millis(), 0);
-
- bucketInfo = data.bucket_info(1);
- EXPECT_EQ(1, bucketInfo.atom_size());
- EXPECT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
- EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs + 1, bucketInfo.elapsed_timestamp_nanos(0));
- EXPECT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
- EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
- EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
- EXPECT_TRUE(bucketInfo.atom(0).subsystem_sleep_state().subsystem_name().empty());
- EXPECT_GT(bucketInfo.atom(0).subsystem_sleep_state().time_millis(), 0);
-
- bucketInfo = data.bucket_info(2);
- EXPECT_EQ(1, bucketInfo.atom_size());
- EXPECT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
- EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs + 2, bucketInfo.elapsed_timestamp_nanos(0));
- EXPECT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
- EXPECT_EQ(MillisToNano(NanoToMillis(baseTimeNs + 5 * bucketSizeNs)),
- bucketInfo.start_bucket_elapsed_nanos());
- EXPECT_EQ(MillisToNano(NanoToMillis(activationNs + ttlNs + 1)),
- bucketInfo.end_bucket_elapsed_nanos());
- EXPECT_TRUE(bucketInfo.atom(0).subsystem_sleep_state().subsystem_name().empty());
- EXPECT_GT(bucketInfo.atom(0).subsystem_sleep_state().time_millis(), 0);
-}
+// TODO(b/149590301): Update this test to use new socket schema.
+//TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvents) {
+// auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE);
+// int64_t baseTimeNs = getElapsedRealtimeNs();
+// int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
+// int64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
+//
+// ConfigKey cfgKey;
+// auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
+// SharedRefBase::make<FakeSubsystemSleepCallback>(),
+// ATOM_TAG);
+// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+// processor->mPullerManager->ForceClearPullerCache();
+//
+// int startBucketNum = processor->mMetricsManagers.begin()->second->
+// mAllMetricProducers[0]->getCurrentBucketNum();
+// EXPECT_GT(startBucketNum, (int64_t)0);
+//
+// // When creating the config, the gauge metric producer should register the alarm at the
+// // end of the current bucket.
+// EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
+// EXPECT_EQ(bucketSizeNs,
+// processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
+// int64_t& nextPullTimeNs =
+// processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
+// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, nextPullTimeNs);
+//
+// auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+// configAddedTimeNs + 55);
+// processor->OnLogEvent(screenOffEvent.get());
+//
+// // Pulling alarm arrives on time and reset the sequential pulling alarm.
+// processor->informPullAlarmFired(nextPullTimeNs + 1);
+// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, nextPullTimeNs);
+//
+// auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+// configAddedTimeNs + bucketSizeNs + 10);
+// processor->OnLogEvent(screenOnEvent.get());
+//
+// screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+// configAddedTimeNs + bucketSizeNs + 100);
+// processor->OnLogEvent(screenOffEvent.get());
+//
+// processor->informPullAlarmFired(nextPullTimeNs + 1);
+// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs,
+// nextPullTimeNs);
+//
+// processor->informPullAlarmFired(nextPullTimeNs + 1);
+// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, nextPullTimeNs);
+//
+// screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+// configAddedTimeNs + 3 * bucketSizeNs + 2);
+// processor->OnLogEvent(screenOnEvent.get());
+//
+// processor->informPullAlarmFired(nextPullTimeNs + 3);
+// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, nextPullTimeNs);
+//
+// screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+// configAddedTimeNs + 5 * bucketSizeNs + 1);
+// processor->OnLogEvent(screenOffEvent.get());
+//
+// processor->informPullAlarmFired(nextPullTimeNs + 2);
+// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, nextPullTimeNs);
+//
+// processor->informPullAlarmFired(nextPullTimeNs + 2);
+//
+// ConfigMetricsReportList reports;
+// vector<uint8_t> buffer;
+// processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
+// ADB_DUMP, FAST, &buffer);
+// EXPECT_TRUE(buffer.size() > 0);
+// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+// backfillDimensionPath(&reports);
+// backfillStringInReport(&reports);
+// backfillStartEndTimestamp(&reports);
+// EXPECT_EQ(1, reports.reports_size());
+// EXPECT_EQ(1, reports.reports(0).metrics_size());
+// StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
+// sortMetricDataByDimensionsValue(
+// reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
+// EXPECT_GT((int)gaugeMetrics.data_size(), 1);
+//
+// auto data = gaugeMetrics.data(0);
+// EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* subsystem name field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
+// EXPECT_EQ(6, data.bucket_info_size());
+//
+// EXPECT_EQ(1, data.bucket_info(0).atom_size());
+// EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
+// EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
+// EXPECT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
+// EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+// EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty());
+// EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0);
+//
+// EXPECT_EQ(1, data.bucket_info(1).atom_size());
+// EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 1,
+// data.bucket_info(1).elapsed_timestamp_nanos(0));
+// EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 1, data.bucket_info(1).elapsed_timestamp_nanos(0));
+// EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
+// EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
+// EXPECT_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty());
+// EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 0);
+//
+// EXPECT_EQ(1, data.bucket_info(2).atom_size());
+// EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
+// EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs + 1,
+// data.bucket_info(2).elapsed_timestamp_nanos(0));
+// EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
+// EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
+// EXPECT_TRUE(data.bucket_info(2).atom(0).subsystem_sleep_state().subsystem_name().empty());
+// EXPECT_GT(data.bucket_info(2).atom(0).subsystem_sleep_state().time_millis(), 0);
+//
+// EXPECT_EQ(1, data.bucket_info(3).atom_size());
+// EXPECT_EQ(1, data.bucket_info(3).elapsed_timestamp_nanos_size());
+// EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs + 1,
+// data.bucket_info(3).elapsed_timestamp_nanos(0));
+// EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(3).start_bucket_elapsed_nanos());
+// EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(3).end_bucket_elapsed_nanos());
+// EXPECT_TRUE(data.bucket_info(3).atom(0).subsystem_sleep_state().subsystem_name().empty());
+// EXPECT_GT(data.bucket_info(3).atom(0).subsystem_sleep_state().time_millis(), 0);
+//
+// EXPECT_EQ(1, data.bucket_info(4).atom_size());
+// EXPECT_EQ(1, data.bucket_info(4).elapsed_timestamp_nanos_size());
+// EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs + 1,
+// data.bucket_info(4).elapsed_timestamp_nanos(0));
+// EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(4).start_bucket_elapsed_nanos());
+// EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(4).end_bucket_elapsed_nanos());
+// EXPECT_TRUE(data.bucket_info(4).atom(0).subsystem_sleep_state().subsystem_name().empty());
+// EXPECT_GT(data.bucket_info(4).atom(0).subsystem_sleep_state().time_millis(), 0);
+//
+// EXPECT_EQ(1, data.bucket_info(5).atom_size());
+// EXPECT_EQ(1, data.bucket_info(5).elapsed_timestamp_nanos_size());
+// EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs + 2,
+// data.bucket_info(5).elapsed_timestamp_nanos(0));
+// EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(5).start_bucket_elapsed_nanos());
+// EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(5).end_bucket_elapsed_nanos());
+// EXPECT_TRUE(data.bucket_info(5).atom(0).subsystem_sleep_state().subsystem_name().empty());
+// EXPECT_GT(data.bucket_info(5).atom(0).subsystem_sleep_state().time_millis(), 0);
+//}
+//
+//TEST(GaugeMetricE2eTest, TestConditionChangeToTrueSamplePulledEvents) {
+// auto config = CreateStatsdConfig(GaugeMetric::CONDITION_CHANGE_TO_TRUE);
+// int64_t baseTimeNs = getElapsedRealtimeNs();
+// int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
+// int64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
+//
+// ConfigKey cfgKey;
+// auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
+// SharedRefBase::make<FakeSubsystemSleepCallback>(),
+// ATOM_TAG);
+// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+// processor->mPullerManager->ForceClearPullerCache();
+//
+// int startBucketNum = processor->mMetricsManagers.begin()->second->
+// mAllMetricProducers[0]->getCurrentBucketNum();
+// EXPECT_GT(startBucketNum, (int64_t)0);
+//
+// auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+// configAddedTimeNs + 55);
+// processor->OnLogEvent(screenOffEvent.get());
+//
+// auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+// configAddedTimeNs + bucketSizeNs + 10);
+// processor->OnLogEvent(screenOnEvent.get());
+//
+// screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+// configAddedTimeNs + bucketSizeNs + 100);
+// processor->OnLogEvent(screenOffEvent.get());
+//
+// screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+// configAddedTimeNs + 3 * bucketSizeNs + 2);
+// processor->OnLogEvent(screenOnEvent.get());
+//
+// screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+// configAddedTimeNs + 5 * bucketSizeNs + 1);
+// processor->OnLogEvent(screenOffEvent.get());
+// screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+// configAddedTimeNs + 5 * bucketSizeNs + 3);
+// processor->OnLogEvent(screenOnEvent.get());
+// screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+// configAddedTimeNs + 5 * bucketSizeNs + 10);
+// processor->OnLogEvent(screenOffEvent.get());
+//
+// ConfigMetricsReportList reports;
+// vector<uint8_t> buffer;
+// processor->onDumpReport(cfgKey, configAddedTimeNs + 8 * bucketSizeNs + 10, false, true,
+// ADB_DUMP, FAST, &buffer);
+// EXPECT_TRUE(buffer.size() > 0);
+// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+// backfillDimensionPath(&reports);
+// backfillStringInReport(&reports);
+// backfillStartEndTimestamp(&reports);
+// EXPECT_EQ(1, reports.reports_size());
+// EXPECT_EQ(1, reports.reports(0).metrics_size());
+// StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
+// sortMetricDataByDimensionsValue(
+// reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
+// EXPECT_GT((int)gaugeMetrics.data_size(), 1);
+//
+// auto data = gaugeMetrics.data(0);
+// EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* subsystem name field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
+// EXPECT_EQ(3, data.bucket_info_size());
+//
+// EXPECT_EQ(1, data.bucket_info(0).atom_size());
+// EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
+// EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
+// EXPECT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
+// EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+// EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty());
+// EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0);
+//
+// EXPECT_EQ(1, data.bucket_info(1).atom_size());
+// EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 100,
+// data.bucket_info(1).elapsed_timestamp_nanos(0));
+// EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
+// EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
+// EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
+// EXPECT_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty());
+// EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 0);
+//
+// EXPECT_EQ(2, data.bucket_info(2).atom_size());
+// EXPECT_EQ(2, data.bucket_info(2).elapsed_timestamp_nanos_size());
+// EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs + 1,
+// data.bucket_info(2).elapsed_timestamp_nanos(0));
+// EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs + 10,
+// data.bucket_info(2).elapsed_timestamp_nanos(1));
+// EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
+// EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
+// EXPECT_TRUE(data.bucket_info(2).atom(0).subsystem_sleep_state().subsystem_name().empty());
+// EXPECT_GT(data.bucket_info(2).atom(0).subsystem_sleep_state().time_millis(), 0);
+// EXPECT_TRUE(data.bucket_info(2).atom(1).subsystem_sleep_state().subsystem_name().empty());
+// EXPECT_GT(data.bucket_info(2).atom(1).subsystem_sleep_state().time_millis(), 0);
+//}
+//
+//
+//TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvent_LateAlarm) {
+// auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE);
+// int64_t baseTimeNs = getElapsedRealtimeNs();
+// int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
+// int64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
+//
+// ConfigKey cfgKey;
+// auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
+// SharedRefBase::make<FakeSubsystemSleepCallback>(),
+// ATOM_TAG);
+// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+// processor->mPullerManager->ForceClearPullerCache();
+//
+// int startBucketNum = processor->mMetricsManagers.begin()->second->
+// mAllMetricProducers[0]->getCurrentBucketNum();
+// EXPECT_GT(startBucketNum, (int64_t)0);
+//
+// // When creating the config, the gauge metric producer should register the alarm at the
+// // end of the current bucket.
+// EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
+// EXPECT_EQ(bucketSizeNs,
+// processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
+// int64_t& nextPullTimeNs =
+// processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
+// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, nextPullTimeNs);
+//
+// auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+// configAddedTimeNs + 55);
+// processor->OnLogEvent(screenOffEvent.get());
+//
+// auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+// configAddedTimeNs + bucketSizeNs + 10);
+// processor->OnLogEvent(screenOnEvent.get());
+//
+// // Pulling alarm arrives one bucket size late.
+// processor->informPullAlarmFired(nextPullTimeNs + bucketSizeNs);
+// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs, nextPullTimeNs);
+//
+// screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+// configAddedTimeNs + 3 * bucketSizeNs + 11);
+// processor->OnLogEvent(screenOffEvent.get());
+//
+// // Pulling alarm arrives more than one bucket size late.
+// processor->informPullAlarmFired(nextPullTimeNs + bucketSizeNs + 12);
+// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, nextPullTimeNs);
+//
+// ConfigMetricsReportList reports;
+// vector<uint8_t> buffer;
+// processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
+// ADB_DUMP, FAST, &buffer);
+// EXPECT_TRUE(buffer.size() > 0);
+// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+// backfillDimensionPath(&reports);
+// backfillStringInReport(&reports);
+// backfillStartEndTimestamp(&reports);
+// EXPECT_EQ(1, reports.reports_size());
+// EXPECT_EQ(1, reports.reports(0).metrics_size());
+// StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
+// sortMetricDataByDimensionsValue(
+// reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
+// EXPECT_GT((int)gaugeMetrics.data_size(), 1);
+//
+// auto data = gaugeMetrics.data(0);
+// EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* subsystem name field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
+// EXPECT_EQ(3, data.bucket_info_size());
+//
+// EXPECT_EQ(1, data.bucket_info(0).atom_size());
+// EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
+// EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
+// EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+// EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty());
+// EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0);
+//
+// EXPECT_EQ(1, data.bucket_info(1).atom_size());
+// EXPECT_EQ(configAddedTimeNs + 3 * bucketSizeNs + 11,
+// data.bucket_info(1).elapsed_timestamp_nanos(0));
+// EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
+// EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
+// EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
+// EXPECT_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty());
+// EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 0);
+//
+// EXPECT_EQ(1, data.bucket_info(2).atom_size());
+// EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
+// EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs + 12,
+// data.bucket_info(2).elapsed_timestamp_nanos(0));
+// EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
+// EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
+// EXPECT_TRUE(data.bucket_info(2).atom(0).subsystem_sleep_state().subsystem_name().empty());
+// EXPECT_GT(data.bucket_info(2).atom(0).subsystem_sleep_state().time_millis(), 0);
+//}
+//
+//TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsWithActivation) {
+// auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE, /*useCondition=*/false);
+//
+// int64_t baseTimeNs = getElapsedRealtimeNs();
+// int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
+// int64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
+//
+// auto batterySaverStartMatcher = CreateBatterySaverModeStartAtomMatcher();
+// *config.add_atom_matcher() = batterySaverStartMatcher;
+// const int64_t ttlNs = 2 * bucketSizeNs; // Two buckets.
+// auto metric_activation = config.add_metric_activation();
+// metric_activation->set_metric_id(metricId);
+// metric_activation->set_activation_type(ACTIVATE_IMMEDIATELY);
+// auto event_activation = metric_activation->add_event_activation();
+// event_activation->set_atom_matcher_id(batterySaverStartMatcher.id());
+// event_activation->set_ttl_seconds(ttlNs / 1000000000);
+//
+// ConfigKey cfgKey;
+// auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
+// SharedRefBase::make<FakeSubsystemSleepCallback>(),
+// ATOM_TAG);
+// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+// processor->mPullerManager->ForceClearPullerCache();
+//
+// int startBucketNum = processor->mMetricsManagers.begin()->second->
+// mAllMetricProducers[0]->getCurrentBucketNum();
+// EXPECT_GT(startBucketNum, (int64_t)0);
+// EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
+//
+// // When creating the config, the gauge metric producer should register the alarm at the
+// // end of the current bucket.
+// EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
+// EXPECT_EQ(bucketSizeNs,
+// processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
+// int64_t& nextPullTimeNs =
+// processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
+// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, nextPullTimeNs);
+//
+// // Pulling alarm arrives on time and reset the sequential pulling alarm.
+// // Event should not be kept.
+// processor->informPullAlarmFired(nextPullTimeNs + 1); // 15 mins + 1 ns.
+// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, nextPullTimeNs);
+// EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
+//
+// // Activate the metric. A pull occurs upon activation.
+// const int64_t activationNs = configAddedTimeNs + bucketSizeNs + (2 * 1000 * 1000); // 2 millis.
+// auto batterySaverOnEvent = CreateBatterySaverOnEvent(activationNs);
+// processor->OnLogEvent(batterySaverOnEvent.get()); // 15 mins + 2 ms.
+// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
+//
+// // This event should be kept. 2 total.
+// processor->informPullAlarmFired(nextPullTimeNs + 1); // 20 mins + 1 ns.
+// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs,
+// nextPullTimeNs);
+//
+// // This event should be kept. 3 total.
+// processor->informPullAlarmFired(nextPullTimeNs + 2); // 25 mins + 2 ns.
+// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, nextPullTimeNs);
+//
+// // Create random event to deactivate metric.
+// auto deactivationEvent = CreateScreenBrightnessChangedEvent(50, activationNs + ttlNs + 1);
+// processor->OnLogEvent(deactivationEvent.get());
+// EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
+//
+// // Event should not be kept. 3 total.
+// processor->informPullAlarmFired(nextPullTimeNs + 3);
+// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, nextPullTimeNs);
+//
+// processor->informPullAlarmFired(nextPullTimeNs + 2);
+//
+// ConfigMetricsReportList reports;
+// vector<uint8_t> buffer;
+// processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
+// ADB_DUMP, FAST, &buffer);
+// EXPECT_TRUE(buffer.size() > 0);
+// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+// backfillDimensionPath(&reports);
+// backfillStringInReport(&reports);
+// backfillStartEndTimestamp(&reports);
+// EXPECT_EQ(1, reports.reports_size());
+// EXPECT_EQ(1, reports.reports(0).metrics_size());
+// StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
+// sortMetricDataByDimensionsValue(
+// reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
+// EXPECT_GT((int)gaugeMetrics.data_size(), 0);
+//
+// auto data = gaugeMetrics.data(0);
+// EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* subsystem name field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
+// EXPECT_EQ(3, data.bucket_info_size());
+//
+// auto bucketInfo = data.bucket_info(0);
+// EXPECT_EQ(1, bucketInfo.atom_size());
+// EXPECT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
+// EXPECT_EQ(activationNs, bucketInfo.elapsed_timestamp_nanos(0));
+// EXPECT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
+// EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
+// EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
+// EXPECT_TRUE(bucketInfo.atom(0).subsystem_sleep_state().subsystem_name().empty());
+// EXPECT_GT(bucketInfo.atom(0).subsystem_sleep_state().time_millis(), 0);
+//
+// bucketInfo = data.bucket_info(1);
+// EXPECT_EQ(1, bucketInfo.atom_size());
+// EXPECT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
+// EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs + 1, bucketInfo.elapsed_timestamp_nanos(0));
+// EXPECT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
+// EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
+// EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
+// EXPECT_TRUE(bucketInfo.atom(0).subsystem_sleep_state().subsystem_name().empty());
+// EXPECT_GT(bucketInfo.atom(0).subsystem_sleep_state().time_millis(), 0);
+//
+// bucketInfo = data.bucket_info(2);
+// EXPECT_EQ(1, bucketInfo.atom_size());
+// EXPECT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
+// EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs + 2, bucketInfo.elapsed_timestamp_nanos(0));
+// EXPECT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
+// EXPECT_EQ(MillisToNano(NanoToMillis(baseTimeNs + 5 * bucketSizeNs)),
+// bucketInfo.start_bucket_elapsed_nanos());
+// EXPECT_EQ(MillisToNano(NanoToMillis(activationNs + ttlNs + 1)),
+// bucketInfo.end_bucket_elapsed_nanos());
+// EXPECT_TRUE(bucketInfo.atom(0).subsystem_sleep_state().subsystem_name().empty());
+// EXPECT_GT(bucketInfo.atom(0).subsystem_sleep_state().time_millis(), 0);
+//}
TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsNoCondition) {
auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE, /*useCondition=*/false);
diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
index cd80310..ef6e753 100644
--- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
+++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
@@ -68,219 +68,221 @@
return config;
}
-std::unique_ptr<LogEvent> CreateAppStartOccurredEvent(
- const int uid, const string& pkg_name, AppStartOccurred::TransitionType type,
- const string& activity_name, const string& calling_pkg_name, const bool is_instant_app,
- int64_t activity_start_msec, uint64_t timestampNs) {
- auto logEvent = std::make_unique<LogEvent>(
- android::util::APP_START_OCCURRED, timestampNs);
- logEvent->write(uid);
- logEvent->write(pkg_name);
- logEvent->write(type);
- logEvent->write(activity_name);
- logEvent->write(calling_pkg_name);
- logEvent->write(is_instant_app);
- logEvent->write(activity_start_msec);
- logEvent->init();
- return logEvent;
-}
+// TODO(b/149590301): Update this helper to use new socket schema.
+//std::unique_ptr<LogEvent> CreateAppStartOccurredEvent(
+// const int uid, const string& pkg_name, AppStartOccurred::TransitionType type,
+// const string& activity_name, const string& calling_pkg_name, const bool is_instant_app,
+// int64_t activity_start_msec, uint64_t timestampNs) {
+// auto logEvent = std::make_unique<LogEvent>(
+// android::util::APP_START_OCCURRED, timestampNs);
+// logEvent->write(uid);
+// logEvent->write(pkg_name);
+// logEvent->write(type);
+// logEvent->write(activity_name);
+// logEvent->write(calling_pkg_name);
+// logEvent->write(is_instant_app);
+// logEvent->write(activity_start_msec);
+// logEvent->init();
+// return logEvent;
+//}
} // namespace
-TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent) {
- for (const auto& sampling_type :
- { GaugeMetric::FIRST_N_SAMPLES, GaugeMetric:: RANDOM_ONE_SAMPLE }) {
- auto config = CreateStatsdConfigForPushedEvent(sampling_type);
- int64_t bucketStartTimeNs = 10000000000;
- int64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
-
- ConfigKey cfgKey;
- auto processor = CreateStatsLogProcessor(
- bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
- EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
- EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-
- int appUid1 = 123;
- int appUid2 = 456;
- std::vector<std::unique_ptr<LogEvent>> events;
- events.push_back(CreateMoveToBackgroundEvent(appUid1, bucketStartTimeNs + 15));
- events.push_back(CreateMoveToForegroundEvent(
- appUid1, bucketStartTimeNs + bucketSizeNs + 250));
- events.push_back(CreateMoveToBackgroundEvent(
- appUid1, bucketStartTimeNs + bucketSizeNs + 350));
- events.push_back(CreateMoveToForegroundEvent(
- appUid1, bucketStartTimeNs + 2 * bucketSizeNs + 100));
-
-
- events.push_back(CreateAppStartOccurredEvent(
- appUid1, "app1", AppStartOccurred::WARM, "activity_name1", "calling_pkg_name1",
- true /*is_instant_app*/, 101 /*activity_start_msec*/, bucketStartTimeNs + 10));
- events.push_back(CreateAppStartOccurredEvent(
- appUid1, "app1", AppStartOccurred::HOT, "activity_name2", "calling_pkg_name2",
- true /*is_instant_app*/, 102 /*activity_start_msec*/, bucketStartTimeNs + 20));
- events.push_back(CreateAppStartOccurredEvent(
- appUid1, "app1", AppStartOccurred::COLD, "activity_name3", "calling_pkg_name3",
- true /*is_instant_app*/, 103 /*activity_start_msec*/, bucketStartTimeNs + 30));
- events.push_back(CreateAppStartOccurredEvent(
- appUid1, "app1", AppStartOccurred::WARM, "activity_name4", "calling_pkg_name4",
- true /*is_instant_app*/, 104 /*activity_start_msec*/,
- bucketStartTimeNs + bucketSizeNs + 30));
- events.push_back(CreateAppStartOccurredEvent(
- appUid1, "app1", AppStartOccurred::COLD, "activity_name5", "calling_pkg_name5",
- true /*is_instant_app*/, 105 /*activity_start_msec*/,
- bucketStartTimeNs + 2 * bucketSizeNs));
- events.push_back(CreateAppStartOccurredEvent(
- appUid1, "app1", AppStartOccurred::HOT, "activity_name6", "calling_pkg_name6",
- false /*is_instant_app*/, 106 /*activity_start_msec*/,
- bucketStartTimeNs + 2 * bucketSizeNs + 10));
-
- events.push_back(CreateMoveToBackgroundEvent(
- appUid2, bucketStartTimeNs + bucketSizeNs + 10));
- events.push_back(CreateAppStartOccurredEvent(
- appUid2, "app2", AppStartOccurred::COLD, "activity_name7", "calling_pkg_name7",
- true /*is_instant_app*/, 201 /*activity_start_msec*/,
- bucketStartTimeNs + 2 * bucketSizeNs + 10));
-
- sortLogEventsByTimestamp(&events);
-
- for (const auto& event : events) {
- processor->OnLogEvent(event.get());
- }
- ConfigMetricsReportList reports;
- vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 3 * bucketSizeNs, false, true,
- ADB_DUMP, FAST, &buffer);
- EXPECT_TRUE(buffer.size() > 0);
- EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
- backfillDimensionPath(&reports);
- backfillStringInReport(&reports);
- backfillStartEndTimestamp(&reports);
- EXPECT_EQ(1, reports.reports_size());
- EXPECT_EQ(1, reports.reports(0).metrics_size());
- StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
- sortMetricDataByDimensionsValue(
- reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
- EXPECT_EQ(2, gaugeMetrics.data_size());
-
- auto data = gaugeMetrics.data(0);
- EXPECT_EQ(android::util::APP_START_OCCURRED, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* uid field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_EQ(appUid1, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
- EXPECT_EQ(3, data.bucket_info_size());
- if (sampling_type == GaugeMetric::FIRST_N_SAMPLES) {
- EXPECT_EQ(2, data.bucket_info(0).atom_size());
- EXPECT_EQ(2, data.bucket_info(0).elapsed_timestamp_nanos_size());
- EXPECT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
- EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
- data.bucket_info(0).end_bucket_elapsed_nanos());
- EXPECT_EQ(AppStartOccurred::HOT,
- data.bucket_info(0).atom(0).app_start_occurred().type());
- EXPECT_EQ("activity_name2",
- data.bucket_info(0).atom(0).app_start_occurred().activity_name());
- EXPECT_EQ(102L,
- data.bucket_info(0).atom(0).app_start_occurred().activity_start_millis());
- EXPECT_EQ(AppStartOccurred::COLD,
- data.bucket_info(0).atom(1).app_start_occurred().type());
- EXPECT_EQ("activity_name3",
- data.bucket_info(0).atom(1).app_start_occurred().activity_name());
- EXPECT_EQ(103L,
- data.bucket_info(0).atom(1).app_start_occurred().activity_start_millis());
-
- EXPECT_EQ(1, data.bucket_info(1).atom_size());
- EXPECT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size());
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
- data.bucket_info(1).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
- data.bucket_info(1).end_bucket_elapsed_nanos());
- EXPECT_EQ(AppStartOccurred::WARM,
- data.bucket_info(1).atom(0).app_start_occurred().type());
- EXPECT_EQ("activity_name4",
- data.bucket_info(1).atom(0).app_start_occurred().activity_name());
- EXPECT_EQ(104L,
- data.bucket_info(1).atom(0).app_start_occurred().activity_start_millis());
-
- EXPECT_EQ(2, data.bucket_info(2).atom_size());
- EXPECT_EQ(2, data.bucket_info(2).elapsed_timestamp_nanos_size());
- EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
- data.bucket_info(2).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
- data.bucket_info(2).end_bucket_elapsed_nanos());
- EXPECT_EQ(AppStartOccurred::COLD,
- data.bucket_info(2).atom(0).app_start_occurred().type());
- EXPECT_EQ("activity_name5",
- data.bucket_info(2).atom(0).app_start_occurred().activity_name());
- EXPECT_EQ(105L,
- data.bucket_info(2).atom(0).app_start_occurred().activity_start_millis());
- EXPECT_EQ(AppStartOccurred::HOT,
- data.bucket_info(2).atom(1).app_start_occurred().type());
- EXPECT_EQ("activity_name6",
- data.bucket_info(2).atom(1).app_start_occurred().activity_name());
- EXPECT_EQ(106L,
- data.bucket_info(2).atom(1).app_start_occurred().activity_start_millis());
- } else {
- EXPECT_EQ(1, data.bucket_info(0).atom_size());
- EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
- EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
- data.bucket_info(0).end_bucket_elapsed_nanos());
- EXPECT_EQ(AppStartOccurred::HOT,
- data.bucket_info(0).atom(0).app_start_occurred().type());
- EXPECT_EQ("activity_name2",
- data.bucket_info(0).atom(0).app_start_occurred().activity_name());
- EXPECT_EQ(102L,
- data.bucket_info(0).atom(0).app_start_occurred().activity_start_millis());
-
- EXPECT_EQ(1, data.bucket_info(1).atom_size());
- EXPECT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size());
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
- data.bucket_info(1).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
- data.bucket_info(1).end_bucket_elapsed_nanos());
- EXPECT_EQ(AppStartOccurred::WARM,
- data.bucket_info(1).atom(0).app_start_occurred().type());
- EXPECT_EQ("activity_name4",
- data.bucket_info(1).atom(0).app_start_occurred().activity_name());
- EXPECT_EQ(104L,
- data.bucket_info(1).atom(0).app_start_occurred().activity_start_millis());
-
- EXPECT_EQ(1, data.bucket_info(2).atom_size());
- EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
- EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
- data.bucket_info(2).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
- data.bucket_info(2).end_bucket_elapsed_nanos());
- EXPECT_EQ(AppStartOccurred::COLD,
- data.bucket_info(2).atom(0).app_start_occurred().type());
- EXPECT_EQ("activity_name5",
- data.bucket_info(2).atom(0).app_start_occurred().activity_name());
- EXPECT_EQ(105L,
- data.bucket_info(2).atom(0).app_start_occurred().activity_start_millis());
- }
-
- data = gaugeMetrics.data(1);
-
- EXPECT_EQ(data.dimensions_in_what().field(), android::util::APP_START_OCCURRED);
- EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
- EXPECT_EQ(1 /* uid field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_EQ(appUid2, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).atom_size());
- EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
- EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
- data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
- data.bucket_info(0).end_bucket_elapsed_nanos());
- EXPECT_EQ(AppStartOccurred::COLD, data.bucket_info(0).atom(0).app_start_occurred().type());
- EXPECT_EQ("activity_name7",
- data.bucket_info(0).atom(0).app_start_occurred().activity_name());
- EXPECT_EQ(201L, data.bucket_info(0).atom(0).app_start_occurred().activity_start_millis());
- }
-}
+// TODO(b/149590301): Update this test to use new socket schema.
+//TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent) {
+// for (const auto& sampling_type :
+// { GaugeMetric::FIRST_N_SAMPLES, GaugeMetric:: RANDOM_ONE_SAMPLE }) {
+// auto config = CreateStatsdConfigForPushedEvent(sampling_type);
+// int64_t bucketStartTimeNs = 10000000000;
+// int64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
+//
+// ConfigKey cfgKey;
+// auto processor = CreateStatsLogProcessor(
+// bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+//
+// int appUid1 = 123;
+// int appUid2 = 456;
+// std::vector<std::unique_ptr<LogEvent>> events;
+// events.push_back(CreateMoveToBackgroundEvent(appUid1, bucketStartTimeNs + 15));
+// events.push_back(CreateMoveToForegroundEvent(
+// appUid1, bucketStartTimeNs + bucketSizeNs + 250));
+// events.push_back(CreateMoveToBackgroundEvent(
+// appUid1, bucketStartTimeNs + bucketSizeNs + 350));
+// events.push_back(CreateMoveToForegroundEvent(
+// appUid1, bucketStartTimeNs + 2 * bucketSizeNs + 100));
+//
+//
+// events.push_back(CreateAppStartOccurredEvent(
+// appUid1, "app1", AppStartOccurred::WARM, "activity_name1", "calling_pkg_name1",
+// true /*is_instant_app*/, 101 /*activity_start_msec*/, bucketStartTimeNs + 10));
+// events.push_back(CreateAppStartOccurredEvent(
+// appUid1, "app1", AppStartOccurred::HOT, "activity_name2", "calling_pkg_name2",
+// true /*is_instant_app*/, 102 /*activity_start_msec*/, bucketStartTimeNs + 20));
+// events.push_back(CreateAppStartOccurredEvent(
+// appUid1, "app1", AppStartOccurred::COLD, "activity_name3", "calling_pkg_name3",
+// true /*is_instant_app*/, 103 /*activity_start_msec*/, bucketStartTimeNs + 30));
+// events.push_back(CreateAppStartOccurredEvent(
+// appUid1, "app1", AppStartOccurred::WARM, "activity_name4", "calling_pkg_name4",
+// true /*is_instant_app*/, 104 /*activity_start_msec*/,
+// bucketStartTimeNs + bucketSizeNs + 30));
+// events.push_back(CreateAppStartOccurredEvent(
+// appUid1, "app1", AppStartOccurred::COLD, "activity_name5", "calling_pkg_name5",
+// true /*is_instant_app*/, 105 /*activity_start_msec*/,
+// bucketStartTimeNs + 2 * bucketSizeNs));
+// events.push_back(CreateAppStartOccurredEvent(
+// appUid1, "app1", AppStartOccurred::HOT, "activity_name6", "calling_pkg_name6",
+// false /*is_instant_app*/, 106 /*activity_start_msec*/,
+// bucketStartTimeNs + 2 * bucketSizeNs + 10));
+//
+// events.push_back(CreateMoveToBackgroundEvent(
+// appUid2, bucketStartTimeNs + bucketSizeNs + 10));
+// events.push_back(CreateAppStartOccurredEvent(
+// appUid2, "app2", AppStartOccurred::COLD, "activity_name7", "calling_pkg_name7",
+// true /*is_instant_app*/, 201 /*activity_start_msec*/,
+// bucketStartTimeNs + 2 * bucketSizeNs + 10));
+//
+// sortLogEventsByTimestamp(&events);
+//
+// for (const auto& event : events) {
+// processor->OnLogEvent(event.get());
+// }
+// ConfigMetricsReportList reports;
+// vector<uint8_t> buffer;
+// processor->onDumpReport(cfgKey, bucketStartTimeNs + 3 * bucketSizeNs, false, true,
+// ADB_DUMP, FAST, &buffer);
+// EXPECT_TRUE(buffer.size() > 0);
+// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+// backfillDimensionPath(&reports);
+// backfillStringInReport(&reports);
+// backfillStartEndTimestamp(&reports);
+// EXPECT_EQ(1, reports.reports_size());
+// EXPECT_EQ(1, reports.reports(0).metrics_size());
+// StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
+// sortMetricDataByDimensionsValue(
+// reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
+// EXPECT_EQ(2, gaugeMetrics.data_size());
+//
+// auto data = gaugeMetrics.data(0);
+// EXPECT_EQ(android::util::APP_START_OCCURRED, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* uid field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_EQ(appUid1, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+// EXPECT_EQ(3, data.bucket_info_size());
+// if (sampling_type == GaugeMetric::FIRST_N_SAMPLES) {
+// EXPECT_EQ(2, data.bucket_info(0).atom_size());
+// EXPECT_EQ(2, data.bucket_info(0).elapsed_timestamp_nanos_size());
+// EXPECT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
+// EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
+// data.bucket_info(0).end_bucket_elapsed_nanos());
+// EXPECT_EQ(AppStartOccurred::HOT,
+// data.bucket_info(0).atom(0).app_start_occurred().type());
+// EXPECT_EQ("activity_name2",
+// data.bucket_info(0).atom(0).app_start_occurred().activity_name());
+// EXPECT_EQ(102L,
+// data.bucket_info(0).atom(0).app_start_occurred().activity_start_millis());
+// EXPECT_EQ(AppStartOccurred::COLD,
+// data.bucket_info(0).atom(1).app_start_occurred().type());
+// EXPECT_EQ("activity_name3",
+// data.bucket_info(0).atom(1).app_start_occurred().activity_name());
+// EXPECT_EQ(103L,
+// data.bucket_info(0).atom(1).app_start_occurred().activity_start_millis());
+//
+// EXPECT_EQ(1, data.bucket_info(1).atom_size());
+// EXPECT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size());
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
+// data.bucket_info(1).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+// data.bucket_info(1).end_bucket_elapsed_nanos());
+// EXPECT_EQ(AppStartOccurred::WARM,
+// data.bucket_info(1).atom(0).app_start_occurred().type());
+// EXPECT_EQ("activity_name4",
+// data.bucket_info(1).atom(0).app_start_occurred().activity_name());
+// EXPECT_EQ(104L,
+// data.bucket_info(1).atom(0).app_start_occurred().activity_start_millis());
+//
+// EXPECT_EQ(2, data.bucket_info(2).atom_size());
+// EXPECT_EQ(2, data.bucket_info(2).elapsed_timestamp_nanos_size());
+// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+// data.bucket_info(2).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
+// data.bucket_info(2).end_bucket_elapsed_nanos());
+// EXPECT_EQ(AppStartOccurred::COLD,
+// data.bucket_info(2).atom(0).app_start_occurred().type());
+// EXPECT_EQ("activity_name5",
+// data.bucket_info(2).atom(0).app_start_occurred().activity_name());
+// EXPECT_EQ(105L,
+// data.bucket_info(2).atom(0).app_start_occurred().activity_start_millis());
+// EXPECT_EQ(AppStartOccurred::HOT,
+// data.bucket_info(2).atom(1).app_start_occurred().type());
+// EXPECT_EQ("activity_name6",
+// data.bucket_info(2).atom(1).app_start_occurred().activity_name());
+// EXPECT_EQ(106L,
+// data.bucket_info(2).atom(1).app_start_occurred().activity_start_millis());
+// } else {
+// EXPECT_EQ(1, data.bucket_info(0).atom_size());
+// EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
+// EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
+// data.bucket_info(0).end_bucket_elapsed_nanos());
+// EXPECT_EQ(AppStartOccurred::HOT,
+// data.bucket_info(0).atom(0).app_start_occurred().type());
+// EXPECT_EQ("activity_name2",
+// data.bucket_info(0).atom(0).app_start_occurred().activity_name());
+// EXPECT_EQ(102L,
+// data.bucket_info(0).atom(0).app_start_occurred().activity_start_millis());
+//
+// EXPECT_EQ(1, data.bucket_info(1).atom_size());
+// EXPECT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size());
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
+// data.bucket_info(1).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+// data.bucket_info(1).end_bucket_elapsed_nanos());
+// EXPECT_EQ(AppStartOccurred::WARM,
+// data.bucket_info(1).atom(0).app_start_occurred().type());
+// EXPECT_EQ("activity_name4",
+// data.bucket_info(1).atom(0).app_start_occurred().activity_name());
+// EXPECT_EQ(104L,
+// data.bucket_info(1).atom(0).app_start_occurred().activity_start_millis());
+//
+// EXPECT_EQ(1, data.bucket_info(2).atom_size());
+// EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
+// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+// data.bucket_info(2).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
+// data.bucket_info(2).end_bucket_elapsed_nanos());
+// EXPECT_EQ(AppStartOccurred::COLD,
+// data.bucket_info(2).atom(0).app_start_occurred().type());
+// EXPECT_EQ("activity_name5",
+// data.bucket_info(2).atom(0).app_start_occurred().activity_name());
+// EXPECT_EQ(105L,
+// data.bucket_info(2).atom(0).app_start_occurred().activity_start_millis());
+// }
+//
+// data = gaugeMetrics.data(1);
+//
+// EXPECT_EQ(data.dimensions_in_what().field(), android::util::APP_START_OCCURRED);
+// EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
+// EXPECT_EQ(1 /* uid field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_EQ(appUid2, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).atom_size());
+// EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
+// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+// data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
+// data.bucket_info(0).end_bucket_elapsed_nanos());
+// EXPECT_EQ(AppStartOccurred::COLD, data.bucket_info(0).atom(0).app_start_occurred().type());
+// EXPECT_EQ("activity_name7",
+// data.bucket_info(0).atom(0).app_start_occurred().activity_name());
+// EXPECT_EQ(201L, data.bucket_info(0).atom(0).app_start_occurred().activity_start_millis());
+// }
+//}
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
diff --git a/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp b/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp
index b6a6492..f3f7df77 100644
--- a/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp
@@ -233,1608 +233,1609 @@
} // namespace
-TEST(MetricActivationE2eTest, TestCountMetric) {
- auto config = CreateStatsdConfig();
-
- int64_t bucketStartTimeNs = NS_PER_SEC * 10; // 10 secs
- int64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000LL * 1000LL;
-
- int uid = 12345;
- int64_t cfgId = 98765;
- ConfigKey cfgKey(uid, cfgId);
-
- sp<UidMap> m = new UidMap();
- sp<StatsPullerManager> pullerManager = new StatsPullerManager();
- sp<AlarmMonitor> anomalyAlarmMonitor;
- sp<AlarmMonitor> subscriberAlarmMonitor;
- vector<int64_t> activeConfigsBroadcast;
-
- long timeBase1 = 1;
- int broadcastCount = 0;
- StatsLogProcessor processor(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor,
- bucketStartTimeNs, [](const ConfigKey& key) { return true; },
- [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid,
- const vector<int64_t>& activeConfigs) {
- broadcastCount++;
- EXPECT_EQ(broadcastUid, uid);
- activeConfigsBroadcast.clear();
- activeConfigsBroadcast.insert(activeConfigsBroadcast.end(),
- activeConfigs.begin(), activeConfigs.end());
- return true;
- });
-
- processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config);
-
- EXPECT_EQ(processor.mMetricsManagers.size(), 1u);
- sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
- EXPECT_TRUE(metricsManager->isConfigValid());
- EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
- sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
- auto& eventActivationMap = metricProducer->mEventActivationMap;
-
- EXPECT_FALSE(metricsManager->isActive());
- EXPECT_FALSE(metricProducer->mIsActive);
- // Two activations: one is triggered by battery saver mode (tracker index 0), the other is
- // triggered by screen on event (tracker index 2).
- EXPECT_EQ(eventActivationMap.size(), 2u);
- EXPECT_TRUE(eventActivationMap.find(0) != eventActivationMap.end());
- EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, 0);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-
- std::unique_ptr<LogEvent> event;
-
- event = CreateAppCrashEvent(111, bucketStartTimeNs + 5);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + 5);
- EXPECT_FALSE(metricsManager->isActive());
- EXPECT_FALSE(metricProducer->mIsActive);
- EXPECT_EQ(broadcastCount, 0);
-
- // Activated by battery save mode.
- event = CreateBatterySaverOnEvent(bucketStartTimeNs + 10);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + 10);
- EXPECT_TRUE(metricsManager->isActive());
- EXPECT_TRUE(metricProducer->mIsActive);
- EXPECT_EQ(broadcastCount, 1);
- EXPECT_EQ(activeConfigsBroadcast.size(), 1);
- EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-
- // First processed event.
- event = CreateAppCrashEvent(222, bucketStartTimeNs + 15);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + 15);
-
- // Activated by screen on event.
- event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
- bucketStartTimeNs + 20);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + 20);
- EXPECT_TRUE(metricsManager->isActive());
- EXPECT_TRUE(metricProducer->mIsActive);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-
- // 2nd processed event.
- // The activation by screen_on event expires, but the one by battery save mode is still active.
- event = CreateAppCrashEvent(333, bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
- EXPECT_TRUE(metricsManager->isActive());
- EXPECT_TRUE(metricProducer->mIsActive);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- // No new broadcast since the config should still be active.
- EXPECT_EQ(broadcastCount, 1);
-
- // 3rd processed event.
- event = CreateAppCrashEvent(444, bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
-
- // All activations expired.
- event = CreateAppCrashEvent(555, bucketStartTimeNs + NS_PER_SEC * 60 * 8);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 8);
- EXPECT_FALSE(metricsManager->isActive());
- EXPECT_FALSE(metricProducer->mIsActive);
- // New broadcast since the config is no longer active.
- EXPECT_EQ(broadcastCount, 2);
- EXPECT_EQ(activeConfigsBroadcast.size(), 0);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-
- // Re-activate metric via screen on.
- event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
- bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- EXPECT_TRUE(metricsManager->isActive());
- EXPECT_TRUE(metricProducer->mIsActive);
- EXPECT_EQ(broadcastCount, 3);
- EXPECT_EQ(activeConfigsBroadcast.size(), 1);
- EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-
- // 4th processed event.
- event = CreateAppCrashEvent(666, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
-
- ConfigMetricsReportList reports;
- vector<uint8_t> buffer;
- processor.onDumpReport(cfgKey, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 1, false, true,
- ADB_DUMP, FAST, &buffer);
- EXPECT_TRUE(buffer.size() > 0);
- EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
- backfillDimensionPath(&reports);
- backfillStartEndTimestamp(&reports);
- EXPECT_EQ(1, reports.reports_size());
- EXPECT_EQ(1, reports.reports(0).metrics_size());
- EXPECT_EQ(4, reports.reports(0).metrics(0).count_metrics().data_size());
-
- StatsLogReport::CountMetricDataWrapper countMetrics;
- sortMetricDataByDimensionsValue(
- reports.reports(0).metrics(0).count_metrics(), &countMetrics);
- EXPECT_EQ(4, countMetrics.data_size());
-
- auto data = countMetrics.data(0);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* uid field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_EQ(222, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
- EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
-
- data = countMetrics.data(1);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* uid field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_EQ(333, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
- EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
-
- data = countMetrics.data(2);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* uid field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_EQ(444, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
- // Partial bucket as metric is deactivated.
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 8,
- data.bucket_info(0).end_bucket_elapsed_nanos());
-
- data = countMetrics.data(3);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* uid field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_EQ(666, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
- EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
- data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
- data.bucket_info(0).end_bucket_elapsed_nanos());
-}
-
-TEST(MetricActivationE2eTest, TestCountMetricWithOneDeactivation) {
- auto config = CreateStatsdConfigWithOneDeactivation();
-
- int64_t bucketStartTimeNs = NS_PER_SEC * 10; // 10 secs
- int64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000LL * 1000LL;
-
- int uid = 12345;
- int64_t cfgId = 98765;
- ConfigKey cfgKey(uid, cfgId);
-
- sp<UidMap> m = new UidMap();
- sp<StatsPullerManager> pullerManager = new StatsPullerManager();
- sp<AlarmMonitor> anomalyAlarmMonitor;
- sp<AlarmMonitor> subscriberAlarmMonitor;
- vector<int64_t> activeConfigsBroadcast;
-
- long timeBase1 = 1;
- int broadcastCount = 0;
- StatsLogProcessor processor(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor,
- bucketStartTimeNs, [](const ConfigKey& key) { return true; },
- [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid,
- const vector<int64_t>& activeConfigs) {
- broadcastCount++;
- EXPECT_EQ(broadcastUid, uid);
- activeConfigsBroadcast.clear();
- activeConfigsBroadcast.insert(activeConfigsBroadcast.end(),
- activeConfigs.begin(), activeConfigs.end());
- return true;
- });
-
- processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config);
-
- EXPECT_EQ(processor.mMetricsManagers.size(), 1u);
- sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
- EXPECT_TRUE(metricsManager->isConfigValid());
- EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
- sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
- auto& eventActivationMap = metricProducer->mEventActivationMap;
- auto& eventDeactivationMap = metricProducer->mEventDeactivationMap;
-
- EXPECT_FALSE(metricsManager->isActive());
- EXPECT_FALSE(metricProducer->mIsActive);
- // Two activations: one is triggered by battery saver mode (tracker index 0), the other is
- // triggered by screen on event (tracker index 2).
- EXPECT_EQ(eventActivationMap.size(), 2u);
- EXPECT_TRUE(eventActivationMap.find(0) != eventActivationMap.end());
- EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, 0);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap.size(), 1u);
- EXPECT_TRUE(eventDeactivationMap.find(3) != eventDeactivationMap.end());
- EXPECT_EQ(eventDeactivationMap[3].size(), 1u);
- EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-
- std::unique_ptr<LogEvent> event;
-
- event = CreateAppCrashEvent(111, bucketStartTimeNs + 5);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + 5);
- EXPECT_FALSE(metricsManager->isActive());
- EXPECT_FALSE(metricProducer->mIsActive);
- EXPECT_EQ(broadcastCount, 0);
-
- // Activated by battery save mode.
- event = CreateBatterySaverOnEvent(bucketStartTimeNs + 10);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + 10);
- EXPECT_TRUE(metricsManager->isActive());
- EXPECT_TRUE(metricProducer->mIsActive);
- EXPECT_EQ(broadcastCount, 1);
- EXPECT_EQ(activeConfigsBroadcast.size(), 1);
- EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-
- // First processed event.
- event = CreateAppCrashEvent(222, bucketStartTimeNs + 15);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + 15);
-
- // Activated by screen on event.
- event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
- bucketStartTimeNs + 20);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + 20);
- EXPECT_TRUE(metricsManager->isActive());
- EXPECT_TRUE(metricProducer->mIsActive);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-
- // 2nd processed event.
- // The activation by screen_on event expires, but the one by battery save mode is still active.
- event = CreateAppCrashEvent(333, bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
- processor.OnLogEvent(event.get(),bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
- EXPECT_TRUE(metricsManager->isActive());
- EXPECT_TRUE(metricProducer->mIsActive);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
- // No new broadcast since the config should still be active.
- EXPECT_EQ(broadcastCount, 1);
-
- // 3rd processed event.
- event = CreateAppCrashEvent(444, bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
-
- // All activations expired.
- event = CreateAppCrashEvent(555, bucketStartTimeNs + NS_PER_SEC * 60 * 8);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 8);
- EXPECT_FALSE(metricsManager->isActive());
- EXPECT_FALSE(metricProducer->mIsActive);
- // New broadcast since the config is no longer active.
- EXPECT_EQ(broadcastCount, 2);
- EXPECT_EQ(activeConfigsBroadcast.size(), 0);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-
- // Re-activate metric via screen on.
- event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
- bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- EXPECT_TRUE(metricsManager->isActive());
- EXPECT_TRUE(metricProducer->mIsActive);
- EXPECT_EQ(broadcastCount, 3);
- EXPECT_EQ(activeConfigsBroadcast.size(), 1);
- EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-
- // 4th processed event.
- event = CreateAppCrashEvent(666, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
-
- // Re-enable battery saver mode activation.
- event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
- EXPECT_TRUE(metricsManager->isActive());
- EXPECT_TRUE(metricProducer->mIsActive);
- EXPECT_EQ(broadcastCount, 3);
- EXPECT_EQ(activeConfigsBroadcast.size(), 1);
- EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-
- // 5th processed event.
- event = CreateAppCrashEvent(777, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
-
- // Cancel battery saver mode activation.
- event = CreateScreenBrightnessChangedEvent(64, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 60);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 60);
- EXPECT_TRUE(metricsManager->isActive());
- EXPECT_TRUE(metricProducer->mIsActive);
- EXPECT_EQ(broadcastCount, 3);
- EXPECT_EQ(activeConfigsBroadcast.size(), 1);
- EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-
- // Screen-on activation expired.
- event = CreateAppCrashEvent(888, bucketStartTimeNs + NS_PER_SEC * 60 * 13);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 13);
- EXPECT_FALSE(metricsManager->isActive());
- EXPECT_FALSE(metricProducer->mIsActive);
- // New broadcast since the config is no longer active.
- EXPECT_EQ(broadcastCount, 4);
- EXPECT_EQ(activeConfigsBroadcast.size(), 0);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-
- event = CreateAppCrashEvent(999, bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
-
- // Re-enable battery saver mode activation.
- event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
- EXPECT_TRUE(metricsManager->isActive());
- EXPECT_TRUE(metricProducer->mIsActive);
- EXPECT_EQ(broadcastCount, 5);
- EXPECT_EQ(activeConfigsBroadcast.size(), 1);
- EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-
- // Cancel battery saver mode activation.
- event = CreateScreenBrightnessChangedEvent(140, bucketStartTimeNs + NS_PER_SEC * 60 * 16);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 16);
- EXPECT_FALSE(metricsManager->isActive());
- EXPECT_FALSE(metricProducer->mIsActive);
- EXPECT_EQ(broadcastCount, 6);
- EXPECT_EQ(activeConfigsBroadcast.size(), 0);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-
- ConfigMetricsReportList reports;
- vector<uint8_t> buffer;
- processor.onDumpReport(cfgKey, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 1, false, true,
- ADB_DUMP, FAST, &buffer);
- EXPECT_TRUE(buffer.size() > 0);
- EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
- backfillDimensionPath(&reports);
- backfillStartEndTimestamp(&reports);
- EXPECT_EQ(1, reports.reports_size());
- EXPECT_EQ(1, reports.reports(0).metrics_size());
- EXPECT_EQ(5, reports.reports(0).metrics(0).count_metrics().data_size());
-
- StatsLogReport::CountMetricDataWrapper countMetrics;
- sortMetricDataByDimensionsValue(
- reports.reports(0).metrics(0).count_metrics(), &countMetrics);
- EXPECT_EQ(5, countMetrics.data_size());
-
- auto data = countMetrics.data(0);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* uid field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_EQ(222, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
- EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
-
- data = countMetrics.data(1);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* uid field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_EQ(333, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
- EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
-
- data = countMetrics.data(2);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* uid field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_EQ(444, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
- // Partial bucket as metric is deactivated.
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 8,
- data.bucket_info(0).end_bucket_elapsed_nanos());
-
- data = countMetrics.data(3);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* uid field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_EQ(666, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
- EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
- data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 13,
- data.bucket_info(0).end_bucket_elapsed_nanos());
-
- data = countMetrics.data(4);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* uid field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_EQ(777, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
- EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
- data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 13,
- data.bucket_info(0).end_bucket_elapsed_nanos());
-}
-
-TEST(MetricActivationE2eTest, TestCountMetricWithTwoDeactivations) {
- auto config = CreateStatsdConfigWithTwoDeactivations();
-
- int64_t bucketStartTimeNs = NS_PER_SEC * 10; // 10 secs
- int64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000LL * 1000LL;
-
- int uid = 12345;
- int64_t cfgId = 98765;
- ConfigKey cfgKey(uid, cfgId);
-
- sp<UidMap> m = new UidMap();
- sp<StatsPullerManager> pullerManager = new StatsPullerManager();
- sp<AlarmMonitor> anomalyAlarmMonitor;
- sp<AlarmMonitor> subscriberAlarmMonitor;
- vector<int64_t> activeConfigsBroadcast;
-
- long timeBase1 = 1;
- int broadcastCount = 0;
- StatsLogProcessor processor(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor,
- bucketStartTimeNs, [](const ConfigKey& key) { return true; },
- [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid,
- const vector<int64_t>& activeConfigs) {
- broadcastCount++;
- EXPECT_EQ(broadcastUid, uid);
- activeConfigsBroadcast.clear();
- activeConfigsBroadcast.insert(activeConfigsBroadcast.end(),
- activeConfigs.begin(), activeConfigs.end());
- return true;
- });
-
- processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config);
-
- EXPECT_EQ(processor.mMetricsManagers.size(), 1u);
- sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
- EXPECT_TRUE(metricsManager->isConfigValid());
- EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
- sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
- auto& eventActivationMap = metricProducer->mEventActivationMap;
- auto& eventDeactivationMap = metricProducer->mEventDeactivationMap;
-
- EXPECT_FALSE(metricsManager->isActive());
- EXPECT_FALSE(metricProducer->mIsActive);
- // Two activations: one is triggered by battery saver mode (tracker index 0), the other is
- // triggered by screen on event (tracker index 2).
- EXPECT_EQ(eventActivationMap.size(), 2u);
- EXPECT_TRUE(eventActivationMap.find(0) != eventActivationMap.end());
- EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, 0);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap.size(), 2u);
- EXPECT_TRUE(eventDeactivationMap.find(3) != eventDeactivationMap.end());
- EXPECT_TRUE(eventDeactivationMap.find(4) != eventDeactivationMap.end());
- EXPECT_EQ(eventDeactivationMap[3].size(), 1u);
- EXPECT_EQ(eventDeactivationMap[4].size(), 1u);
- EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
- EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
-
- std::unique_ptr<LogEvent> event;
-
- event = CreateAppCrashEvent(111, bucketStartTimeNs + 5);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + 5);
- EXPECT_FALSE(metricsManager->isActive());
- EXPECT_FALSE(metricProducer->mIsActive);
- EXPECT_EQ(broadcastCount, 0);
-
- // Activated by battery save mode.
- event = CreateBatterySaverOnEvent(bucketStartTimeNs + 10);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + 10);
- EXPECT_TRUE(metricsManager->isActive());
- EXPECT_TRUE(metricProducer->mIsActive);
- EXPECT_EQ(broadcastCount, 1);
- EXPECT_EQ(activeConfigsBroadcast.size(), 1);
- EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
- EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
-
- // First processed event.
- event = CreateAppCrashEvent(222, bucketStartTimeNs + 15);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + 15);
-
- // Activated by screen on event.
- event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
- bucketStartTimeNs + 20);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + 20);
- EXPECT_TRUE(metricsManager->isActive());
- EXPECT_TRUE(metricProducer->mIsActive);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
- EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
-
- // 2nd processed event.
- // The activation by screen_on event expires, but the one by battery save mode is still active.
- event = CreateAppCrashEvent(333, bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
- EXPECT_TRUE(metricsManager->isActive());
- EXPECT_TRUE(metricProducer->mIsActive);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
- EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
- // No new broadcast since the config should still be active.
- EXPECT_EQ(broadcastCount, 1);
-
- // 3rd processed event.
- event = CreateAppCrashEvent(444, bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
-
- // All activations expired.
- event = CreateAppCrashEvent(555, bucketStartTimeNs + NS_PER_SEC * 60 * 8);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 8);
- EXPECT_FALSE(metricsManager->isActive());
- EXPECT_FALSE(metricProducer->mIsActive);
- // New broadcast since the config is no longer active.
- EXPECT_EQ(broadcastCount, 2);
- EXPECT_EQ(activeConfigsBroadcast.size(), 0);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
- EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
-
- // Re-activate metric via screen on.
- event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
- bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- EXPECT_TRUE(metricsManager->isActive());
- EXPECT_TRUE(metricProducer->mIsActive);
- EXPECT_EQ(broadcastCount, 3);
- EXPECT_EQ(activeConfigsBroadcast.size(), 1);
- EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
- EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
-
- // 4th processed event.
- event = CreateAppCrashEvent(666, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
-
- // Re-enable battery saver mode activation.
- event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
- EXPECT_TRUE(metricsManager->isActive());
- EXPECT_TRUE(metricProducer->mIsActive);
- EXPECT_EQ(broadcastCount, 3);
- EXPECT_EQ(activeConfigsBroadcast.size(), 1);
- EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
- EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
-
- // 5th processed event.
- event = CreateAppCrashEvent(777, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
-
- // Cancel battery saver mode and screen on activation.
- event = CreateScreenBrightnessChangedEvent(64, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 60);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 60);
- EXPECT_FALSE(metricsManager->isActive());
- EXPECT_FALSE(metricProducer->mIsActive);
- // New broadcast since the config is no longer active.
- EXPECT_EQ(broadcastCount, 4);
- EXPECT_EQ(activeConfigsBroadcast.size(), 0);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
- EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
-
- // Screen-on activation expired.
- event = CreateAppCrashEvent(888, bucketStartTimeNs + NS_PER_SEC * 60 * 13);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 13);
- EXPECT_FALSE(metricsManager->isActive());
- EXPECT_FALSE(metricProducer->mIsActive);
- EXPECT_EQ(broadcastCount, 4);
- EXPECT_EQ(activeConfigsBroadcast.size(), 0);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
- EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
-
- event = CreateAppCrashEvent(999, bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
-
- // Re-enable battery saver mode activation.
- event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
- EXPECT_TRUE(metricsManager->isActive());
- EXPECT_TRUE(metricProducer->mIsActive);
- EXPECT_EQ(broadcastCount, 5);
- EXPECT_EQ(activeConfigsBroadcast.size(), 1);
- EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
- EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
-
- // Cancel battery saver mode and screen on activation.
- event = CreateScreenBrightnessChangedEvent(140, bucketStartTimeNs + NS_PER_SEC * 60 * 16);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 16);
- EXPECT_FALSE(metricsManager->isActive());
- EXPECT_FALSE(metricProducer->mIsActive);
- EXPECT_EQ(broadcastCount, 6);
- EXPECT_EQ(activeConfigsBroadcast.size(), 0);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
- EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
-
- ConfigMetricsReportList reports;
- vector<uint8_t> buffer;
- processor.onDumpReport(cfgKey, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 1, false, true,
- ADB_DUMP, FAST, &buffer);
- EXPECT_TRUE(buffer.size() > 0);
- EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
- backfillDimensionPath(&reports);
- backfillStartEndTimestamp(&reports);
- EXPECT_EQ(1, reports.reports_size());
- EXPECT_EQ(1, reports.reports(0).metrics_size());
- EXPECT_EQ(5, reports.reports(0).metrics(0).count_metrics().data_size());
-
- StatsLogReport::CountMetricDataWrapper countMetrics;
- sortMetricDataByDimensionsValue(
- reports.reports(0).metrics(0).count_metrics(), &countMetrics);
- EXPECT_EQ(5, countMetrics.data_size());
-
- auto data = countMetrics.data(0);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* uid field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_EQ(222, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
- EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
-
- data = countMetrics.data(1);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* uid field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_EQ(333, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
- EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
-
- data = countMetrics.data(2);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* uid field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_EQ(444, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
- // Partial bucket as metric is deactivated.
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 8,
- data.bucket_info(0).end_bucket_elapsed_nanos());
-
- data = countMetrics.data(3);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* uid field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_EQ(666, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
- EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
- data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 11,
- data.bucket_info(0).end_bucket_elapsed_nanos());
-
- data = countMetrics.data(4);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* uid field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_EQ(777, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
- EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
- data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 11,
- data.bucket_info(0).end_bucket_elapsed_nanos());
-}
-
-TEST(MetricActivationE2eTest, TestCountMetricWithSameDeactivation) {
- auto config = CreateStatsdConfigWithSameDeactivations();
-
- int64_t bucketStartTimeNs = NS_PER_SEC * 10; // 10 secs
- int64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000LL * 1000LL;
-
- int uid = 12345;
- int64_t cfgId = 98765;
- ConfigKey cfgKey(uid, cfgId);
-
- sp<UidMap> m = new UidMap();
- sp<StatsPullerManager> pullerManager = new StatsPullerManager();
- sp<AlarmMonitor> anomalyAlarmMonitor;
- sp<AlarmMonitor> subscriberAlarmMonitor;
- vector<int64_t> activeConfigsBroadcast;
-
- long timeBase1 = 1;
- int broadcastCount = 0;
- StatsLogProcessor processor(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor,
- bucketStartTimeNs, [](const ConfigKey& key) { return true; },
- [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid,
- const vector<int64_t>& activeConfigs) {
- broadcastCount++;
- EXPECT_EQ(broadcastUid, uid);
- activeConfigsBroadcast.clear();
- activeConfigsBroadcast.insert(activeConfigsBroadcast.end(),
- activeConfigs.begin(), activeConfigs.end());
- return true;
- });
-
- processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config);
-
- EXPECT_EQ(processor.mMetricsManagers.size(), 1u);
- sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
- EXPECT_TRUE(metricsManager->isConfigValid());
- EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
- sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
- auto& eventActivationMap = metricProducer->mEventActivationMap;
- auto& eventDeactivationMap = metricProducer->mEventDeactivationMap;
-
- EXPECT_FALSE(metricsManager->isActive());
- EXPECT_FALSE(metricProducer->mIsActive);
- // Two activations: one is triggered by battery saver mode (tracker index 0), the other is
- // triggered by screen on event (tracker index 2).
- EXPECT_EQ(eventActivationMap.size(), 2u);
- EXPECT_TRUE(eventActivationMap.find(0) != eventActivationMap.end());
- EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, 0);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap.size(), 1u);
- EXPECT_TRUE(eventDeactivationMap.find(3) != eventDeactivationMap.end());
- EXPECT_EQ(eventDeactivationMap[3].size(), 2u);
- EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
- EXPECT_EQ(eventDeactivationMap[3][1], eventActivationMap[2]);
- EXPECT_EQ(broadcastCount, 0);
-
- std::unique_ptr<LogEvent> event;
-
- // Event that should be ignored.
- event = CreateAppCrashEvent(111, bucketStartTimeNs + 1);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + 1);
-
- // Activate metric via screen on for 2 minutes.
- event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, bucketStartTimeNs + 10);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + 10);
- EXPECT_TRUE(metricsManager->isActive());
- EXPECT_TRUE(metricProducer->mIsActive);
- EXPECT_EQ(broadcastCount, 1);
- EXPECT_EQ(activeConfigsBroadcast.size(), 1);
- EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 10);
-
- // 1st processed event.
- event = CreateAppCrashEvent(222, bucketStartTimeNs + 15);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + 15);
-
- // Enable battery saver mode activation for 5 minutes.
- event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 + 10);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 + 10);
- EXPECT_TRUE(metricsManager->isActive());
- EXPECT_TRUE(metricProducer->mIsActive);
- EXPECT_EQ(broadcastCount, 1);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 + 10);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 10);
-
- // 2nd processed event.
- event = CreateAppCrashEvent(333, bucketStartTimeNs + NS_PER_SEC * 60 + 40);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 + 40);
-
- // Cancel battery saver mode and screen on activation.
- int64_t firstDeactivation = bucketStartTimeNs + NS_PER_SEC * 61;
- event = CreateScreenBrightnessChangedEvent(64, firstDeactivation);
- processor.OnLogEvent(event.get(), firstDeactivation);
- EXPECT_FALSE(metricsManager->isActive());
- EXPECT_FALSE(metricProducer->mIsActive);
- // New broadcast since the config is no longer active.
- EXPECT_EQ(broadcastCount, 2);
- EXPECT_EQ(activeConfigsBroadcast.size(), 0);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-
- // Should be ignored
- event = CreateAppCrashEvent(444, bucketStartTimeNs + NS_PER_SEC * 61 + 80);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 61 + 80);
-
- // Re-enable battery saver mode activation.
- event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 15);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 15);
- EXPECT_TRUE(metricsManager->isActive());
- EXPECT_TRUE(metricProducer->mIsActive);
- EXPECT_EQ(broadcastCount, 3);
- EXPECT_EQ(activeConfigsBroadcast.size(), 1);
- EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 15);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-
- // 3rd processed event.
- event = CreateAppCrashEvent(555, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 80);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 80);
-
- // Cancel battery saver mode activation.
- int64_t secondDeactivation = bucketStartTimeNs + NS_PER_SEC * 60 * 13;
- event = CreateScreenBrightnessChangedEvent(140, secondDeactivation);
- processor.OnLogEvent(event.get(), secondDeactivation);
- EXPECT_FALSE(metricsManager->isActive());
- EXPECT_FALSE(metricProducer->mIsActive);
- EXPECT_EQ(broadcastCount, 4);
- EXPECT_EQ(activeConfigsBroadcast.size(), 0);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-
- // Should be ignored.
- event = CreateAppCrashEvent(666, bucketStartTimeNs + NS_PER_SEC * 60 * 13 + 80);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 13 + 80);
-
- ConfigMetricsReportList reports;
- vector<uint8_t> buffer;
- processor.onDumpReport(cfgKey, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 1, false, true,
- ADB_DUMP, FAST, &buffer);
- EXPECT_TRUE(buffer.size() > 0);
- EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
- backfillDimensionPath(&reports);
- backfillStartEndTimestamp(&reports);
- EXPECT_EQ(1, reports.reports_size());
- EXPECT_EQ(1, reports.reports(0).metrics_size());
- EXPECT_EQ(3, reports.reports(0).metrics(0).count_metrics().data_size());
-
- StatsLogReport::CountMetricDataWrapper countMetrics;
- sortMetricDataByDimensionsValue(
- reports.reports(0).metrics(0).count_metrics(), &countMetrics);
- EXPECT_EQ(3, countMetrics.data_size());
-
- auto data = countMetrics.data(0);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* uid field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_EQ(222, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
- EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(firstDeactivation, data.bucket_info(0).end_bucket_elapsed_nanos());
-
- data = countMetrics.data(1);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* uid field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_EQ(333, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
- EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(firstDeactivation, data.bucket_info(0).end_bucket_elapsed_nanos());
-
- data = countMetrics.data(2);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* uid field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_EQ(555, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
- // Partial bucket as metric is deactivated.
- EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(secondDeactivation, data.bucket_info(0).end_bucket_elapsed_nanos());
-}
-
-TEST(MetricActivationE2eTest, TestCountMetricWithTwoMetricsTwoDeactivations) {
- auto config = CreateStatsdConfigWithTwoMetricsTwoDeactivations();
-
- int64_t bucketStartTimeNs = NS_PER_SEC * 10; // 10 secs
- int64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000LL * 1000LL;
-
- int uid = 12345;
- int64_t cfgId = 98765;
- ConfigKey cfgKey(uid, cfgId);
-
- sp<UidMap> m = new UidMap();
- sp<StatsPullerManager> pullerManager = new StatsPullerManager();
- sp<AlarmMonitor> anomalyAlarmMonitor;
- sp<AlarmMonitor> subscriberAlarmMonitor;
- vector<int64_t> activeConfigsBroadcast;
-
- long timeBase1 = 1;
- int broadcastCount = 0;
- StatsLogProcessor processor(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor,
- bucketStartTimeNs, [](const ConfigKey& key) { return true; },
- [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid,
- const vector<int64_t>& activeConfigs) {
- broadcastCount++;
- EXPECT_EQ(broadcastUid, uid);
- activeConfigsBroadcast.clear();
- activeConfigsBroadcast.insert(activeConfigsBroadcast.end(),
- activeConfigs.begin(), activeConfigs.end());
- return true;
- });
-
- processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config);
-
- EXPECT_EQ(processor.mMetricsManagers.size(), 1u);
- sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
- EXPECT_TRUE(metricsManager->isConfigValid());
- EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 2);
- sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
- auto& eventActivationMap = metricProducer->mEventActivationMap;
- auto& eventDeactivationMap = metricProducer->mEventDeactivationMap;
- sp<MetricProducer> metricProducer2 = metricsManager->mAllMetricProducers[1];
- auto& eventActivationMap2 = metricProducer2->mEventActivationMap;
- auto& eventDeactivationMap2 = metricProducer2->mEventDeactivationMap;
-
- EXPECT_FALSE(metricsManager->isActive());
- EXPECT_FALSE(metricProducer->mIsActive);
- EXPECT_FALSE(metricProducer2->mIsActive);
- // Two activations: one is triggered by battery saver mode (tracker index 0), the other is
- // triggered by screen on event (tracker index 2).
- EXPECT_EQ(eventActivationMap.size(), 2u);
- EXPECT_TRUE(eventActivationMap.find(0) != eventActivationMap.end());
- EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, 0);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap.size(), 2u);
- EXPECT_TRUE(eventDeactivationMap.find(3) != eventDeactivationMap.end());
- EXPECT_TRUE(eventDeactivationMap.find(4) != eventDeactivationMap.end());
- EXPECT_EQ(eventDeactivationMap[3].size(), 1u);
- EXPECT_EQ(eventDeactivationMap[4].size(), 1u);
- EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
- EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
-
- EXPECT_EQ(eventActivationMap2.size(), 2u);
- EXPECT_TRUE(eventActivationMap2.find(0) != eventActivationMap2.end());
- EXPECT_TRUE(eventActivationMap2.find(2) != eventActivationMap2.end());
- EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap2[0]->start_ns, 0);
- EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap2[2]->start_ns, 0);
- EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap2.size(), 2u);
- EXPECT_TRUE(eventDeactivationMap2.find(3) != eventDeactivationMap2.end());
- EXPECT_TRUE(eventDeactivationMap2.find(4) != eventDeactivationMap2.end());
- EXPECT_EQ(eventDeactivationMap[3].size(), 1u);
- EXPECT_EQ(eventDeactivationMap[4].size(), 1u);
- EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
- EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
-
- std::unique_ptr<LogEvent> event;
-
- event = CreateAppCrashEvent(111, bucketStartTimeNs + 5);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + 5);
- event = CreateMoveToForegroundEvent(1111, bucketStartTimeNs + 5);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + 5);
- EXPECT_FALSE(metricsManager->isActive());
- EXPECT_FALSE(metricProducer->mIsActive);
- EXPECT_FALSE(metricProducer2->mIsActive);
- EXPECT_EQ(broadcastCount, 0);
-
- // Activated by battery save mode.
- event = CreateBatterySaverOnEvent(bucketStartTimeNs + 10);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + 10);
- EXPECT_TRUE(metricsManager->isActive());
- EXPECT_EQ(broadcastCount, 1);
- EXPECT_EQ(activeConfigsBroadcast.size(), 1);
- EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
- EXPECT_TRUE(metricProducer->mIsActive);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
- EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
- EXPECT_TRUE(metricProducer2->mIsActive);
- EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + 10);
- EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap2[2]->start_ns, 0);
- EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
- EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
-
- // First processed event.
- event = CreateAppCrashEvent(222, bucketStartTimeNs + 15);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + 15);
- event = CreateMoveToForegroundEvent(2222, bucketStartTimeNs + 15);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + 15);
-
- // Activated by screen on event.
- event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
- bucketStartTimeNs + 20);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + 20);
- EXPECT_TRUE(metricsManager->isActive());
- EXPECT_TRUE(metricProducer->mIsActive);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
- EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
- EXPECT_TRUE(metricProducer2->mIsActive);
- EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + 10);
- EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + 20);
- EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
- EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
-
- // 2nd processed event.
- // The activation by screen_on event expires, but the one by battery save mode is still active.
- event = CreateAppCrashEvent(333, bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
- event = CreateMoveToForegroundEvent(3333, bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
- EXPECT_TRUE(metricsManager->isActive());
- EXPECT_TRUE(metricProducer->mIsActive);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
- EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
- EXPECT_TRUE(metricProducer2->mIsActive);
- EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + 10);
- EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + 20);
- EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
- EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
- // No new broadcast since the config should still be active.
- EXPECT_EQ(broadcastCount, 1);
-
- // 3rd processed event.
- event = CreateAppCrashEvent(444, bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
- event = CreateMoveToForegroundEvent(4444, bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
-
- // All activations expired.
- event = CreateAppCrashEvent(555, bucketStartTimeNs + NS_PER_SEC * 60 * 8);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 8);
- event = CreateMoveToForegroundEvent(5555, bucketStartTimeNs + NS_PER_SEC * 60 * 8);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 8);
- EXPECT_FALSE(metricsManager->isActive());
- // New broadcast since the config is no longer active.
- EXPECT_EQ(broadcastCount, 2);
- EXPECT_EQ(activeConfigsBroadcast.size(), 0);
- EXPECT_FALSE(metricProducer->mIsActive);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
- EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
- EXPECT_FALSE(metricProducer2->mIsActive);
- EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + 10);
- EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + 20);
- EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
- EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
-
- // Re-activate metric via screen on.
- event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
- bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- EXPECT_TRUE(metricsManager->isActive());
- EXPECT_EQ(broadcastCount, 3);
- EXPECT_EQ(activeConfigsBroadcast.size(), 1);
- EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
- EXPECT_TRUE(metricProducer->mIsActive);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
- EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
- EXPECT_TRUE(metricProducer2->mIsActive);
- EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + 10);
- EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
- EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
-
- // 4th processed event.
- event = CreateAppCrashEvent(666, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
- event = CreateMoveToForegroundEvent(6666, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
-
- // Re-enable battery saver mode activation.
- event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
- EXPECT_TRUE(metricsManager->isActive());
- EXPECT_EQ(broadcastCount, 3);
- EXPECT_EQ(activeConfigsBroadcast.size(), 1);
- EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
- EXPECT_TRUE(metricProducer->mIsActive);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
- EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
- EXPECT_TRUE(metricProducer2->mIsActive);
- EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
- EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
- EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
-
- // 5th processed event.
- event = CreateAppCrashEvent(777, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
- event = CreateMoveToForegroundEvent(7777, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
-
- // Cancel battery saver mode and screen on activation.
- event = CreateScreenBrightnessChangedEvent(64, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 60);
- processor.OnLogEvent(event.get(),bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 60);
- EXPECT_FALSE(metricsManager->isActive());
- // New broadcast since the config is no longer active.
- EXPECT_EQ(broadcastCount, 4);
- EXPECT_EQ(activeConfigsBroadcast.size(), 0);
- EXPECT_FALSE(metricProducer->mIsActive);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
- EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
- EXPECT_FALSE(metricProducer2->mIsActive);
- EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
- EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
- EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
-
- // Screen-on activation expired.
- event = CreateAppCrashEvent(888, bucketStartTimeNs + NS_PER_SEC * 60 * 13);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 13);
- event = CreateMoveToForegroundEvent(8888, bucketStartTimeNs + NS_PER_SEC * 60 * 13);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 13);
- EXPECT_FALSE(metricsManager->isActive());
- EXPECT_EQ(broadcastCount, 4);
- EXPECT_EQ(activeConfigsBroadcast.size(), 0);
- EXPECT_FALSE(metricProducer->mIsActive);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
- EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
- EXPECT_FALSE(metricProducer2->mIsActive);
- EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
- EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
- EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
-
- event = CreateAppCrashEvent(999, bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
- event = CreateMoveToForegroundEvent(9999, bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
-
- // Re-enable battery saver mode activation.
- event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
- processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
- EXPECT_TRUE(metricsManager->isActive());
- EXPECT_EQ(broadcastCount, 5);
- EXPECT_EQ(activeConfigsBroadcast.size(), 1);
- EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
- EXPECT_TRUE(metricProducer->mIsActive);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
- EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
- EXPECT_TRUE(metricProducer2->mIsActive);
- EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kActive);
- EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
- EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
- EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
-
- // Cancel battery saver mode and screen on activation.
- event = CreateScreenBrightnessChangedEvent(140, bucketStartTimeNs + NS_PER_SEC * 60 * 16);
- processor.OnLogEvent(event.get(),bucketStartTimeNs + NS_PER_SEC * 60 * 16);
- EXPECT_FALSE(metricsManager->isActive());
- EXPECT_EQ(broadcastCount, 6);
- EXPECT_EQ(activeConfigsBroadcast.size(), 0);
- EXPECT_FALSE(metricProducer->mIsActive);
- EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
- EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
- EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
- EXPECT_FALSE(metricProducer2->mIsActive);
- EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
- EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
- EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kNotActive);
- EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
- EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
- EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
-
- ConfigMetricsReportList reports;
- vector<uint8_t> buffer;
- processor.onDumpReport(cfgKey, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 1, false, true,
- ADB_DUMP, FAST, &buffer);
- EXPECT_TRUE(buffer.size() > 0);
- EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
- backfillDimensionPath(&reports);
- backfillStartEndTimestamp(&reports);
- EXPECT_EQ(1, reports.reports_size());
- EXPECT_EQ(2, reports.reports(0).metrics_size());
- EXPECT_EQ(5, reports.reports(0).metrics(0).count_metrics().data_size());
- EXPECT_EQ(5, reports.reports(0).metrics(1).count_metrics().data_size());
-
- StatsLogReport::CountMetricDataWrapper countMetrics;
-
- sortMetricDataByDimensionsValue(
- reports.reports(0).metrics(0).count_metrics(), &countMetrics);
- EXPECT_EQ(5, countMetrics.data_size());
-
- auto data = countMetrics.data(0);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* uid field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_EQ(222, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
- EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
-
- data = countMetrics.data(1);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* uid field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_EQ(333, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
- EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
-
- data = countMetrics.data(2);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* uid field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_EQ(444, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
- // Partial bucket as metric is deactivated.
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 8,
- data.bucket_info(0).end_bucket_elapsed_nanos());
-
- data = countMetrics.data(3);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* uid field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_EQ(666, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
- EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
- data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 11,
- data.bucket_info(0).end_bucket_elapsed_nanos());
-
- data = countMetrics.data(4);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* uid field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_EQ(777, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
- EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
- data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 11,
- data.bucket_info(0).end_bucket_elapsed_nanos());
-
-
- countMetrics.clear_data();
- sortMetricDataByDimensionsValue(
- reports.reports(0).metrics(1).count_metrics(), &countMetrics);
- EXPECT_EQ(5, countMetrics.data_size());
-
- data = countMetrics.data(0);
- EXPECT_EQ(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* uid field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_EQ(2222, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
- EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
-
- data = countMetrics.data(1);
- EXPECT_EQ(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* uid field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_EQ(3333, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
- EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
-
- data = countMetrics.data(2);
- EXPECT_EQ(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* uid field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_EQ(4444, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
- // Partial bucket as metric is deactivated.
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 8,
- data.bucket_info(0).end_bucket_elapsed_nanos());
-
- data = countMetrics.data(3);
- EXPECT_EQ(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* uid field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_EQ(6666, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
- EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
- data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 11,
- data.bucket_info(0).end_bucket_elapsed_nanos());
-
- data = countMetrics.data(4);
- EXPECT_EQ(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* uid field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_EQ(7777, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(1, data.bucket_info(0).count());
- EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
- data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 11,
- data.bucket_info(0).end_bucket_elapsed_nanos());
-}
+// TODO(b/149590301): Update these tests to use new socket schema.
+//TEST(MetricActivationE2eTest, TestCountMetric) {
+// auto config = CreateStatsdConfig();
+//
+// int64_t bucketStartTimeNs = NS_PER_SEC * 10; // 10 secs
+// int64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000LL * 1000LL;
+//
+// int uid = 12345;
+// int64_t cfgId = 98765;
+// ConfigKey cfgKey(uid, cfgId);
+//
+// sp<UidMap> m = new UidMap();
+// sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+// sp<AlarmMonitor> anomalyAlarmMonitor;
+// sp<AlarmMonitor> subscriberAlarmMonitor;
+// vector<int64_t> activeConfigsBroadcast;
+//
+// long timeBase1 = 1;
+// int broadcastCount = 0;
+// StatsLogProcessor processor(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor,
+// bucketStartTimeNs, [](const ConfigKey& key) { return true; },
+// [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid,
+// const vector<int64_t>& activeConfigs) {
+// broadcastCount++;
+// EXPECT_EQ(broadcastUid, uid);
+// activeConfigsBroadcast.clear();
+// activeConfigsBroadcast.insert(activeConfigsBroadcast.end(),
+// activeConfigs.begin(), activeConfigs.end());
+// return true;
+// });
+//
+// processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config);
+//
+// EXPECT_EQ(processor.mMetricsManagers.size(), 1u);
+// sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
+// EXPECT_TRUE(metricsManager->isConfigValid());
+// EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+// sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+// auto& eventActivationMap = metricProducer->mEventActivationMap;
+//
+// EXPECT_FALSE(metricsManager->isActive());
+// EXPECT_FALSE(metricProducer->mIsActive);
+// // Two activations: one is triggered by battery saver mode (tracker index 0), the other is
+// // triggered by screen on event (tracker index 2).
+// EXPECT_EQ(eventActivationMap.size(), 2u);
+// EXPECT_TRUE(eventActivationMap.find(0) != eventActivationMap.end());
+// EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, 0);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//
+// std::unique_ptr<LogEvent> event;
+//
+// event = CreateAppCrashEvent(111, bucketStartTimeNs + 5);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + 5);
+// EXPECT_FALSE(metricsManager->isActive());
+// EXPECT_FALSE(metricProducer->mIsActive);
+// EXPECT_EQ(broadcastCount, 0);
+//
+// // Activated by battery save mode.
+// event = CreateBatterySaverOnEvent(bucketStartTimeNs + 10);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + 10);
+// EXPECT_TRUE(metricsManager->isActive());
+// EXPECT_TRUE(metricProducer->mIsActive);
+// EXPECT_EQ(broadcastCount, 1);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+// EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//
+// // First processed event.
+// event = CreateAppCrashEvent(222, bucketStartTimeNs + 15);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + 15);
+//
+// // Activated by screen on event.
+// event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+// bucketStartTimeNs + 20);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + 20);
+// EXPECT_TRUE(metricsManager->isActive());
+// EXPECT_TRUE(metricProducer->mIsActive);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//
+// // 2nd processed event.
+// // The activation by screen_on event expires, but the one by battery save mode is still active.
+// event = CreateAppCrashEvent(333, bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
+// EXPECT_TRUE(metricsManager->isActive());
+// EXPECT_TRUE(metricProducer->mIsActive);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// // No new broadcast since the config should still be active.
+// EXPECT_EQ(broadcastCount, 1);
+//
+// // 3rd processed event.
+// event = CreateAppCrashEvent(444, bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
+//
+// // All activations expired.
+// event = CreateAppCrashEvent(555, bucketStartTimeNs + NS_PER_SEC * 60 * 8);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 8);
+// EXPECT_FALSE(metricsManager->isActive());
+// EXPECT_FALSE(metricProducer->mIsActive);
+// // New broadcast since the config is no longer active.
+// EXPECT_EQ(broadcastCount, 2);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//
+// // Re-activate metric via screen on.
+// event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+// bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+// EXPECT_TRUE(metricsManager->isActive());
+// EXPECT_TRUE(metricProducer->mIsActive);
+// EXPECT_EQ(broadcastCount, 3);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+// EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//
+// // 4th processed event.
+// event = CreateAppCrashEvent(666, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
+//
+// ConfigMetricsReportList reports;
+// vector<uint8_t> buffer;
+// processor.onDumpReport(cfgKey, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 1, false, true,
+// ADB_DUMP, FAST, &buffer);
+// EXPECT_TRUE(buffer.size() > 0);
+// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+// backfillDimensionPath(&reports);
+// backfillStartEndTimestamp(&reports);
+// EXPECT_EQ(1, reports.reports_size());
+// EXPECT_EQ(1, reports.reports(0).metrics_size());
+// EXPECT_EQ(4, reports.reports(0).metrics(0).count_metrics().data_size());
+//
+// StatsLogReport::CountMetricDataWrapper countMetrics;
+// sortMetricDataByDimensionsValue(
+// reports.reports(0).metrics(0).count_metrics(), &countMetrics);
+// EXPECT_EQ(4, countMetrics.data_size());
+//
+// auto data = countMetrics.data(0);
+// EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* uid field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_EQ(222, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+// EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+// data = countMetrics.data(1);
+// EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* uid field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_EQ(333, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+// EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+// data = countMetrics.data(2);
+// EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* uid field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_EQ(444, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+// // Partial bucket as metric is deactivated.
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 8,
+// data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+// data = countMetrics.data(3);
+// EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* uid field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_EQ(666, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+// data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
+// data.bucket_info(0).end_bucket_elapsed_nanos());
+//}
+//
+//TEST(MetricActivationE2eTest, TestCountMetricWithOneDeactivation) {
+// auto config = CreateStatsdConfigWithOneDeactivation();
+//
+// int64_t bucketStartTimeNs = NS_PER_SEC * 10; // 10 secs
+// int64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000LL * 1000LL;
+//
+// int uid = 12345;
+// int64_t cfgId = 98765;
+// ConfigKey cfgKey(uid, cfgId);
+//
+// sp<UidMap> m = new UidMap();
+// sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+// sp<AlarmMonitor> anomalyAlarmMonitor;
+// sp<AlarmMonitor> subscriberAlarmMonitor;
+// vector<int64_t> activeConfigsBroadcast;
+//
+// long timeBase1 = 1;
+// int broadcastCount = 0;
+// StatsLogProcessor processor(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor,
+// bucketStartTimeNs, [](const ConfigKey& key) { return true; },
+// [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid,
+// const vector<int64_t>& activeConfigs) {
+// broadcastCount++;
+// EXPECT_EQ(broadcastUid, uid);
+// activeConfigsBroadcast.clear();
+// activeConfigsBroadcast.insert(activeConfigsBroadcast.end(),
+// activeConfigs.begin(), activeConfigs.end());
+// return true;
+// });
+//
+// processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config);
+//
+// EXPECT_EQ(processor.mMetricsManagers.size(), 1u);
+// sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
+// EXPECT_TRUE(metricsManager->isConfigValid());
+// EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+// sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+// auto& eventActivationMap = metricProducer->mEventActivationMap;
+// auto& eventDeactivationMap = metricProducer->mEventDeactivationMap;
+//
+// EXPECT_FALSE(metricsManager->isActive());
+// EXPECT_FALSE(metricProducer->mIsActive);
+// // Two activations: one is triggered by battery saver mode (tracker index 0), the other is
+// // triggered by screen on event (tracker index 2).
+// EXPECT_EQ(eventActivationMap.size(), 2u);
+// EXPECT_TRUE(eventActivationMap.find(0) != eventActivationMap.end());
+// EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, 0);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap.size(), 1u);
+// EXPECT_TRUE(eventDeactivationMap.find(3) != eventDeactivationMap.end());
+// EXPECT_EQ(eventDeactivationMap[3].size(), 1u);
+// EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//
+// std::unique_ptr<LogEvent> event;
+//
+// event = CreateAppCrashEvent(111, bucketStartTimeNs + 5);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + 5);
+// EXPECT_FALSE(metricsManager->isActive());
+// EXPECT_FALSE(metricProducer->mIsActive);
+// EXPECT_EQ(broadcastCount, 0);
+//
+// // Activated by battery save mode.
+// event = CreateBatterySaverOnEvent(bucketStartTimeNs + 10);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + 10);
+// EXPECT_TRUE(metricsManager->isActive());
+// EXPECT_TRUE(metricProducer->mIsActive);
+// EXPECT_EQ(broadcastCount, 1);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+// EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//
+// // First processed event.
+// event = CreateAppCrashEvent(222, bucketStartTimeNs + 15);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + 15);
+//
+// // Activated by screen on event.
+// event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+// bucketStartTimeNs + 20);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + 20);
+// EXPECT_TRUE(metricsManager->isActive());
+// EXPECT_TRUE(metricProducer->mIsActive);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//
+// // 2nd processed event.
+// // The activation by screen_on event expires, but the one by battery save mode is still active.
+// event = CreateAppCrashEvent(333, bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
+// processor.OnLogEvent(event.get(),bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
+// EXPECT_TRUE(metricsManager->isActive());
+// EXPECT_TRUE(metricProducer->mIsActive);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+// // No new broadcast since the config should still be active.
+// EXPECT_EQ(broadcastCount, 1);
+//
+// // 3rd processed event.
+// event = CreateAppCrashEvent(444, bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
+//
+// // All activations expired.
+// event = CreateAppCrashEvent(555, bucketStartTimeNs + NS_PER_SEC * 60 * 8);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 8);
+// EXPECT_FALSE(metricsManager->isActive());
+// EXPECT_FALSE(metricProducer->mIsActive);
+// // New broadcast since the config is no longer active.
+// EXPECT_EQ(broadcastCount, 2);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//
+// // Re-activate metric via screen on.
+// event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+// bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+// EXPECT_TRUE(metricsManager->isActive());
+// EXPECT_TRUE(metricProducer->mIsActive);
+// EXPECT_EQ(broadcastCount, 3);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+// EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//
+// // 4th processed event.
+// event = CreateAppCrashEvent(666, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
+//
+// // Re-enable battery saver mode activation.
+// event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+// EXPECT_TRUE(metricsManager->isActive());
+// EXPECT_TRUE(metricProducer->mIsActive);
+// EXPECT_EQ(broadcastCount, 3);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+// EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//
+// // 5th processed event.
+// event = CreateAppCrashEvent(777, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
+//
+// // Cancel battery saver mode activation.
+// event = CreateScreenBrightnessChangedEvent(64, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 60);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 60);
+// EXPECT_TRUE(metricsManager->isActive());
+// EXPECT_TRUE(metricProducer->mIsActive);
+// EXPECT_EQ(broadcastCount, 3);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+// EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//
+// // Screen-on activation expired.
+// event = CreateAppCrashEvent(888, bucketStartTimeNs + NS_PER_SEC * 60 * 13);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 13);
+// EXPECT_FALSE(metricsManager->isActive());
+// EXPECT_FALSE(metricProducer->mIsActive);
+// // New broadcast since the config is no longer active.
+// EXPECT_EQ(broadcastCount, 4);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//
+// event = CreateAppCrashEvent(999, bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
+//
+// // Re-enable battery saver mode activation.
+// event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
+// EXPECT_TRUE(metricsManager->isActive());
+// EXPECT_TRUE(metricProducer->mIsActive);
+// EXPECT_EQ(broadcastCount, 5);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+// EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//
+// // Cancel battery saver mode activation.
+// event = CreateScreenBrightnessChangedEvent(140, bucketStartTimeNs + NS_PER_SEC * 60 * 16);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 16);
+// EXPECT_FALSE(metricsManager->isActive());
+// EXPECT_FALSE(metricProducer->mIsActive);
+// EXPECT_EQ(broadcastCount, 6);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//
+// ConfigMetricsReportList reports;
+// vector<uint8_t> buffer;
+// processor.onDumpReport(cfgKey, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 1, false, true,
+// ADB_DUMP, FAST, &buffer);
+// EXPECT_TRUE(buffer.size() > 0);
+// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+// backfillDimensionPath(&reports);
+// backfillStartEndTimestamp(&reports);
+// EXPECT_EQ(1, reports.reports_size());
+// EXPECT_EQ(1, reports.reports(0).metrics_size());
+// EXPECT_EQ(5, reports.reports(0).metrics(0).count_metrics().data_size());
+//
+// StatsLogReport::CountMetricDataWrapper countMetrics;
+// sortMetricDataByDimensionsValue(
+// reports.reports(0).metrics(0).count_metrics(), &countMetrics);
+// EXPECT_EQ(5, countMetrics.data_size());
+//
+// auto data = countMetrics.data(0);
+// EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* uid field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_EQ(222, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+// EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+// data = countMetrics.data(1);
+// EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* uid field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_EQ(333, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+// EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+// data = countMetrics.data(2);
+// EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* uid field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_EQ(444, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+// // Partial bucket as metric is deactivated.
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 8,
+// data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+// data = countMetrics.data(3);
+// EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* uid field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_EQ(666, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+// data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 13,
+// data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+// data = countMetrics.data(4);
+// EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* uid field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_EQ(777, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+// data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 13,
+// data.bucket_info(0).end_bucket_elapsed_nanos());
+//}
+//
+//TEST(MetricActivationE2eTest, TestCountMetricWithTwoDeactivations) {
+// auto config = CreateStatsdConfigWithTwoDeactivations();
+//
+// int64_t bucketStartTimeNs = NS_PER_SEC * 10; // 10 secs
+// int64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000LL * 1000LL;
+//
+// int uid = 12345;
+// int64_t cfgId = 98765;
+// ConfigKey cfgKey(uid, cfgId);
+//
+// sp<UidMap> m = new UidMap();
+// sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+// sp<AlarmMonitor> anomalyAlarmMonitor;
+// sp<AlarmMonitor> subscriberAlarmMonitor;
+// vector<int64_t> activeConfigsBroadcast;
+//
+// long timeBase1 = 1;
+// int broadcastCount = 0;
+// StatsLogProcessor processor(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor,
+// bucketStartTimeNs, [](const ConfigKey& key) { return true; },
+// [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid,
+// const vector<int64_t>& activeConfigs) {
+// broadcastCount++;
+// EXPECT_EQ(broadcastUid, uid);
+// activeConfigsBroadcast.clear();
+// activeConfigsBroadcast.insert(activeConfigsBroadcast.end(),
+// activeConfigs.begin(), activeConfigs.end());
+// return true;
+// });
+//
+// processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config);
+//
+// EXPECT_EQ(processor.mMetricsManagers.size(), 1u);
+// sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
+// EXPECT_TRUE(metricsManager->isConfigValid());
+// EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+// sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+// auto& eventActivationMap = metricProducer->mEventActivationMap;
+// auto& eventDeactivationMap = metricProducer->mEventDeactivationMap;
+//
+// EXPECT_FALSE(metricsManager->isActive());
+// EXPECT_FALSE(metricProducer->mIsActive);
+// // Two activations: one is triggered by battery saver mode (tracker index 0), the other is
+// // triggered by screen on event (tracker index 2).
+// EXPECT_EQ(eventActivationMap.size(), 2u);
+// EXPECT_TRUE(eventActivationMap.find(0) != eventActivationMap.end());
+// EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, 0);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap.size(), 2u);
+// EXPECT_TRUE(eventDeactivationMap.find(3) != eventDeactivationMap.end());
+// EXPECT_TRUE(eventDeactivationMap.find(4) != eventDeactivationMap.end());
+// EXPECT_EQ(eventDeactivationMap[3].size(), 1u);
+// EXPECT_EQ(eventDeactivationMap[4].size(), 1u);
+// EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+// EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+//
+// std::unique_ptr<LogEvent> event;
+//
+// event = CreateAppCrashEvent(111, bucketStartTimeNs + 5);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + 5);
+// EXPECT_FALSE(metricsManager->isActive());
+// EXPECT_FALSE(metricProducer->mIsActive);
+// EXPECT_EQ(broadcastCount, 0);
+//
+// // Activated by battery save mode.
+// event = CreateBatterySaverOnEvent(bucketStartTimeNs + 10);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + 10);
+// EXPECT_TRUE(metricsManager->isActive());
+// EXPECT_TRUE(metricProducer->mIsActive);
+// EXPECT_EQ(broadcastCount, 1);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+// EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+// EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+//
+// // First processed event.
+// event = CreateAppCrashEvent(222, bucketStartTimeNs + 15);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + 15);
+//
+// // Activated by screen on event.
+// event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+// bucketStartTimeNs + 20);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + 20);
+// EXPECT_TRUE(metricsManager->isActive());
+// EXPECT_TRUE(metricProducer->mIsActive);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+// EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+//
+// // 2nd processed event.
+// // The activation by screen_on event expires, but the one by battery save mode is still active.
+// event = CreateAppCrashEvent(333, bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
+// EXPECT_TRUE(metricsManager->isActive());
+// EXPECT_TRUE(metricProducer->mIsActive);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+// EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+// // No new broadcast since the config should still be active.
+// EXPECT_EQ(broadcastCount, 1);
+//
+// // 3rd processed event.
+// event = CreateAppCrashEvent(444, bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
+//
+// // All activations expired.
+// event = CreateAppCrashEvent(555, bucketStartTimeNs + NS_PER_SEC * 60 * 8);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 8);
+// EXPECT_FALSE(metricsManager->isActive());
+// EXPECT_FALSE(metricProducer->mIsActive);
+// // New broadcast since the config is no longer active.
+// EXPECT_EQ(broadcastCount, 2);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+// EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+//
+// // Re-activate metric via screen on.
+// event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+// bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+// EXPECT_TRUE(metricsManager->isActive());
+// EXPECT_TRUE(metricProducer->mIsActive);
+// EXPECT_EQ(broadcastCount, 3);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+// EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+// EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+//
+// // 4th processed event.
+// event = CreateAppCrashEvent(666, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
+//
+// // Re-enable battery saver mode activation.
+// event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+// EXPECT_TRUE(metricsManager->isActive());
+// EXPECT_TRUE(metricProducer->mIsActive);
+// EXPECT_EQ(broadcastCount, 3);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+// EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+// EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+//
+// // 5th processed event.
+// event = CreateAppCrashEvent(777, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
+//
+// // Cancel battery saver mode and screen on activation.
+// event = CreateScreenBrightnessChangedEvent(64, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 60);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 60);
+// EXPECT_FALSE(metricsManager->isActive());
+// EXPECT_FALSE(metricProducer->mIsActive);
+// // New broadcast since the config is no longer active.
+// EXPECT_EQ(broadcastCount, 4);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+// EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+//
+// // Screen-on activation expired.
+// event = CreateAppCrashEvent(888, bucketStartTimeNs + NS_PER_SEC * 60 * 13);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 13);
+// EXPECT_FALSE(metricsManager->isActive());
+// EXPECT_FALSE(metricProducer->mIsActive);
+// EXPECT_EQ(broadcastCount, 4);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+// EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+//
+// event = CreateAppCrashEvent(999, bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
+//
+// // Re-enable battery saver mode activation.
+// event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
+// EXPECT_TRUE(metricsManager->isActive());
+// EXPECT_TRUE(metricProducer->mIsActive);
+// EXPECT_EQ(broadcastCount, 5);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+// EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+// EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+//
+// // Cancel battery saver mode and screen on activation.
+// event = CreateScreenBrightnessChangedEvent(140, bucketStartTimeNs + NS_PER_SEC * 60 * 16);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 16);
+// EXPECT_FALSE(metricsManager->isActive());
+// EXPECT_FALSE(metricProducer->mIsActive);
+// EXPECT_EQ(broadcastCount, 6);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+// EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+//
+// ConfigMetricsReportList reports;
+// vector<uint8_t> buffer;
+// processor.onDumpReport(cfgKey, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 1, false, true,
+// ADB_DUMP, FAST, &buffer);
+// EXPECT_TRUE(buffer.size() > 0);
+// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+// backfillDimensionPath(&reports);
+// backfillStartEndTimestamp(&reports);
+// EXPECT_EQ(1, reports.reports_size());
+// EXPECT_EQ(1, reports.reports(0).metrics_size());
+// EXPECT_EQ(5, reports.reports(0).metrics(0).count_metrics().data_size());
+//
+// StatsLogReport::CountMetricDataWrapper countMetrics;
+// sortMetricDataByDimensionsValue(
+// reports.reports(0).metrics(0).count_metrics(), &countMetrics);
+// EXPECT_EQ(5, countMetrics.data_size());
+//
+// auto data = countMetrics.data(0);
+// EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* uid field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_EQ(222, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+// EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+// data = countMetrics.data(1);
+// EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* uid field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_EQ(333, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+// EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+// data = countMetrics.data(2);
+// EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* uid field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_EQ(444, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+// // Partial bucket as metric is deactivated.
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 8,
+// data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+// data = countMetrics.data(3);
+// EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* uid field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_EQ(666, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+// data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 11,
+// data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+// data = countMetrics.data(4);
+// EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* uid field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_EQ(777, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+// data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 11,
+// data.bucket_info(0).end_bucket_elapsed_nanos());
+//}
+//
+//TEST(MetricActivationE2eTest, TestCountMetricWithSameDeactivation) {
+// auto config = CreateStatsdConfigWithSameDeactivations();
+//
+// int64_t bucketStartTimeNs = NS_PER_SEC * 10; // 10 secs
+// int64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000LL * 1000LL;
+//
+// int uid = 12345;
+// int64_t cfgId = 98765;
+// ConfigKey cfgKey(uid, cfgId);
+//
+// sp<UidMap> m = new UidMap();
+// sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+// sp<AlarmMonitor> anomalyAlarmMonitor;
+// sp<AlarmMonitor> subscriberAlarmMonitor;
+// vector<int64_t> activeConfigsBroadcast;
+//
+// long timeBase1 = 1;
+// int broadcastCount = 0;
+// StatsLogProcessor processor(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor,
+// bucketStartTimeNs, [](const ConfigKey& key) { return true; },
+// [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid,
+// const vector<int64_t>& activeConfigs) {
+// broadcastCount++;
+// EXPECT_EQ(broadcastUid, uid);
+// activeConfigsBroadcast.clear();
+// activeConfigsBroadcast.insert(activeConfigsBroadcast.end(),
+// activeConfigs.begin(), activeConfigs.end());
+// return true;
+// });
+//
+// processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config);
+//
+// EXPECT_EQ(processor.mMetricsManagers.size(), 1u);
+// sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
+// EXPECT_TRUE(metricsManager->isConfigValid());
+// EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+// sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+// auto& eventActivationMap = metricProducer->mEventActivationMap;
+// auto& eventDeactivationMap = metricProducer->mEventDeactivationMap;
+//
+// EXPECT_FALSE(metricsManager->isActive());
+// EXPECT_FALSE(metricProducer->mIsActive);
+// // Two activations: one is triggered by battery saver mode (tracker index 0), the other is
+// // triggered by screen on event (tracker index 2).
+// EXPECT_EQ(eventActivationMap.size(), 2u);
+// EXPECT_TRUE(eventActivationMap.find(0) != eventActivationMap.end());
+// EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, 0);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap.size(), 1u);
+// EXPECT_TRUE(eventDeactivationMap.find(3) != eventDeactivationMap.end());
+// EXPECT_EQ(eventDeactivationMap[3].size(), 2u);
+// EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+// EXPECT_EQ(eventDeactivationMap[3][1], eventActivationMap[2]);
+// EXPECT_EQ(broadcastCount, 0);
+//
+// std::unique_ptr<LogEvent> event;
+//
+// // Event that should be ignored.
+// event = CreateAppCrashEvent(111, bucketStartTimeNs + 1);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + 1);
+//
+// // Activate metric via screen on for 2 minutes.
+// event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, bucketStartTimeNs + 10);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + 10);
+// EXPECT_TRUE(metricsManager->isActive());
+// EXPECT_TRUE(metricProducer->mIsActive);
+// EXPECT_EQ(broadcastCount, 1);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+// EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 10);
+//
+// // 1st processed event.
+// event = CreateAppCrashEvent(222, bucketStartTimeNs + 15);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + 15);
+//
+// // Enable battery saver mode activation for 5 minutes.
+// event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 + 10);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 + 10);
+// EXPECT_TRUE(metricsManager->isActive());
+// EXPECT_TRUE(metricProducer->mIsActive);
+// EXPECT_EQ(broadcastCount, 1);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 + 10);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 10);
+//
+// // 2nd processed event.
+// event = CreateAppCrashEvent(333, bucketStartTimeNs + NS_PER_SEC * 60 + 40);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 + 40);
+//
+// // Cancel battery saver mode and screen on activation.
+// int64_t firstDeactivation = bucketStartTimeNs + NS_PER_SEC * 61;
+// event = CreateScreenBrightnessChangedEvent(64, firstDeactivation);
+// processor.OnLogEvent(event.get(), firstDeactivation);
+// EXPECT_FALSE(metricsManager->isActive());
+// EXPECT_FALSE(metricProducer->mIsActive);
+// // New broadcast since the config is no longer active.
+// EXPECT_EQ(broadcastCount, 2);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//
+// // Should be ignored
+// event = CreateAppCrashEvent(444, bucketStartTimeNs + NS_PER_SEC * 61 + 80);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 61 + 80);
+//
+// // Re-enable battery saver mode activation.
+// event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 15);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 15);
+// EXPECT_TRUE(metricsManager->isActive());
+// EXPECT_TRUE(metricProducer->mIsActive);
+// EXPECT_EQ(broadcastCount, 3);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+// EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 15);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//
+// // 3rd processed event.
+// event = CreateAppCrashEvent(555, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 80);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 80);
+//
+// // Cancel battery saver mode activation.
+// int64_t secondDeactivation = bucketStartTimeNs + NS_PER_SEC * 60 * 13;
+// event = CreateScreenBrightnessChangedEvent(140, secondDeactivation);
+// processor.OnLogEvent(event.get(), secondDeactivation);
+// EXPECT_FALSE(metricsManager->isActive());
+// EXPECT_FALSE(metricProducer->mIsActive);
+// EXPECT_EQ(broadcastCount, 4);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//
+// // Should be ignored.
+// event = CreateAppCrashEvent(666, bucketStartTimeNs + NS_PER_SEC * 60 * 13 + 80);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 13 + 80);
+//
+// ConfigMetricsReportList reports;
+// vector<uint8_t> buffer;
+// processor.onDumpReport(cfgKey, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 1, false, true,
+// ADB_DUMP, FAST, &buffer);
+// EXPECT_TRUE(buffer.size() > 0);
+// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+// backfillDimensionPath(&reports);
+// backfillStartEndTimestamp(&reports);
+// EXPECT_EQ(1, reports.reports_size());
+// EXPECT_EQ(1, reports.reports(0).metrics_size());
+// EXPECT_EQ(3, reports.reports(0).metrics(0).count_metrics().data_size());
+//
+// StatsLogReport::CountMetricDataWrapper countMetrics;
+// sortMetricDataByDimensionsValue(
+// reports.reports(0).metrics(0).count_metrics(), &countMetrics);
+// EXPECT_EQ(3, countMetrics.data_size());
+//
+// auto data = countMetrics.data(0);
+// EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* uid field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_EQ(222, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+// EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(firstDeactivation, data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+// data = countMetrics.data(1);
+// EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* uid field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_EQ(333, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+// EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(firstDeactivation, data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+// data = countMetrics.data(2);
+// EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* uid field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_EQ(555, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+// // Partial bucket as metric is deactivated.
+// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(secondDeactivation, data.bucket_info(0).end_bucket_elapsed_nanos());
+//}
+//
+//TEST(MetricActivationE2eTest, TestCountMetricWithTwoMetricsTwoDeactivations) {
+// auto config = CreateStatsdConfigWithTwoMetricsTwoDeactivations();
+//
+// int64_t bucketStartTimeNs = NS_PER_SEC * 10; // 10 secs
+// int64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000LL * 1000LL;
+//
+// int uid = 12345;
+// int64_t cfgId = 98765;
+// ConfigKey cfgKey(uid, cfgId);
+//
+// sp<UidMap> m = new UidMap();
+// sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+// sp<AlarmMonitor> anomalyAlarmMonitor;
+// sp<AlarmMonitor> subscriberAlarmMonitor;
+// vector<int64_t> activeConfigsBroadcast;
+//
+// long timeBase1 = 1;
+// int broadcastCount = 0;
+// StatsLogProcessor processor(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor,
+// bucketStartTimeNs, [](const ConfigKey& key) { return true; },
+// [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid,
+// const vector<int64_t>& activeConfigs) {
+// broadcastCount++;
+// EXPECT_EQ(broadcastUid, uid);
+// activeConfigsBroadcast.clear();
+// activeConfigsBroadcast.insert(activeConfigsBroadcast.end(),
+// activeConfigs.begin(), activeConfigs.end());
+// return true;
+// });
+//
+// processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config);
+//
+// EXPECT_EQ(processor.mMetricsManagers.size(), 1u);
+// sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
+// EXPECT_TRUE(metricsManager->isConfigValid());
+// EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 2);
+// sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+// auto& eventActivationMap = metricProducer->mEventActivationMap;
+// auto& eventDeactivationMap = metricProducer->mEventDeactivationMap;
+// sp<MetricProducer> metricProducer2 = metricsManager->mAllMetricProducers[1];
+// auto& eventActivationMap2 = metricProducer2->mEventActivationMap;
+// auto& eventDeactivationMap2 = metricProducer2->mEventDeactivationMap;
+//
+// EXPECT_FALSE(metricsManager->isActive());
+// EXPECT_FALSE(metricProducer->mIsActive);
+// EXPECT_FALSE(metricProducer2->mIsActive);
+// // Two activations: one is triggered by battery saver mode (tracker index 0), the other is
+// // triggered by screen on event (tracker index 2).
+// EXPECT_EQ(eventActivationMap.size(), 2u);
+// EXPECT_TRUE(eventActivationMap.find(0) != eventActivationMap.end());
+// EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, 0);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap.size(), 2u);
+// EXPECT_TRUE(eventDeactivationMap.find(3) != eventDeactivationMap.end());
+// EXPECT_TRUE(eventDeactivationMap.find(4) != eventDeactivationMap.end());
+// EXPECT_EQ(eventDeactivationMap[3].size(), 1u);
+// EXPECT_EQ(eventDeactivationMap[4].size(), 1u);
+// EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+// EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+//
+// EXPECT_EQ(eventActivationMap2.size(), 2u);
+// EXPECT_TRUE(eventActivationMap2.find(0) != eventActivationMap2.end());
+// EXPECT_TRUE(eventActivationMap2.find(2) != eventActivationMap2.end());
+// EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap2[0]->start_ns, 0);
+// EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap2[2]->start_ns, 0);
+// EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap2.size(), 2u);
+// EXPECT_TRUE(eventDeactivationMap2.find(3) != eventDeactivationMap2.end());
+// EXPECT_TRUE(eventDeactivationMap2.find(4) != eventDeactivationMap2.end());
+// EXPECT_EQ(eventDeactivationMap[3].size(), 1u);
+// EXPECT_EQ(eventDeactivationMap[4].size(), 1u);
+// EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
+// EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
+//
+// std::unique_ptr<LogEvent> event;
+//
+// event = CreateAppCrashEvent(111, bucketStartTimeNs + 5);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + 5);
+// event = CreateMoveToForegroundEvent(1111, bucketStartTimeNs + 5);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + 5);
+// EXPECT_FALSE(metricsManager->isActive());
+// EXPECT_FALSE(metricProducer->mIsActive);
+// EXPECT_FALSE(metricProducer2->mIsActive);
+// EXPECT_EQ(broadcastCount, 0);
+//
+// // Activated by battery save mode.
+// event = CreateBatterySaverOnEvent(bucketStartTimeNs + 10);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + 10);
+// EXPECT_TRUE(metricsManager->isActive());
+// EXPECT_EQ(broadcastCount, 1);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+// EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+// EXPECT_TRUE(metricProducer->mIsActive);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+// EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+// EXPECT_TRUE(metricProducer2->mIsActive);
+// EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + 10);
+// EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap2[2]->start_ns, 0);
+// EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
+// EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
+//
+// // First processed event.
+// event = CreateAppCrashEvent(222, bucketStartTimeNs + 15);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + 15);
+// event = CreateMoveToForegroundEvent(2222, bucketStartTimeNs + 15);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + 15);
+//
+// // Activated by screen on event.
+// event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+// bucketStartTimeNs + 20);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + 20);
+// EXPECT_TRUE(metricsManager->isActive());
+// EXPECT_TRUE(metricProducer->mIsActive);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+// EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+// EXPECT_TRUE(metricProducer2->mIsActive);
+// EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + 10);
+// EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + 20);
+// EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
+// EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
+//
+// // 2nd processed event.
+// // The activation by screen_on event expires, but the one by battery save mode is still active.
+// event = CreateAppCrashEvent(333, bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
+// event = CreateMoveToForegroundEvent(3333, bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
+// EXPECT_TRUE(metricsManager->isActive());
+// EXPECT_TRUE(metricProducer->mIsActive);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+// EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+// EXPECT_TRUE(metricProducer2->mIsActive);
+// EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + 10);
+// EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + 20);
+// EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
+// EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
+// // No new broadcast since the config should still be active.
+// EXPECT_EQ(broadcastCount, 1);
+//
+// // 3rd processed event.
+// event = CreateAppCrashEvent(444, bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
+// event = CreateMoveToForegroundEvent(4444, bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
+//
+// // All activations expired.
+// event = CreateAppCrashEvent(555, bucketStartTimeNs + NS_PER_SEC * 60 * 8);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 8);
+// event = CreateMoveToForegroundEvent(5555, bucketStartTimeNs + NS_PER_SEC * 60 * 8);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 8);
+// EXPECT_FALSE(metricsManager->isActive());
+// // New broadcast since the config is no longer active.
+// EXPECT_EQ(broadcastCount, 2);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+// EXPECT_FALSE(metricProducer->mIsActive);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+// EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+// EXPECT_FALSE(metricProducer2->mIsActive);
+// EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + 10);
+// EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + 20);
+// EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
+// EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
+//
+// // Re-activate metric via screen on.
+// event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+// bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+// EXPECT_TRUE(metricsManager->isActive());
+// EXPECT_EQ(broadcastCount, 3);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+// EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+// EXPECT_TRUE(metricProducer->mIsActive);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+// EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+// EXPECT_TRUE(metricProducer2->mIsActive);
+// EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + 10);
+// EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+// EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
+// EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
+//
+// // 4th processed event.
+// event = CreateAppCrashEvent(666, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
+// event = CreateMoveToForegroundEvent(6666, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
+//
+// // Re-enable battery saver mode activation.
+// event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+// EXPECT_TRUE(metricsManager->isActive());
+// EXPECT_EQ(broadcastCount, 3);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+// EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+// EXPECT_TRUE(metricProducer->mIsActive);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+// EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+// EXPECT_TRUE(metricProducer2->mIsActive);
+// EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+// EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+// EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
+// EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
+//
+// // 5th processed event.
+// event = CreateAppCrashEvent(777, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
+// event = CreateMoveToForegroundEvent(7777, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
+//
+// // Cancel battery saver mode and screen on activation.
+// event = CreateScreenBrightnessChangedEvent(64, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 60);
+// processor.OnLogEvent(event.get(),bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 60);
+// EXPECT_FALSE(metricsManager->isActive());
+// // New broadcast since the config is no longer active.
+// EXPECT_EQ(broadcastCount, 4);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+// EXPECT_FALSE(metricProducer->mIsActive);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+// EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+// EXPECT_FALSE(metricProducer2->mIsActive);
+// EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+// EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+// EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
+// EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
+//
+// // Screen-on activation expired.
+// event = CreateAppCrashEvent(888, bucketStartTimeNs + NS_PER_SEC * 60 * 13);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 13);
+// event = CreateMoveToForegroundEvent(8888, bucketStartTimeNs + NS_PER_SEC * 60 * 13);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 13);
+// EXPECT_FALSE(metricsManager->isActive());
+// EXPECT_EQ(broadcastCount, 4);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+// EXPECT_FALSE(metricProducer->mIsActive);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+// EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+// EXPECT_FALSE(metricProducer2->mIsActive);
+// EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+// EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+// EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
+// EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
+//
+// event = CreateAppCrashEvent(999, bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
+// event = CreateMoveToForegroundEvent(9999, bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
+//
+// // Re-enable battery saver mode activation.
+// event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
+// processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
+// EXPECT_TRUE(metricsManager->isActive());
+// EXPECT_EQ(broadcastCount, 5);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+// EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+// EXPECT_TRUE(metricProducer->mIsActive);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+// EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+// EXPECT_TRUE(metricProducer2->mIsActive);
+// EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kActive);
+// EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
+// EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+// EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
+// EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
+//
+// // Cancel battery saver mode and screen on activation.
+// event = CreateScreenBrightnessChangedEvent(140, bucketStartTimeNs + NS_PER_SEC * 60 * 16);
+// processor.OnLogEvent(event.get(),bucketStartTimeNs + NS_PER_SEC * 60 * 16);
+// EXPECT_FALSE(metricsManager->isActive());
+// EXPECT_EQ(broadcastCount, 6);
+// EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+// EXPECT_FALSE(metricProducer->mIsActive);
+// EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
+// EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+// EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+// EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+// EXPECT_FALSE(metricProducer2->mIsActive);
+// EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
+// EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+// EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kNotActive);
+// EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+// EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+// EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
+// EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
+//
+// ConfigMetricsReportList reports;
+// vector<uint8_t> buffer;
+// processor.onDumpReport(cfgKey, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 1, false, true,
+// ADB_DUMP, FAST, &buffer);
+// EXPECT_TRUE(buffer.size() > 0);
+// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+// backfillDimensionPath(&reports);
+// backfillStartEndTimestamp(&reports);
+// EXPECT_EQ(1, reports.reports_size());
+// EXPECT_EQ(2, reports.reports(0).metrics_size());
+// EXPECT_EQ(5, reports.reports(0).metrics(0).count_metrics().data_size());
+// EXPECT_EQ(5, reports.reports(0).metrics(1).count_metrics().data_size());
+//
+// StatsLogReport::CountMetricDataWrapper countMetrics;
+//
+// sortMetricDataByDimensionsValue(
+// reports.reports(0).metrics(0).count_metrics(), &countMetrics);
+// EXPECT_EQ(5, countMetrics.data_size());
+//
+// auto data = countMetrics.data(0);
+// EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* uid field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_EQ(222, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+// EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+// data = countMetrics.data(1);
+// EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* uid field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_EQ(333, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+// EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+// data = countMetrics.data(2);
+// EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* uid field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_EQ(444, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+// // Partial bucket as metric is deactivated.
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 8,
+// data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+// data = countMetrics.data(3);
+// EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* uid field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_EQ(666, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+// data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 11,
+// data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+// data = countMetrics.data(4);
+// EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* uid field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_EQ(777, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+// data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 11,
+// data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+//
+// countMetrics.clear_data();
+// sortMetricDataByDimensionsValue(
+// reports.reports(0).metrics(1).count_metrics(), &countMetrics);
+// EXPECT_EQ(5, countMetrics.data_size());
+//
+// data = countMetrics.data(0);
+// EXPECT_EQ(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* uid field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_EQ(2222, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+// EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+// data = countMetrics.data(1);
+// EXPECT_EQ(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* uid field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_EQ(3333, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+// EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+// data = countMetrics.data(2);
+// EXPECT_EQ(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* uid field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_EQ(4444, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+// // Partial bucket as metric is deactivated.
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 8,
+// data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+// data = countMetrics.data(3);
+// EXPECT_EQ(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* uid field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_EQ(6666, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+// data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 11,
+// data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+// data = countMetrics.data(4);
+// EXPECT_EQ(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* uid field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_EQ(7777, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(1, data.bucket_info(0).count());
+// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+// data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 11,
+// data.bucket_info(0).end_bucket_elapsed_nanos());
+//}
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
diff --git a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
index 78fb391..7d93fcc 100644
--- a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
@@ -97,249 +97,250 @@
}
} // namespace
-// If we want to test multiple dump data, we must do it in separate tests, because in the e2e tests,
-// we should use the real API which will clear the data after dump data is called.
-TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks1) {
- auto config = CreateStatsdConfig();
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
-
- ConfigKey cfgKey;
- auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
- EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
- EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-
- int appUid = 123;
- auto crashEvent1 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 1);
- auto crashEvent2 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 201);
- auto crashEvent3= CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 101);
-
- auto crashEvent4 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 51);
- auto crashEvent5 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 299);
- auto crashEvent6 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 2001);
-
- auto crashEvent7 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 16);
- auto crashEvent8 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 249);
-
- auto crashEvent9 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 351);
- auto crashEvent10 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 2);
-
- auto screenTurnedOnEvent =
- CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
- bucketStartTimeNs + 2);
- auto screenTurnedOffEvent =
- CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
- bucketStartTimeNs + 200);
- auto screenTurnedOnEvent2 =
- CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
- bucketStartTimeNs + 2 * bucketSizeNs - 100);
-
- std::vector<AttributionNodeInternal> attributions = {
- CreateAttribution(appUid, "App1"), CreateAttribution(appUid + 1, "GMSCoreModule1")};
- auto syncOnEvent1 =
- CreateSyncStartEvent(attributions, "ReadEmail", bucketStartTimeNs + 50);
- auto syncOffEvent1 =
- CreateSyncEndEvent(attributions, "ReadEmail", bucketStartTimeNs + bucketSizeNs + 300);
- auto syncOnEvent2 =
- CreateSyncStartEvent(attributions, "ReadDoc", bucketStartTimeNs + bucketSizeNs + 2000);
-
- auto moveToBackgroundEvent1 =
- CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 15);
- auto moveToForegroundEvent1 =
- CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 250);
-
- auto moveToBackgroundEvent2 =
- CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 350);
- auto moveToForegroundEvent2 =
- CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 1);
-
- /*
- bucket #1 bucket #2
-
-
- | | | | | | | | | | (crashEvents)
- |-------------------------------------|-----------------------------------|---------
-
- | | (MoveToBkground)
-
- | | (MoveToForeground)
-
- | | (SyncIsOn)
- | (SyncIsOff)
- | | (ScreenIsOn)
- | (ScreenIsOff)
- */
- std::vector<std::unique_ptr<LogEvent>> events;
- events.push_back(std::move(crashEvent1));
- events.push_back(std::move(crashEvent2));
- events.push_back(std::move(crashEvent3));
- events.push_back(std::move(crashEvent4));
- events.push_back(std::move(crashEvent5));
- events.push_back(std::move(crashEvent6));
- events.push_back(std::move(crashEvent7));
- events.push_back(std::move(crashEvent8));
- events.push_back(std::move(crashEvent9));
- events.push_back(std::move(crashEvent10));
- events.push_back(std::move(screenTurnedOnEvent));
- events.push_back(std::move(screenTurnedOffEvent));
- events.push_back(std::move(screenTurnedOnEvent2));
- events.push_back(std::move(syncOnEvent1));
- events.push_back(std::move(syncOffEvent1));
- events.push_back(std::move(syncOnEvent2));
- events.push_back(std::move(moveToBackgroundEvent1));
- events.push_back(std::move(moveToForegroundEvent1));
- events.push_back(std::move(moveToBackgroundEvent2));
- events.push_back(std::move(moveToForegroundEvent2));
-
- sortLogEventsByTimestamp(&events);
-
- for (const auto& event : events) {
- processor->OnLogEvent(event.get());
- }
- ConfigMetricsReportList reports;
- vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true,
- ADB_DUMP, FAST, &buffer);
- EXPECT_TRUE(buffer.size() > 0);
- EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
- backfillDimensionPath(&reports);
- backfillStringInReport(&reports);
- backfillStartEndTimestamp(&reports);
- EXPECT_EQ(reports.reports_size(), 1);
- EXPECT_EQ(reports.reports(0).metrics_size(), 1);
- EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data_size(), 1);
- EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info_size(), 1);
- EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(0).count(), 1);
- auto data = reports.reports(0).metrics(0).count_metrics().data(0);
- // Validate dimension value.
- EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
- EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
- // Uid field.
- EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1);
- EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid);
-}
-
-TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks2) {
- auto config = CreateStatsdConfig();
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
-
- ConfigKey cfgKey;
- auto processor = CreateStatsLogProcessor(
- bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
- EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
- EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-
- int appUid = 123;
- auto crashEvent1 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 1);
- auto crashEvent2 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 201);
- auto crashEvent3 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 101);
-
- auto crashEvent4 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 51);
- auto crashEvent5 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 299);
- auto crashEvent6 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 2001);
-
- auto crashEvent7 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 16);
- auto crashEvent8 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 249);
-
- auto crashEvent9 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 351);
- auto crashEvent10 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 2);
-
- auto screenTurnedOnEvent = CreateScreenStateChangedEvent(
- android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 2);
- auto screenTurnedOffEvent = CreateScreenStateChangedEvent(
- android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 200);
- auto screenTurnedOnEvent2 =
- CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
- bucketStartTimeNs + 2 * bucketSizeNs - 100);
-
- std::vector<AttributionNodeInternal> attributions = {
- CreateAttribution(appUid, "App1"), CreateAttribution(appUid + 1, "GMSCoreModule1")};
- auto syncOnEvent1 = CreateSyncStartEvent(attributions, "ReadEmail", bucketStartTimeNs + 50);
- auto syncOffEvent1 =
- CreateSyncEndEvent(attributions, "ReadEmail", bucketStartTimeNs + bucketSizeNs + 300);
- auto syncOnEvent2 =
- CreateSyncStartEvent(attributions, "ReadDoc", bucketStartTimeNs + bucketSizeNs + 2000);
-
- auto moveToBackgroundEvent1 = CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 15);
- auto moveToForegroundEvent1 =
- CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 250);
-
- auto moveToBackgroundEvent2 =
- CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 350);
- auto moveToForegroundEvent2 =
- CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 1);
-
- /*
- bucket #1 bucket #2
-
-
- | | | | | | | | | | (crashEvents)
- |-------------------------------------|-----------------------------------|---------
-
- | | (MoveToBkground)
-
- | | (MoveToForeground)
-
- | | (SyncIsOn)
- | (SyncIsOff)
- | | (ScreenIsOn)
- | (ScreenIsOff)
- */
- std::vector<std::unique_ptr<LogEvent>> events;
- events.push_back(std::move(crashEvent1));
- events.push_back(std::move(crashEvent2));
- events.push_back(std::move(crashEvent3));
- events.push_back(std::move(crashEvent4));
- events.push_back(std::move(crashEvent5));
- events.push_back(std::move(crashEvent6));
- events.push_back(std::move(crashEvent7));
- events.push_back(std::move(crashEvent8));
- events.push_back(std::move(crashEvent9));
- events.push_back(std::move(crashEvent10));
- events.push_back(std::move(screenTurnedOnEvent));
- events.push_back(std::move(screenTurnedOffEvent));
- events.push_back(std::move(screenTurnedOnEvent2));
- events.push_back(std::move(syncOnEvent1));
- events.push_back(std::move(syncOffEvent1));
- events.push_back(std::move(syncOnEvent2));
- events.push_back(std::move(moveToBackgroundEvent1));
- events.push_back(std::move(moveToForegroundEvent1));
- events.push_back(std::move(moveToBackgroundEvent2));
- events.push_back(std::move(moveToForegroundEvent2));
-
- sortLogEventsByTimestamp(&events);
-
- for (const auto& event : events) {
- processor->OnLogEvent(event.get());
- }
- ConfigMetricsReportList reports;
- vector<uint8_t> buffer;
-
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
- ADB_DUMP, FAST, &buffer);
- EXPECT_TRUE(buffer.size() > 0);
- EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
- backfillDimensionPath(&reports);
- backfillStringInReport(&reports);
- backfillStartEndTimestamp(&reports);
- EXPECT_EQ(reports.reports_size(), 1);
- EXPECT_EQ(reports.reports(0).metrics_size(), 1);
- EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data_size(), 1);
- EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info_size(), 2);
- EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(0).count(), 1);
- EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(1).count(), 3);
- auto data = reports.reports(0).metrics(0).count_metrics().data(0);
- // Validate dimension value.
- EXPECT_EQ(data.dimensions_in_what().field(),
- android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
- EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
- // Uid field.
- EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1);
- EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid);
-}
+// TODO(b/149590301): Update these tests to use new socket schema.
+//// If we want to test multiple dump data, we must do it in separate tests, because in the e2e tests,
+//// we should use the real API which will clear the data after dump data is called.
+//TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks1) {
+// auto config = CreateStatsdConfig();
+// uint64_t bucketStartTimeNs = 10000000000;
+// uint64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
+//
+// ConfigKey cfgKey;
+// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+//
+// int appUid = 123;
+// auto crashEvent1 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 1);
+// auto crashEvent2 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 201);
+// auto crashEvent3= CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 101);
+//
+// auto crashEvent4 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 51);
+// auto crashEvent5 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 299);
+// auto crashEvent6 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 2001);
+//
+// auto crashEvent7 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 16);
+// auto crashEvent8 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 249);
+//
+// auto crashEvent9 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 351);
+// auto crashEvent10 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 2);
+//
+// auto screenTurnedOnEvent =
+// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+// bucketStartTimeNs + 2);
+// auto screenTurnedOffEvent =
+// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+// bucketStartTimeNs + 200);
+// auto screenTurnedOnEvent2 =
+// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+// bucketStartTimeNs + 2 * bucketSizeNs - 100);
+//
+// std::vector<AttributionNodeInternal> attributions = {
+// CreateAttribution(appUid, "App1"), CreateAttribution(appUid + 1, "GMSCoreModule1")};
+// auto syncOnEvent1 =
+// CreateSyncStartEvent(attributions, "ReadEmail", bucketStartTimeNs + 50);
+// auto syncOffEvent1 =
+// CreateSyncEndEvent(attributions, "ReadEmail", bucketStartTimeNs + bucketSizeNs + 300);
+// auto syncOnEvent2 =
+// CreateSyncStartEvent(attributions, "ReadDoc", bucketStartTimeNs + bucketSizeNs + 2000);
+//
+// auto moveToBackgroundEvent1 =
+// CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 15);
+// auto moveToForegroundEvent1 =
+// CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 250);
+//
+// auto moveToBackgroundEvent2 =
+// CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 350);
+// auto moveToForegroundEvent2 =
+// CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 1);
+//
+// /*
+// bucket #1 bucket #2
+//
+//
+// | | | | | | | | | | (crashEvents)
+// |-------------------------------------|-----------------------------------|---------
+//
+// | | (MoveToBkground)
+//
+// | | (MoveToForeground)
+//
+// | | (SyncIsOn)
+// | (SyncIsOff)
+// | | (ScreenIsOn)
+// | (ScreenIsOff)
+// */
+// std::vector<std::unique_ptr<LogEvent>> events;
+// events.push_back(std::move(crashEvent1));
+// events.push_back(std::move(crashEvent2));
+// events.push_back(std::move(crashEvent3));
+// events.push_back(std::move(crashEvent4));
+// events.push_back(std::move(crashEvent5));
+// events.push_back(std::move(crashEvent6));
+// events.push_back(std::move(crashEvent7));
+// events.push_back(std::move(crashEvent8));
+// events.push_back(std::move(crashEvent9));
+// events.push_back(std::move(crashEvent10));
+// events.push_back(std::move(screenTurnedOnEvent));
+// events.push_back(std::move(screenTurnedOffEvent));
+// events.push_back(std::move(screenTurnedOnEvent2));
+// events.push_back(std::move(syncOnEvent1));
+// events.push_back(std::move(syncOffEvent1));
+// events.push_back(std::move(syncOnEvent2));
+// events.push_back(std::move(moveToBackgroundEvent1));
+// events.push_back(std::move(moveToForegroundEvent1));
+// events.push_back(std::move(moveToBackgroundEvent2));
+// events.push_back(std::move(moveToForegroundEvent2));
+//
+// sortLogEventsByTimestamp(&events);
+//
+// for (const auto& event : events) {
+// processor->OnLogEvent(event.get());
+// }
+// ConfigMetricsReportList reports;
+// vector<uint8_t> buffer;
+// processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true,
+// ADB_DUMP, FAST, &buffer);
+// EXPECT_TRUE(buffer.size() > 0);
+// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+// backfillDimensionPath(&reports);
+// backfillStringInReport(&reports);
+// backfillStartEndTimestamp(&reports);
+// EXPECT_EQ(reports.reports_size(), 1);
+// EXPECT_EQ(reports.reports(0).metrics_size(), 1);
+// EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data_size(), 1);
+// EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info_size(), 1);
+// EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(0).count(), 1);
+// auto data = reports.reports(0).metrics(0).count_metrics().data(0);
+// // Validate dimension value.
+// EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
+// EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
+// // Uid field.
+// EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1);
+// EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid);
+//}
+//
+//TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks2) {
+// auto config = CreateStatsdConfig();
+// uint64_t bucketStartTimeNs = 10000000000;
+// uint64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
+//
+// ConfigKey cfgKey;
+// auto processor = CreateStatsLogProcessor(
+// bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+//
+// int appUid = 123;
+// auto crashEvent1 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 1);
+// auto crashEvent2 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 201);
+// auto crashEvent3 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 101);
+//
+// auto crashEvent4 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 51);
+// auto crashEvent5 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 299);
+// auto crashEvent6 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 2001);
+//
+// auto crashEvent7 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 16);
+// auto crashEvent8 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 249);
+//
+// auto crashEvent9 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 351);
+// auto crashEvent10 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 2);
+//
+// auto screenTurnedOnEvent = CreateScreenStateChangedEvent(
+// android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 2);
+// auto screenTurnedOffEvent = CreateScreenStateChangedEvent(
+// android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 200);
+// auto screenTurnedOnEvent2 =
+// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+// bucketStartTimeNs + 2 * bucketSizeNs - 100);
+//
+// std::vector<AttributionNodeInternal> attributions = {
+// CreateAttribution(appUid, "App1"), CreateAttribution(appUid + 1, "GMSCoreModule1")};
+// auto syncOnEvent1 = CreateSyncStartEvent(attributions, "ReadEmail", bucketStartTimeNs + 50);
+// auto syncOffEvent1 =
+// CreateSyncEndEvent(attributions, "ReadEmail", bucketStartTimeNs + bucketSizeNs + 300);
+// auto syncOnEvent2 =
+// CreateSyncStartEvent(attributions, "ReadDoc", bucketStartTimeNs + bucketSizeNs + 2000);
+//
+// auto moveToBackgroundEvent1 = CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 15);
+// auto moveToForegroundEvent1 =
+// CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 250);
+//
+// auto moveToBackgroundEvent2 =
+// CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 350);
+// auto moveToForegroundEvent2 =
+// CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 1);
+//
+// /*
+// bucket #1 bucket #2
+//
+//
+// | | | | | | | | | | (crashEvents)
+// |-------------------------------------|-----------------------------------|---------
+//
+// | | (MoveToBkground)
+//
+// | | (MoveToForeground)
+//
+// | | (SyncIsOn)
+// | (SyncIsOff)
+// | | (ScreenIsOn)
+// | (ScreenIsOff)
+// */
+// std::vector<std::unique_ptr<LogEvent>> events;
+// events.push_back(std::move(crashEvent1));
+// events.push_back(std::move(crashEvent2));
+// events.push_back(std::move(crashEvent3));
+// events.push_back(std::move(crashEvent4));
+// events.push_back(std::move(crashEvent5));
+// events.push_back(std::move(crashEvent6));
+// events.push_back(std::move(crashEvent7));
+// events.push_back(std::move(crashEvent8));
+// events.push_back(std::move(crashEvent9));
+// events.push_back(std::move(crashEvent10));
+// events.push_back(std::move(screenTurnedOnEvent));
+// events.push_back(std::move(screenTurnedOffEvent));
+// events.push_back(std::move(screenTurnedOnEvent2));
+// events.push_back(std::move(syncOnEvent1));
+// events.push_back(std::move(syncOffEvent1));
+// events.push_back(std::move(syncOnEvent2));
+// events.push_back(std::move(moveToBackgroundEvent1));
+// events.push_back(std::move(moveToForegroundEvent1));
+// events.push_back(std::move(moveToBackgroundEvent2));
+// events.push_back(std::move(moveToForegroundEvent2));
+//
+// sortLogEventsByTimestamp(&events);
+//
+// for (const auto& event : events) {
+// processor->OnLogEvent(event.get());
+// }
+// ConfigMetricsReportList reports;
+// vector<uint8_t> buffer;
+//
+// processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
+// ADB_DUMP, FAST, &buffer);
+// EXPECT_TRUE(buffer.size() > 0);
+// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+// backfillDimensionPath(&reports);
+// backfillStringInReport(&reports);
+// backfillStartEndTimestamp(&reports);
+// EXPECT_EQ(reports.reports_size(), 1);
+// EXPECT_EQ(reports.reports(0).metrics_size(), 1);
+// EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data_size(), 1);
+// EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info_size(), 2);
+// EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(0).count(), 1);
+// EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(1).count(), 3);
+// auto data = reports.reports(0).metrics(0).count_metrics().data(0);
+// // Validate dimension value.
+// EXPECT_EQ(data.dimensions_in_what().field(),
+// android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
+// EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
+// // Uid field.
+// EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1);
+// EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid);
+//}
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
diff --git a/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp b/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
index 1eecbe5..9ec831b 100644
--- a/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
@@ -113,95 +113,96 @@
}
} // anonymous namespace
-TEST(PartialBucketE2eTest, TestCountMetricWithoutSplit) {
- shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
- SendConfig(service, MakeConfig());
- int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
- // initialized with.
-
- service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
- service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 2).get());
-
- ConfigMetricsReport report = GetReports(service->mProcessor, start + 3);
- // Expect no metrics since the bucket has not finished yet.
- EXPECT_EQ(1, report.metrics_size());
- EXPECT_EQ(0, report.metrics(0).count_metrics().data_size());
-}
-
-TEST(PartialBucketE2eTest, TestCountMetricNoSplitOnNewApp) {
- shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
- SendConfig(service, MakeConfig());
- int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
- // initialized with.
-
- // Force the uidmap to update at timestamp 2.
- service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
- // This is a new installation, so there shouldn't be a split (should be same as the without
- // split case).
- service->mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"),
- String16(""));
- // Goes into the second bucket.
- service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get());
-
- ConfigMetricsReport report = GetReports(service->mProcessor, start + 4);
- EXPECT_EQ(1, report.metrics_size());
- EXPECT_EQ(0, report.metrics(0).count_metrics().data_size());
-}
-
-TEST(PartialBucketE2eTest, TestCountMetricSplitOnUpgrade) {
- shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
- SendConfig(service, MakeConfig());
- int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
- // initialized with.
- service->mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
- {String16("")});
-
- // Force the uidmap to update at timestamp 2.
- service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
- service->mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"),
- String16(""));
- // Goes into the second bucket.
- service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get());
-
- ConfigMetricsReport report = GetReports(service->mProcessor, start + 4);
- backfillStartEndTimestamp(&report);
-
- ASSERT_EQ(1, report.metrics_size());
- ASSERT_EQ(1, report.metrics(0).count_metrics().data_size());
- ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size());
- EXPECT_TRUE(report.metrics(0).count_metrics().data(0).bucket_info(0).
- has_start_bucket_elapsed_nanos());
- EXPECT_TRUE(report.metrics(0).count_metrics().data(0).bucket_info(0).
- has_end_bucket_elapsed_nanos());
- EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count());
-}
-
-TEST(PartialBucketE2eTest, TestCountMetricSplitOnRemoval) {
- shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
- SendConfig(service, MakeConfig());
- int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
- // initialized with.
- service->mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
- {String16("")});
-
- // Force the uidmap to update at timestamp 2.
- service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
- service->mUidMap->removeApp(start + 2, String16(kApp1.c_str()), 1);
- // Goes into the second bucket.
- service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get());
-
- ConfigMetricsReport report = GetReports(service->mProcessor, start + 4);
- backfillStartEndTimestamp(&report);
-
- ASSERT_EQ(1, report.metrics_size());
- ASSERT_EQ(1, report.metrics(0).count_metrics().data_size());
- ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size());
- EXPECT_TRUE(report.metrics(0).count_metrics().data(0).bucket_info(0).
- has_start_bucket_elapsed_nanos());
- EXPECT_TRUE(report.metrics(0).count_metrics().data(0).bucket_info(0).
- has_end_bucket_elapsed_nanos());
- EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count());
-}
+// TODO(b/149590301): Update this test to use new socket schema.
+//TEST(PartialBucketE2eTest, TestCountMetricWithoutSplit) {
+// shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
+// SendConfig(service, MakeConfig());
+// int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
+// // initialized with.
+//
+// service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
+// service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 2).get());
+//
+// ConfigMetricsReport report = GetReports(service->mProcessor, start + 3);
+// // Expect no metrics since the bucket has not finished yet.
+// EXPECT_EQ(1, report.metrics_size());
+// EXPECT_EQ(0, report.metrics(0).count_metrics().data_size());
+//}
+//
+//TEST(PartialBucketE2eTest, TestCountMetricNoSplitOnNewApp) {
+// shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
+// SendConfig(service, MakeConfig());
+// int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
+// // initialized with.
+//
+// // Force the uidmap to update at timestamp 2.
+// service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
+// // This is a new installation, so there shouldn't be a split (should be same as the without
+// // split case).
+// service->mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"),
+// String16(""));
+// // Goes into the second bucket.
+// service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get());
+//
+// ConfigMetricsReport report = GetReports(service->mProcessor, start + 4);
+// EXPECT_EQ(1, report.metrics_size());
+// EXPECT_EQ(0, report.metrics(0).count_metrics().data_size());
+//}
+//
+//TEST(PartialBucketE2eTest, TestCountMetricSplitOnUpgrade) {
+// shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
+// SendConfig(service, MakeConfig());
+// int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
+// // initialized with.
+// service->mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
+// {String16("")});
+//
+// // Force the uidmap to update at timestamp 2.
+// service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
+// service->mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"),
+// String16(""));
+// // Goes into the second bucket.
+// service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get());
+//
+// ConfigMetricsReport report = GetReports(service->mProcessor, start + 4);
+// backfillStartEndTimestamp(&report);
+//
+// ASSERT_EQ(1, report.metrics_size());
+// ASSERT_EQ(1, report.metrics(0).count_metrics().data_size());
+// ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size());
+// EXPECT_TRUE(report.metrics(0).count_metrics().data(0).bucket_info(0).
+// has_start_bucket_elapsed_nanos());
+// EXPECT_TRUE(report.metrics(0).count_metrics().data(0).bucket_info(0).
+// has_end_bucket_elapsed_nanos());
+// EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count());
+//}
+//
+//TEST(PartialBucketE2eTest, TestCountMetricSplitOnRemoval) {
+// shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
+// SendConfig(service, MakeConfig());
+// int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
+// // initialized with.
+// service->mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
+// {String16("")});
+//
+// // Force the uidmap to update at timestamp 2.
+// service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
+// service->mUidMap->removeApp(start + 2, String16(kApp1.c_str()), 1);
+// // Goes into the second bucket.
+// service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get());
+//
+// ConfigMetricsReport report = GetReports(service->mProcessor, start + 4);
+// backfillStartEndTimestamp(&report);
+//
+// ASSERT_EQ(1, report.metrics_size());
+// ASSERT_EQ(1, report.metrics(0).count_metrics().data_size());
+// ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size());
+// EXPECT_TRUE(report.metrics(0).count_metrics().data(0).bucket_info(0).
+// has_start_bucket_elapsed_nanos());
+// EXPECT_TRUE(report.metrics(0).count_metrics().data(0).bucket_info(0).
+// has_end_bucket_elapsed_nanos());
+// EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count());
+//}
TEST(PartialBucketE2eTest, TestValueMetricWithoutMinPartialBucket) {
shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
diff --git a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
index 9d39f9c..99dbaf1 100644
--- a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
@@ -64,316 +64,317 @@
} // namespace
-TEST(ValueMetricE2eTest, TestPulledEvents) {
- auto config = CreateStatsdConfig();
- int64_t baseTimeNs = getElapsedRealtimeNs();
- int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
- int64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
-
- ConfigKey cfgKey;
- auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
- SharedRefBase::make<FakeSubsystemSleepCallback>(),
- android::util::SUBSYSTEM_SLEEP_STATE);
- EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
- EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
- processor->mPullerManager->ForceClearPullerCache();
-
- int startBucketNum = processor->mMetricsManagers.begin()->second->
- mAllMetricProducers[0]->getCurrentBucketNum();
- EXPECT_GT(startBucketNum, (int64_t)0);
-
- // When creating the config, the value metric producer should register the alarm at the
- // end of the current bucket.
- EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
- EXPECT_EQ(bucketSizeNs,
- processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
- int64_t& expectedPullTimeNs =
- processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
- EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
-
- auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
- configAddedTimeNs + 55);
- processor->OnLogEvent(screenOffEvent.get());
-
- auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
- configAddedTimeNs + 65);
- processor->OnLogEvent(screenOnEvent.get());
-
- screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
- configAddedTimeNs + 75);
- processor->OnLogEvent(screenOffEvent.get());
-
- // Pulling alarm arrives on time and reset the sequential pulling alarm.
- processor->informPullAlarmFired(expectedPullTimeNs + 1);
- EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, expectedPullTimeNs);
-
- processor->informPullAlarmFired(expectedPullTimeNs + 1);
-
- screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
- configAddedTimeNs + 2 * bucketSizeNs + 15);
- processor->OnLogEvent(screenOnEvent.get());
-
- processor->informPullAlarmFired(expectedPullTimeNs + 1);
-
- processor->informPullAlarmFired(expectedPullTimeNs + 1);
-
- screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
- configAddedTimeNs + 4 * bucketSizeNs + 11);
- processor->OnLogEvent(screenOffEvent.get());
-
- processor->informPullAlarmFired(expectedPullTimeNs + 1);
-
- processor->informPullAlarmFired(expectedPullTimeNs + 1);
-
- ConfigMetricsReportList reports;
- vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
- ADB_DUMP, FAST, &buffer);
- EXPECT_TRUE(buffer.size() > 0);
- EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
- backfillDimensionPath(&reports);
- backfillStringInReport(&reports);
- backfillStartEndTimestamp(&reports);
- EXPECT_EQ(1, reports.reports_size());
- EXPECT_EQ(1, reports.reports(0).metrics_size());
- StatsLogReport::ValueMetricDataWrapper valueMetrics;
- sortMetricDataByDimensionsValue(
- reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
- EXPECT_GT((int)valueMetrics.data_size(), 1);
-
- auto data = valueMetrics.data(0);
- EXPECT_EQ(android::util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* subsystem name field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
- // We have 4 buckets, the first one was incomplete since the condition was unknown.
- EXPECT_EQ(4, data.bucket_info_size());
-
- EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
- EXPECT_EQ(1, data.bucket_info(0).values_size());
-
- EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
- EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
- EXPECT_EQ(1, data.bucket_info(1).values_size());
-
- EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
- EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
- EXPECT_EQ(1, data.bucket_info(2).values_size());
-
- EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(3).start_bucket_elapsed_nanos());
- EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(3).end_bucket_elapsed_nanos());
- EXPECT_EQ(1, data.bucket_info(3).values_size());
-}
-
-TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm) {
- auto config = CreateStatsdConfig();
- int64_t baseTimeNs = getElapsedRealtimeNs();
- // 10 mins == 2 bucket durations.
- int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
- int64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
-
- ConfigKey cfgKey;
- auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
- SharedRefBase::make<FakeSubsystemSleepCallback>(),
- android::util::SUBSYSTEM_SLEEP_STATE);
- EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
- EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
- processor->mPullerManager->ForceClearPullerCache();
-
- int startBucketNum = processor->mMetricsManagers.begin()->second->
- mAllMetricProducers[0]->getCurrentBucketNum();
- EXPECT_GT(startBucketNum, (int64_t)0);
-
- // When creating the config, the value metric producer should register the alarm at the
- // end of the current bucket.
- EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
- EXPECT_EQ(bucketSizeNs,
- processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
- int64_t& expectedPullTimeNs =
- processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
- EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
-
- // Screen off/on/off events.
- auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
- configAddedTimeNs + 55);
- processor->OnLogEvent(screenOffEvent.get());
-
- auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
- configAddedTimeNs + 65);
- processor->OnLogEvent(screenOnEvent.get());
-
- screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
- configAddedTimeNs + 75);
- processor->OnLogEvent(screenOffEvent.get());
-
- // Pulling alarm arrives late by 2 buckets and 1 ns. 2 buckets late is too far away in the
- // future, data will be skipped.
- processor->informPullAlarmFired(expectedPullTimeNs + 2 * bucketSizeNs + 1);
- EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, expectedPullTimeNs);
-
- // This screen state change will start a new bucket.
- screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
- configAddedTimeNs + 4 * bucketSizeNs + 65);
- processor->OnLogEvent(screenOnEvent.get());
-
- // The alarm is delayed but we already created a bucket thanks to the screen state condition.
- // This bucket does not have to be skipped since the alarm arrives in time for the next bucket.
- processor->informPullAlarmFired(expectedPullTimeNs + bucketSizeNs + 21);
- EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, expectedPullTimeNs);
-
- screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
- configAddedTimeNs + 6 * bucketSizeNs + 31);
- processor->OnLogEvent(screenOffEvent.get());
-
- processor->informPullAlarmFired(expectedPullTimeNs + bucketSizeNs + 21);
- EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 8 * bucketSizeNs, expectedPullTimeNs);
-
- processor->informPullAlarmFired(expectedPullTimeNs + 1);
- EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 9 * bucketSizeNs, expectedPullTimeNs);
-
- ConfigMetricsReportList reports;
- vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, configAddedTimeNs + 9 * bucketSizeNs + 10, false, true,
- ADB_DUMP, FAST, &buffer);
- EXPECT_TRUE(buffer.size() > 0);
- EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
- backfillDimensionPath(&reports);
- backfillStringInReport(&reports);
- backfillStartEndTimestamp(&reports);
- EXPECT_EQ(1, reports.reports_size());
- EXPECT_EQ(1, reports.reports(0).metrics_size());
- StatsLogReport::ValueMetricDataWrapper valueMetrics;
- sortMetricDataByDimensionsValue(
- reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
- EXPECT_GT((int)valueMetrics.data_size(), 1);
-
- auto data = valueMetrics.data(0);
- EXPECT_EQ(android::util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* subsystem name field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
- EXPECT_EQ(3, data.bucket_info_size());
-
- EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
- EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
- EXPECT_EQ(1, data.bucket_info(0).values_size());
-
- EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
- EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
- EXPECT_EQ(1, data.bucket_info(1).values_size());
-
- EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
- EXPECT_EQ(baseTimeNs + 10 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
- EXPECT_EQ(1, data.bucket_info(2).values_size());
-}
-
-TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation) {
- auto config = CreateStatsdConfig(false);
- int64_t baseTimeNs = getElapsedRealtimeNs();
- int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
- int64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
-
- auto batterySaverStartMatcher = CreateBatterySaverModeStartAtomMatcher();
- *config.add_atom_matcher() = batterySaverStartMatcher;
- const int64_t ttlNs = 2 * bucketSizeNs; // Two buckets.
- auto metric_activation = config.add_metric_activation();
- metric_activation->set_metric_id(metricId);
- metric_activation->set_activation_type(ACTIVATE_IMMEDIATELY);
- auto event_activation = metric_activation->add_event_activation();
- event_activation->set_atom_matcher_id(batterySaverStartMatcher.id());
- event_activation->set_ttl_seconds(ttlNs / 1000000000);
-
- ConfigKey cfgKey;
- auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
- SharedRefBase::make<FakeSubsystemSleepCallback>(),
- android::util::SUBSYSTEM_SLEEP_STATE);
- EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
- EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
- processor->mPullerManager->ForceClearPullerCache();
-
- int startBucketNum = processor->mMetricsManagers.begin()->second->
- mAllMetricProducers[0]->getCurrentBucketNum();
- EXPECT_GT(startBucketNum, (int64_t)0);
- EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
-
- // When creating the config, the value metric producer should register the alarm at the
- // end of the current bucket.
- EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
- EXPECT_EQ(bucketSizeNs,
- processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
- int64_t& expectedPullTimeNs =
- processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
- EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
-
- // Pulling alarm arrives on time and reset the sequential pulling alarm.
- processor->informPullAlarmFired(expectedPullTimeNs + 1); // 15 mins + 1 ns.
- EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, expectedPullTimeNs);
- EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
-
- // Activate the metric. A pull occurs here
- const int64_t activationNs = configAddedTimeNs + bucketSizeNs + (2 * 1000 * 1000); // 2 millis.
- auto batterySaverOnEvent = CreateBatterySaverOnEvent(activationNs);
- processor->OnLogEvent(batterySaverOnEvent.get()); // 15 mins + 2 ms.
- EXPECT_TRUE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
-
- processor->informPullAlarmFired(expectedPullTimeNs + 1); // 20 mins + 1 ns.
- EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs, expectedPullTimeNs);
-
- processor->informPullAlarmFired(expectedPullTimeNs + 2); // 25 mins + 2 ns.
- EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, expectedPullTimeNs);
-
- // Create random event to deactivate metric.
- auto deactivationEvent = CreateScreenBrightnessChangedEvent(50, activationNs + ttlNs + 1);
- processor->OnLogEvent(deactivationEvent.get());
- EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
-
- processor->informPullAlarmFired(expectedPullTimeNs + 3);
- EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, expectedPullTimeNs);
-
- processor->informPullAlarmFired(expectedPullTimeNs + 4);
- EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, expectedPullTimeNs);
-
- ConfigMetricsReportList reports;
- vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
- ADB_DUMP, FAST, &buffer);
- EXPECT_TRUE(buffer.size() > 0);
- EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
- backfillDimensionPath(&reports);
- backfillStringInReport(&reports);
- backfillStartEndTimestamp(&reports);
- EXPECT_EQ(1, reports.reports_size());
- EXPECT_EQ(1, reports.reports(0).metrics_size());
- StatsLogReport::ValueMetricDataWrapper valueMetrics;
- sortMetricDataByDimensionsValue(
- reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
- EXPECT_GT((int)valueMetrics.data_size(), 0);
-
- auto data = valueMetrics.data(0);
- EXPECT_EQ(android::util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
- EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
- EXPECT_EQ(1 /* subsystem name field */,
- data.dimensions_in_what().value_tuple().dimensions_value(0).field());
- EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
- // We have 2 full buckets, the two surrounding the activation are dropped.
- EXPECT_EQ(2, data.bucket_info_size());
-
- auto bucketInfo = data.bucket_info(0);
- EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
- EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
- EXPECT_EQ(1, bucketInfo.values_size());
-
- bucketInfo = data.bucket_info(1);
- EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
- EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
- EXPECT_EQ(1, bucketInfo.values_size());
-}
+// TODO(b/149590301): Update this test to use new socket schema.
+//TEST(ValueMetricE2eTest, TestPulledEvents) {
+// auto config = CreateStatsdConfig();
+// int64_t baseTimeNs = getElapsedRealtimeNs();
+// int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
+// int64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
+//
+// ConfigKey cfgKey;
+// auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
+// SharedRefBase::make<FakeSubsystemSleepCallback>(),
+// android::util::SUBSYSTEM_SLEEP_STATE);
+// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+// processor->mPullerManager->ForceClearPullerCache();
+//
+// int startBucketNum = processor->mMetricsManagers.begin()->second->
+// mAllMetricProducers[0]->getCurrentBucketNum();
+// EXPECT_GT(startBucketNum, (int64_t)0);
+//
+// // When creating the config, the value metric producer should register the alarm at the
+// // end of the current bucket.
+// EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
+// EXPECT_EQ(bucketSizeNs,
+// processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
+// int64_t& expectedPullTimeNs =
+// processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
+// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
+//
+// auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+// configAddedTimeNs + 55);
+// processor->OnLogEvent(screenOffEvent.get());
+//
+// auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+// configAddedTimeNs + 65);
+// processor->OnLogEvent(screenOnEvent.get());
+//
+// screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+// configAddedTimeNs + 75);
+// processor->OnLogEvent(screenOffEvent.get());
+//
+// // Pulling alarm arrives on time and reset the sequential pulling alarm.
+// processor->informPullAlarmFired(expectedPullTimeNs + 1);
+// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, expectedPullTimeNs);
+//
+// processor->informPullAlarmFired(expectedPullTimeNs + 1);
+//
+// screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+// configAddedTimeNs + 2 * bucketSizeNs + 15);
+// processor->OnLogEvent(screenOnEvent.get());
+//
+// processor->informPullAlarmFired(expectedPullTimeNs + 1);
+//
+// processor->informPullAlarmFired(expectedPullTimeNs + 1);
+//
+// screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+// configAddedTimeNs + 4 * bucketSizeNs + 11);
+// processor->OnLogEvent(screenOffEvent.get());
+//
+// processor->informPullAlarmFired(expectedPullTimeNs + 1);
+//
+// processor->informPullAlarmFired(expectedPullTimeNs + 1);
+//
+// ConfigMetricsReportList reports;
+// vector<uint8_t> buffer;
+// processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
+// ADB_DUMP, FAST, &buffer);
+// EXPECT_TRUE(buffer.size() > 0);
+// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+// backfillDimensionPath(&reports);
+// backfillStringInReport(&reports);
+// backfillStartEndTimestamp(&reports);
+// EXPECT_EQ(1, reports.reports_size());
+// EXPECT_EQ(1, reports.reports(0).metrics_size());
+// StatsLogReport::ValueMetricDataWrapper valueMetrics;
+// sortMetricDataByDimensionsValue(
+// reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
+// EXPECT_GT((int)valueMetrics.data_size(), 1);
+//
+// auto data = valueMetrics.data(0);
+// EXPECT_EQ(android::util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* subsystem name field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
+// // We have 4 buckets, the first one was incomplete since the condition was unknown.
+// EXPECT_EQ(4, data.bucket_info_size());
+//
+// EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+// EXPECT_EQ(1, data.bucket_info(0).values_size());
+//
+// EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
+// EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
+// EXPECT_EQ(1, data.bucket_info(1).values_size());
+//
+// EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
+// EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
+// EXPECT_EQ(1, data.bucket_info(2).values_size());
+//
+// EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(3).start_bucket_elapsed_nanos());
+// EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(3).end_bucket_elapsed_nanos());
+// EXPECT_EQ(1, data.bucket_info(3).values_size());
+//}
+//
+//TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm) {
+// auto config = CreateStatsdConfig();
+// int64_t baseTimeNs = getElapsedRealtimeNs();
+// // 10 mins == 2 bucket durations.
+// int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
+// int64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
+//
+// ConfigKey cfgKey;
+// auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
+// SharedRefBase::make<FakeSubsystemSleepCallback>(),
+// android::util::SUBSYSTEM_SLEEP_STATE);
+// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+// processor->mPullerManager->ForceClearPullerCache();
+//
+// int startBucketNum = processor->mMetricsManagers.begin()->second->
+// mAllMetricProducers[0]->getCurrentBucketNum();
+// EXPECT_GT(startBucketNum, (int64_t)0);
+//
+// // When creating the config, the value metric producer should register the alarm at the
+// // end of the current bucket.
+// EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
+// EXPECT_EQ(bucketSizeNs,
+// processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
+// int64_t& expectedPullTimeNs =
+// processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
+// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
+//
+// // Screen off/on/off events.
+// auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+// configAddedTimeNs + 55);
+// processor->OnLogEvent(screenOffEvent.get());
+//
+// auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+// configAddedTimeNs + 65);
+// processor->OnLogEvent(screenOnEvent.get());
+//
+// screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+// configAddedTimeNs + 75);
+// processor->OnLogEvent(screenOffEvent.get());
+//
+// // Pulling alarm arrives late by 2 buckets and 1 ns. 2 buckets late is too far away in the
+// // future, data will be skipped.
+// processor->informPullAlarmFired(expectedPullTimeNs + 2 * bucketSizeNs + 1);
+// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, expectedPullTimeNs);
+//
+// // This screen state change will start a new bucket.
+// screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+// configAddedTimeNs + 4 * bucketSizeNs + 65);
+// processor->OnLogEvent(screenOnEvent.get());
+//
+// // The alarm is delayed but we already created a bucket thanks to the screen state condition.
+// // This bucket does not have to be skipped since the alarm arrives in time for the next bucket.
+// processor->informPullAlarmFired(expectedPullTimeNs + bucketSizeNs + 21);
+// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, expectedPullTimeNs);
+//
+// screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+// configAddedTimeNs + 6 * bucketSizeNs + 31);
+// processor->OnLogEvent(screenOffEvent.get());
+//
+// processor->informPullAlarmFired(expectedPullTimeNs + bucketSizeNs + 21);
+// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 8 * bucketSizeNs, expectedPullTimeNs);
+//
+// processor->informPullAlarmFired(expectedPullTimeNs + 1);
+// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 9 * bucketSizeNs, expectedPullTimeNs);
+//
+// ConfigMetricsReportList reports;
+// vector<uint8_t> buffer;
+// processor->onDumpReport(cfgKey, configAddedTimeNs + 9 * bucketSizeNs + 10, false, true,
+// ADB_DUMP, FAST, &buffer);
+// EXPECT_TRUE(buffer.size() > 0);
+// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+// backfillDimensionPath(&reports);
+// backfillStringInReport(&reports);
+// backfillStartEndTimestamp(&reports);
+// EXPECT_EQ(1, reports.reports_size());
+// EXPECT_EQ(1, reports.reports(0).metrics_size());
+// StatsLogReport::ValueMetricDataWrapper valueMetrics;
+// sortMetricDataByDimensionsValue(
+// reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
+// EXPECT_GT((int)valueMetrics.data_size(), 1);
+//
+// auto data = valueMetrics.data(0);
+// EXPECT_EQ(android::util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* subsystem name field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
+// EXPECT_EQ(3, data.bucket_info_size());
+//
+// EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+// EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+// EXPECT_EQ(1, data.bucket_info(0).values_size());
+//
+// EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
+// EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
+// EXPECT_EQ(1, data.bucket_info(1).values_size());
+//
+// EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
+// EXPECT_EQ(baseTimeNs + 10 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
+// EXPECT_EQ(1, data.bucket_info(2).values_size());
+//}
+//
+//TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation) {
+// auto config = CreateStatsdConfig(false);
+// int64_t baseTimeNs = getElapsedRealtimeNs();
+// int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
+// int64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
+//
+// auto batterySaverStartMatcher = CreateBatterySaverModeStartAtomMatcher();
+// *config.add_atom_matcher() = batterySaverStartMatcher;
+// const int64_t ttlNs = 2 * bucketSizeNs; // Two buckets.
+// auto metric_activation = config.add_metric_activation();
+// metric_activation->set_metric_id(metricId);
+// metric_activation->set_activation_type(ACTIVATE_IMMEDIATELY);
+// auto event_activation = metric_activation->add_event_activation();
+// event_activation->set_atom_matcher_id(batterySaverStartMatcher.id());
+// event_activation->set_ttl_seconds(ttlNs / 1000000000);
+//
+// ConfigKey cfgKey;
+// auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
+// SharedRefBase::make<FakeSubsystemSleepCallback>(),
+// android::util::SUBSYSTEM_SLEEP_STATE);
+// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+// processor->mPullerManager->ForceClearPullerCache();
+//
+// int startBucketNum = processor->mMetricsManagers.begin()->second->
+// mAllMetricProducers[0]->getCurrentBucketNum();
+// EXPECT_GT(startBucketNum, (int64_t)0);
+// EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
+//
+// // When creating the config, the value metric producer should register the alarm at the
+// // end of the current bucket.
+// EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
+// EXPECT_EQ(bucketSizeNs,
+// processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
+// int64_t& expectedPullTimeNs =
+// processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
+// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
+//
+// // Pulling alarm arrives on time and reset the sequential pulling alarm.
+// processor->informPullAlarmFired(expectedPullTimeNs + 1); // 15 mins + 1 ns.
+// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, expectedPullTimeNs);
+// EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
+//
+// // Activate the metric. A pull occurs here
+// const int64_t activationNs = configAddedTimeNs + bucketSizeNs + (2 * 1000 * 1000); // 2 millis.
+// auto batterySaverOnEvent = CreateBatterySaverOnEvent(activationNs);
+// processor->OnLogEvent(batterySaverOnEvent.get()); // 15 mins + 2 ms.
+// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
+//
+// processor->informPullAlarmFired(expectedPullTimeNs + 1); // 20 mins + 1 ns.
+// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs, expectedPullTimeNs);
+//
+// processor->informPullAlarmFired(expectedPullTimeNs + 2); // 25 mins + 2 ns.
+// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, expectedPullTimeNs);
+//
+// // Create random event to deactivate metric.
+// auto deactivationEvent = CreateScreenBrightnessChangedEvent(50, activationNs + ttlNs + 1);
+// processor->OnLogEvent(deactivationEvent.get());
+// EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
+//
+// processor->informPullAlarmFired(expectedPullTimeNs + 3);
+// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, expectedPullTimeNs);
+//
+// processor->informPullAlarmFired(expectedPullTimeNs + 4);
+// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, expectedPullTimeNs);
+//
+// ConfigMetricsReportList reports;
+// vector<uint8_t> buffer;
+// processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
+// ADB_DUMP, FAST, &buffer);
+// EXPECT_TRUE(buffer.size() > 0);
+// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+// backfillDimensionPath(&reports);
+// backfillStringInReport(&reports);
+// backfillStartEndTimestamp(&reports);
+// EXPECT_EQ(1, reports.reports_size());
+// EXPECT_EQ(1, reports.reports(0).metrics_size());
+// StatsLogReport::ValueMetricDataWrapper valueMetrics;
+// sortMetricDataByDimensionsValue(
+// reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
+// EXPECT_GT((int)valueMetrics.data_size(), 0);
+//
+// auto data = valueMetrics.data(0);
+// EXPECT_EQ(android::util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
+// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+// EXPECT_EQ(1 /* subsystem name field */,
+// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+// EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
+// // We have 2 full buckets, the two surrounding the activation are dropped.
+// EXPECT_EQ(2, data.bucket_info_size());
+//
+// auto bucketInfo = data.bucket_info(0);
+// EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
+// EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
+// EXPECT_EQ(1, bucketInfo.values_size());
+//
+// bucketInfo = data.bucket_info(1);
+// EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
+// EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
+// EXPECT_EQ(1, bucketInfo.values_size());
+//}
/**
* Test initialization of a simple value metric that is sliced by a state.
diff --git a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
index e13bf14..21092e2 100644
--- a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
@@ -69,282 +69,284 @@
CreateAttribution(222, "GMSCoreModule1"),
CreateAttribution(222, "GMSCoreModule2")};
-/*
-Events:
-Screen off is met from (200ns,1 min+500ns].
-Acquire event for wl1 from 2ns to 1min+2ns
-Acquire event for wl2 from 1min-10ns to 2min-15ns
-*/
-void FeedEvents(StatsdConfig config, sp<StatsLogProcessor> processor) {
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
-
- auto screenTurnedOnEvent = CreateScreenStateChangedEvent(
- android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 1);
- auto screenTurnedOffEvent = CreateScreenStateChangedEvent(
- android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 200);
- auto screenTurnedOnEvent2 =
- CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
- bucketStartTimeNs + bucketSizeNs + 500);
-
- auto acquireEvent1 = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 2);
- auto releaseEvent1 =
- CreateReleaseWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 2);
- auto acquireEvent2 =
- CreateAcquireWakelockEvent(attributions2, "wl2", bucketStartTimeNs + bucketSizeNs - 10);
- auto releaseEvent2 = CreateReleaseWakelockEvent(attributions2, "wl2",
- bucketStartTimeNs + 2 * bucketSizeNs - 15);
-
- std::vector<std::unique_ptr<LogEvent>> events;
-
- events.push_back(std::move(screenTurnedOnEvent));
- events.push_back(std::move(screenTurnedOffEvent));
- events.push_back(std::move(screenTurnedOnEvent2));
- events.push_back(std::move(acquireEvent1));
- events.push_back(std::move(acquireEvent2));
- events.push_back(std::move(releaseEvent1));
- events.push_back(std::move(releaseEvent2));
-
- sortLogEventsByTimestamp(&events);
-
- for (const auto& event : events) {
- processor->OnLogEvent(event.get());
- }
-}
+// TODO(b/149590301): Update this helper to use new socket schema.
+///*
+//Events:
+//Screen off is met from (200ns,1 min+500ns].
+//Acquire event for wl1 from 2ns to 1min+2ns
+//Acquire event for wl2 from 1min-10ns to 2min-15ns
+//*/
+//void FeedEvents(StatsdConfig config, sp<StatsLogProcessor> processor) {
+// uint64_t bucketStartTimeNs = 10000000000;
+// uint64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+//
+// auto screenTurnedOnEvent = CreateScreenStateChangedEvent(
+// android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 1);
+// auto screenTurnedOffEvent = CreateScreenStateChangedEvent(
+// android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 200);
+// auto screenTurnedOnEvent2 =
+// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+// bucketStartTimeNs + bucketSizeNs + 500);
+//
+// auto acquireEvent1 = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 2);
+// auto releaseEvent1 =
+// CreateReleaseWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 2);
+// auto acquireEvent2 =
+// CreateAcquireWakelockEvent(attributions2, "wl2", bucketStartTimeNs + bucketSizeNs - 10);
+// auto releaseEvent2 = CreateReleaseWakelockEvent(attributions2, "wl2",
+// bucketStartTimeNs + 2 * bucketSizeNs - 15);
+//
+// std::vector<std::unique_ptr<LogEvent>> events;
+//
+// events.push_back(std::move(screenTurnedOnEvent));
+// events.push_back(std::move(screenTurnedOffEvent));
+// events.push_back(std::move(screenTurnedOnEvent2));
+// events.push_back(std::move(acquireEvent1));
+// events.push_back(std::move(acquireEvent2));
+// events.push_back(std::move(releaseEvent1));
+// events.push_back(std::move(releaseEvent2));
+//
+// sortLogEventsByTimestamp(&events);
+//
+// for (const auto& event : events) {
+// processor->OnLogEvent(event.get());
+// }
+//}
} // namespace
-TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration1) {
- ConfigKey cfgKey;
- auto config = CreateStatsdConfig(DurationMetric::SUM);
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
- auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
- EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
- EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
- FeedEvents(config, processor);
- vector<uint8_t> buffer;
- ConfigMetricsReportList reports;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true,
- ADB_DUMP, FAST, &buffer);
- EXPECT_TRUE(buffer.size() > 0);
- EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
- backfillDimensionPath(&reports);
- backfillStringInReport(&reports);
- backfillStartEndTimestamp(&reports);
-
- EXPECT_EQ(reports.reports_size(), 1);
- EXPECT_EQ(reports.reports(0).metrics_size(), 1);
- // Only 1 dimension output. The tag dimension in the predicate has been aggregated.
- EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
-
- auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
- // Validate dimension value.
- ValidateAttributionUidDimension(data.dimensions_in_what(),
- android::util::WAKELOCK_STATE_CHANGED, 111);
- // Validate bucket info.
- EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 1);
- data = reports.reports(0).metrics(0).duration_metrics().data(0);
- // The wakelock holding interval starts from the screen off event and to the end of the 1st
- // bucket.
- EXPECT_EQ((unsigned long long)data.bucket_info(0).duration_nanos(), bucketSizeNs - 200);
-}
-
-TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration2) {
- ConfigKey cfgKey;
- auto config = CreateStatsdConfig(DurationMetric::SUM);
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
- auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
- EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
- EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
- FeedEvents(config, processor);
- vector<uint8_t> buffer;
- ConfigMetricsReportList reports;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
- ADB_DUMP, FAST, &buffer);
- EXPECT_TRUE(buffer.size() > 0);
- EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
- backfillDimensionPath(&reports);
- backfillStringInReport(&reports);
- backfillStartEndTimestamp(&reports);
- EXPECT_EQ(reports.reports_size(), 1);
- EXPECT_EQ(reports.reports(0).metrics_size(), 1);
- EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
- // Dump the report after the end of 2nd bucket.
- EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 2);
- auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
- // Validate dimension value.
- ValidateAttributionUidDimension(data.dimensions_in_what(),
- android::util::WAKELOCK_STATE_CHANGED, 111);
- // Two output buckets.
- // The wakelock holding interval in the 1st bucket starts from the screen off event and to
- // the end of the 1st bucket.
- EXPECT_EQ((unsigned long long)data.bucket_info(0).duration_nanos(),
- bucketStartTimeNs + bucketSizeNs - (bucketStartTimeNs + 200));
- // The wakelock holding interval in the 2nd bucket starts at the beginning of the bucket and
- // ends at the second screen on event.
- EXPECT_EQ((unsigned long long)data.bucket_info(1).duration_nanos(), 500UL);
-}
-TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration3) {
- ConfigKey cfgKey;
- auto config = CreateStatsdConfig(DurationMetric::SUM);
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
- auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
- EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
- EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
- FeedEvents(config, processor);
- vector<uint8_t> buffer;
- ConfigMetricsReportList reports;
-
- std::vector<std::unique_ptr<LogEvent>> events;
- events.push_back(
- CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
- bucketStartTimeNs + 2 * bucketSizeNs + 90));
- events.push_back(CreateAcquireWakelockEvent(attributions1, "wl3",
- bucketStartTimeNs + 2 * bucketSizeNs + 100));
- events.push_back(CreateReleaseWakelockEvent(attributions1, "wl3",
- bucketStartTimeNs + 5 * bucketSizeNs + 100));
- sortLogEventsByTimestamp(&events);
- for (const auto& event : events) {
- processor->OnLogEvent(event.get());
- }
-
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, false, true,
- ADB_DUMP, FAST, &buffer);
- EXPECT_TRUE(buffer.size() > 0);
- EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
- backfillDimensionPath(&reports);
- backfillStringInReport(&reports);
- backfillStartEndTimestamp(&reports);
- EXPECT_EQ(reports.reports_size(), 1);
- EXPECT_EQ(reports.reports(0).metrics_size(), 1);
- EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
- EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 6);
- auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
- ValidateAttributionUidDimension(data.dimensions_in_what(),
- android::util::WAKELOCK_STATE_CHANGED, 111);
- // The last wakelock holding spans 4 buckets.
- EXPECT_EQ((unsigned long long)data.bucket_info(2).duration_nanos(), bucketSizeNs - 100);
- EXPECT_EQ((unsigned long long)data.bucket_info(3).duration_nanos(), bucketSizeNs);
- EXPECT_EQ((unsigned long long)data.bucket_info(4).duration_nanos(), bucketSizeNs);
- EXPECT_EQ((unsigned long long)data.bucket_info(5).duration_nanos(), 100UL);
-}
-
-TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration1) {
- ConfigKey cfgKey;
- auto config = CreateStatsdConfig(DurationMetric::MAX_SPARSE);
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
- auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
- EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
- EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
- FeedEvents(config, processor);
- ConfigMetricsReportList reports;
- vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true,
- ADB_DUMP, FAST, &buffer);
- EXPECT_TRUE(buffer.size() > 0);
-
- EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
- backfillDimensionPath(&reports);
- backfillStringInReport(&reports);
- backfillStartEndTimestamp(&reports);
-
- EXPECT_EQ(reports.reports_size(), 1);
-
- // When using ProtoOutputStream, if nothing written to a sub msg, it won't be treated as
- // one. It was previsouly 1 because we had a fake onDumpReport which calls add_metric() by
- // itself.
- EXPECT_EQ(1, reports.reports(0).metrics_size());
- EXPECT_EQ(0, reports.reports(0).metrics(0).duration_metrics().data_size());
-}
-
-TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration2) {
- ConfigKey cfgKey;
- auto config = CreateStatsdConfig(DurationMetric::MAX_SPARSE);
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
- auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
- EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
- EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
- FeedEvents(config, processor);
- ConfigMetricsReportList reports;
- vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
- ADB_DUMP, FAST, &buffer);
- EXPECT_TRUE(buffer.size() > 0);
- EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
- backfillDimensionPath(&reports);
- backfillStringInReport(&reports);
- backfillStartEndTimestamp(&reports);
- EXPECT_EQ(reports.reports_size(), 1);
- EXPECT_EQ(reports.reports(0).metrics_size(), 1);
- EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
- // Dump the report after the end of 2nd bucket. One dimension with one bucket.
- EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 1);
- auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
- // Validate dimension value.
- ValidateAttributionUidDimension(data.dimensions_in_what(),
- android::util::WAKELOCK_STATE_CHANGED, 111);
- // The max is acquire event for wl1 to screen off start.
- EXPECT_EQ((unsigned long long)data.bucket_info(0).duration_nanos(), bucketSizeNs + 2 - 200);
-}
-
-TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration3) {
- ConfigKey cfgKey;
- auto config = CreateStatsdConfig(DurationMetric::MAX_SPARSE);
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
- auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
- EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
- EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
- FeedEvents(config, processor);
- ConfigMetricsReportList reports;
- vector<uint8_t> buffer;
-
- std::vector<std::unique_ptr<LogEvent>> events;
- events.push_back(
- CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
- bucketStartTimeNs + 2 * bucketSizeNs + 90));
- events.push_back(CreateAcquireWakelockEvent(attributions1, "wl3",
- bucketStartTimeNs + 2 * bucketSizeNs + 100));
- events.push_back(CreateReleaseWakelockEvent(attributions1, "wl3",
- bucketStartTimeNs + 5 * bucketSizeNs + 100));
- sortLogEventsByTimestamp(&events);
- for (const auto& event : events) {
- processor->OnLogEvent(event.get());
- }
-
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, false, true,
- ADB_DUMP, FAST, &buffer);
- EXPECT_TRUE(buffer.size() > 0);
- EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
- backfillDimensionPath(&reports);
- backfillStringInReport(&reports);
- backfillStartEndTimestamp(&reports);
- EXPECT_EQ(reports.reports_size(), 1);
- EXPECT_EQ(reports.reports(0).metrics_size(), 1);
- EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
- EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 2);
- auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
- ValidateAttributionUidDimension(data.dimensions_in_what(),
- android::util::WAKELOCK_STATE_CHANGED, 111);
- // The last wakelock holding spans 4 buckets.
- EXPECT_EQ((unsigned long long)data.bucket_info(1).duration_nanos(), 3 * bucketSizeNs);
- EXPECT_EQ((unsigned long long)data.bucket_info(1).start_bucket_elapsed_nanos(),
- bucketStartTimeNs + 5 * bucketSizeNs);
- EXPECT_EQ((unsigned long long)data.bucket_info(1).end_bucket_elapsed_nanos(),
- bucketStartTimeNs + 6 * bucketSizeNs);
-}
+// TODO(b/149590301): Update these tests to use new socket schema.
+//TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration1) {
+// ConfigKey cfgKey;
+// auto config = CreateStatsdConfig(DurationMetric::SUM);
+// uint64_t bucketStartTimeNs = 10000000000;
+// uint64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+// FeedEvents(config, processor);
+// vector<uint8_t> buffer;
+// ConfigMetricsReportList reports;
+// processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true,
+// ADB_DUMP, FAST, &buffer);
+// EXPECT_TRUE(buffer.size() > 0);
+// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+// backfillDimensionPath(&reports);
+// backfillStringInReport(&reports);
+// backfillStartEndTimestamp(&reports);
+//
+// EXPECT_EQ(reports.reports_size(), 1);
+// EXPECT_EQ(reports.reports(0).metrics_size(), 1);
+// // Only 1 dimension output. The tag dimension in the predicate has been aggregated.
+// EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
+//
+// auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
+// // Validate dimension value.
+// ValidateAttributionUidDimension(data.dimensions_in_what(),
+// android::util::WAKELOCK_STATE_CHANGED, 111);
+// // Validate bucket info.
+// EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 1);
+// data = reports.reports(0).metrics(0).duration_metrics().data(0);
+// // The wakelock holding interval starts from the screen off event and to the end of the 1st
+// // bucket.
+// EXPECT_EQ((unsigned long long)data.bucket_info(0).duration_nanos(), bucketSizeNs - 200);
+//}
+//
+//TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration2) {
+// ConfigKey cfgKey;
+// auto config = CreateStatsdConfig(DurationMetric::SUM);
+// uint64_t bucketStartTimeNs = 10000000000;
+// uint64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+// FeedEvents(config, processor);
+// vector<uint8_t> buffer;
+// ConfigMetricsReportList reports;
+// processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
+// ADB_DUMP, FAST, &buffer);
+// EXPECT_TRUE(buffer.size() > 0);
+// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+// backfillDimensionPath(&reports);
+// backfillStringInReport(&reports);
+// backfillStartEndTimestamp(&reports);
+// EXPECT_EQ(reports.reports_size(), 1);
+// EXPECT_EQ(reports.reports(0).metrics_size(), 1);
+// EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
+// // Dump the report after the end of 2nd bucket.
+// EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 2);
+// auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
+// // Validate dimension value.
+// ValidateAttributionUidDimension(data.dimensions_in_what(),
+// android::util::WAKELOCK_STATE_CHANGED, 111);
+// // Two output buckets.
+// // The wakelock holding interval in the 1st bucket starts from the screen off event and to
+// // the end of the 1st bucket.
+// EXPECT_EQ((unsigned long long)data.bucket_info(0).duration_nanos(),
+// bucketStartTimeNs + bucketSizeNs - (bucketStartTimeNs + 200));
+// // The wakelock holding interval in the 2nd bucket starts at the beginning of the bucket and
+// // ends at the second screen on event.
+// EXPECT_EQ((unsigned long long)data.bucket_info(1).duration_nanos(), 500UL);
+//}
+//TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration3) {
+// ConfigKey cfgKey;
+// auto config = CreateStatsdConfig(DurationMetric::SUM);
+// uint64_t bucketStartTimeNs = 10000000000;
+// uint64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+// FeedEvents(config, processor);
+// vector<uint8_t> buffer;
+// ConfigMetricsReportList reports;
+//
+// std::vector<std::unique_ptr<LogEvent>> events;
+// events.push_back(
+// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+// bucketStartTimeNs + 2 * bucketSizeNs + 90));
+// events.push_back(CreateAcquireWakelockEvent(attributions1, "wl3",
+// bucketStartTimeNs + 2 * bucketSizeNs + 100));
+// events.push_back(CreateReleaseWakelockEvent(attributions1, "wl3",
+// bucketStartTimeNs + 5 * bucketSizeNs + 100));
+// sortLogEventsByTimestamp(&events);
+// for (const auto& event : events) {
+// processor->OnLogEvent(event.get());
+// }
+//
+// processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, false, true,
+// ADB_DUMP, FAST, &buffer);
+// EXPECT_TRUE(buffer.size() > 0);
+// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+// backfillDimensionPath(&reports);
+// backfillStringInReport(&reports);
+// backfillStartEndTimestamp(&reports);
+// EXPECT_EQ(reports.reports_size(), 1);
+// EXPECT_EQ(reports.reports(0).metrics_size(), 1);
+// EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
+// EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 6);
+// auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
+// ValidateAttributionUidDimension(data.dimensions_in_what(),
+// android::util::WAKELOCK_STATE_CHANGED, 111);
+// // The last wakelock holding spans 4 buckets.
+// EXPECT_EQ((unsigned long long)data.bucket_info(2).duration_nanos(), bucketSizeNs - 100);
+// EXPECT_EQ((unsigned long long)data.bucket_info(3).duration_nanos(), bucketSizeNs);
+// EXPECT_EQ((unsigned long long)data.bucket_info(4).duration_nanos(), bucketSizeNs);
+// EXPECT_EQ((unsigned long long)data.bucket_info(5).duration_nanos(), 100UL);
+//}
+//
+//TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration1) {
+// ConfigKey cfgKey;
+// auto config = CreateStatsdConfig(DurationMetric::MAX_SPARSE);
+// uint64_t bucketStartTimeNs = 10000000000;
+// uint64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+// FeedEvents(config, processor);
+// ConfigMetricsReportList reports;
+// vector<uint8_t> buffer;
+// processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true,
+// ADB_DUMP, FAST, &buffer);
+// EXPECT_TRUE(buffer.size() > 0);
+//
+// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+// backfillDimensionPath(&reports);
+// backfillStringInReport(&reports);
+// backfillStartEndTimestamp(&reports);
+//
+// EXPECT_EQ(reports.reports_size(), 1);
+//
+// // When using ProtoOutputStream, if nothing written to a sub msg, it won't be treated as
+// // one. It was previsouly 1 because we had a fake onDumpReport which calls add_metric() by
+// // itself.
+// EXPECT_EQ(1, reports.reports(0).metrics_size());
+// EXPECT_EQ(0, reports.reports(0).metrics(0).duration_metrics().data_size());
+//}
+//
+//TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration2) {
+// ConfigKey cfgKey;
+// auto config = CreateStatsdConfig(DurationMetric::MAX_SPARSE);
+// uint64_t bucketStartTimeNs = 10000000000;
+// uint64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+// FeedEvents(config, processor);
+// ConfigMetricsReportList reports;
+// vector<uint8_t> buffer;
+// processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
+// ADB_DUMP, FAST, &buffer);
+// EXPECT_TRUE(buffer.size() > 0);
+// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+// backfillDimensionPath(&reports);
+// backfillStringInReport(&reports);
+// backfillStartEndTimestamp(&reports);
+// EXPECT_EQ(reports.reports_size(), 1);
+// EXPECT_EQ(reports.reports(0).metrics_size(), 1);
+// EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
+// // Dump the report after the end of 2nd bucket. One dimension with one bucket.
+// EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 1);
+// auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
+// // Validate dimension value.
+// ValidateAttributionUidDimension(data.dimensions_in_what(),
+// android::util::WAKELOCK_STATE_CHANGED, 111);
+// // The max is acquire event for wl1 to screen off start.
+// EXPECT_EQ((unsigned long long)data.bucket_info(0).duration_nanos(), bucketSizeNs + 2 - 200);
+//}
+//
+//TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration3) {
+// ConfigKey cfgKey;
+// auto config = CreateStatsdConfig(DurationMetric::MAX_SPARSE);
+// uint64_t bucketStartTimeNs = 10000000000;
+// uint64_t bucketSizeNs =
+// TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+// FeedEvents(config, processor);
+// ConfigMetricsReportList reports;
+// vector<uint8_t> buffer;
+//
+// std::vector<std::unique_ptr<LogEvent>> events;
+// events.push_back(
+// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+// bucketStartTimeNs + 2 * bucketSizeNs + 90));
+// events.push_back(CreateAcquireWakelockEvent(attributions1, "wl3",
+// bucketStartTimeNs + 2 * bucketSizeNs + 100));
+// events.push_back(CreateReleaseWakelockEvent(attributions1, "wl3",
+// bucketStartTimeNs + 5 * bucketSizeNs + 100));
+// sortLogEventsByTimestamp(&events);
+// for (const auto& event : events) {
+// processor->OnLogEvent(event.get());
+// }
+//
+// processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, false, true,
+// ADB_DUMP, FAST, &buffer);
+// EXPECT_TRUE(buffer.size() > 0);
+// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+// backfillDimensionPath(&reports);
+// backfillStringInReport(&reports);
+// backfillStartEndTimestamp(&reports);
+// EXPECT_EQ(reports.reports_size(), 1);
+// EXPECT_EQ(reports.reports(0).metrics_size(), 1);
+// EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
+// EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 2);
+// auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
+// ValidateAttributionUidDimension(data.dimensions_in_what(),
+// android::util::WAKELOCK_STATE_CHANGED, 111);
+// // The last wakelock holding spans 4 buckets.
+// EXPECT_EQ((unsigned long long)data.bucket_info(1).duration_nanos(), 3 * bucketSizeNs);
+// EXPECT_EQ((unsigned long long)data.bucket_info(1).start_bucket_elapsed_nanos(),
+// bucketStartTimeNs + 5 * bucketSizeNs);
+// EXPECT_EQ((unsigned long long)data.bucket_info(1).end_bucket_elapsed_nanos(),
+// bucketStartTimeNs + 6 * bucketSizeNs);
+//}
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
diff --git a/cmds/statsd/tests/external/StatsPuller_test.cpp b/cmds/statsd/tests/external/StatsPuller_test.cpp
index f42356a..c0b4f43 100644
--- a/cmds/statsd/tests/external/StatsPuller_test.cpp
+++ b/cmds/statsd/tests/external/StatsPuller_test.cpp
@@ -57,12 +57,13 @@
FakePuller puller;
-shared_ptr<LogEvent> createSimpleEvent(int64_t eventTimeNs, int64_t value) {
- shared_ptr<LogEvent> event = make_shared<LogEvent>(pullTagId, eventTimeNs);
- event->write(value);
- event->init();
- return event;
-}
+// TODO(b/149590301): Update this helper to use new socket schema.
+//shared_ptr<LogEvent> createSimpleEvent(int64_t eventTimeNs, int64_t value) {
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(pullTagId, eventTimeNs);
+// event->write(value);
+// event->init();
+// return event;
+//}
class StatsPullerTest : public ::testing::Test {
public:
@@ -79,148 +80,149 @@
} // Anonymous namespace.
-TEST_F(StatsPullerTest, PullSuccess) {
- pullData.push_back(createSimpleEvent(1111L, 33));
-
- pullSuccess = true;
-
- vector<std::shared_ptr<LogEvent>> dataHolder;
- EXPECT_TRUE(puller.Pull(&dataHolder));
- EXPECT_EQ(1, dataHolder.size());
- EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
- EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
- EXPECT_EQ(1, dataHolder[0]->size());
- EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
-
- sleep_for(std::chrono::seconds(1));
-
- pullData.clear();
- pullData.push_back(createSimpleEvent(2222L, 44));
-
- pullSuccess = true;
-
- EXPECT_TRUE(puller.Pull(&dataHolder));
- EXPECT_EQ(1, dataHolder.size());
- EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
- EXPECT_EQ(2222L, dataHolder[0]->GetElapsedTimestampNs());
- EXPECT_EQ(1, dataHolder[0]->size());
- EXPECT_EQ(44, dataHolder[0]->getValues()[0].mValue.int_value);
-}
-
-TEST_F(StatsPullerTest, PullFailAfterSuccess) {
- pullData.push_back(createSimpleEvent(1111L, 33));
-
- pullSuccess = true;
-
- vector<std::shared_ptr<LogEvent>> dataHolder;
- EXPECT_TRUE(puller.Pull(&dataHolder));
- EXPECT_EQ(1, dataHolder.size());
- EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
- EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
- EXPECT_EQ(1, dataHolder[0]->size());
- EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
-
- sleep_for(std::chrono::seconds(1));
-
- pullData.clear();
- pullData.push_back(createSimpleEvent(2222L, 44));
-
- pullSuccess = false;
- dataHolder.clear();
- EXPECT_FALSE(puller.Pull(&dataHolder));
- EXPECT_EQ(0, dataHolder.size());
-
- pullSuccess = true;
- dataHolder.clear();
- EXPECT_FALSE(puller.Pull(&dataHolder));
- EXPECT_EQ(0, dataHolder.size());
-}
-
-// Test pull takes longer than timeout, 2nd pull happens shorter than cooldown
-TEST_F(StatsPullerTest, PullTakeTooLongAndPullFast) {
- pullData.push_back(createSimpleEvent(1111L, 33));
- pullSuccess = true;
- // timeout is 0.5
- pullDelayNs = (long)(0.8 * NS_PER_SEC);
-
- vector<std::shared_ptr<LogEvent>> dataHolder;
- EXPECT_FALSE(puller.Pull(&dataHolder));
- EXPECT_EQ(0, dataHolder.size());
-
- pullData.clear();
- pullData.push_back(createSimpleEvent(2222L, 44));
-
- pullSuccess = true;
- dataHolder.clear();
- EXPECT_FALSE(puller.Pull(&dataHolder));
- EXPECT_EQ(0, dataHolder.size());
-}
-
-TEST_F(StatsPullerTest, PullFail) {
- pullData.push_back(createSimpleEvent(1111L, 33));
-
- pullSuccess = false;
-
- vector<std::shared_ptr<LogEvent>> dataHolder;
- EXPECT_FALSE(puller.Pull(&dataHolder));
- EXPECT_EQ(0, dataHolder.size());
-}
-
-TEST_F(StatsPullerTest, PullTakeTooLong) {
- pullData.push_back(createSimpleEvent(1111L, 33));
-
- pullSuccess = true;
- pullDelayNs = NS_PER_SEC;
-
- vector<std::shared_ptr<LogEvent>> dataHolder;
- EXPECT_FALSE(puller.Pull(&dataHolder));
- EXPECT_EQ(0, dataHolder.size());
-}
-
-TEST_F(StatsPullerTest, PullTooFast) {
- pullData.push_back(createSimpleEvent(1111L, 33));
-
- pullSuccess = true;
-
- vector<std::shared_ptr<LogEvent>> dataHolder;
- EXPECT_TRUE(puller.Pull(&dataHolder));
- EXPECT_EQ(1, dataHolder.size());
- EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
- EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
- EXPECT_EQ(1, dataHolder[0]->size());
- EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
-
- pullData.clear();
- pullData.push_back(createSimpleEvent(2222L, 44));
-
- pullSuccess = true;
-
- dataHolder.clear();
- EXPECT_TRUE(puller.Pull(&dataHolder));
- EXPECT_EQ(1, dataHolder.size());
- EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
- EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
- EXPECT_EQ(1, dataHolder[0]->size());
- EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
-}
-
-TEST_F(StatsPullerTest, PullFailsAndTooFast) {
- pullData.push_back(createSimpleEvent(1111L, 33));
-
- pullSuccess = false;
-
- vector<std::shared_ptr<LogEvent>> dataHolder;
- EXPECT_FALSE(puller.Pull(&dataHolder));
- EXPECT_EQ(0, dataHolder.size());
-
- pullData.clear();
- pullData.push_back(createSimpleEvent(2222L, 44));
-
- pullSuccess = true;
-
- EXPECT_FALSE(puller.Pull(&dataHolder));
- EXPECT_EQ(0, dataHolder.size());
-}
+// TODO(b/149590301): Update these tests to use new socket schema.
+//TEST_F(StatsPullerTest, PullSuccess) {
+// pullData.push_back(createSimpleEvent(1111L, 33));
+//
+// pullSuccess = true;
+//
+// vector<std::shared_ptr<LogEvent>> dataHolder;
+// EXPECT_TRUE(puller.Pull(&dataHolder));
+// EXPECT_EQ(1, dataHolder.size());
+// EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
+// EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
+// EXPECT_EQ(1, dataHolder[0]->size());
+// EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
+//
+// sleep_for(std::chrono::seconds(1));
+//
+// pullData.clear();
+// pullData.push_back(createSimpleEvent(2222L, 44));
+//
+// pullSuccess = true;
+//
+// EXPECT_TRUE(puller.Pull(&dataHolder));
+// EXPECT_EQ(1, dataHolder.size());
+// EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
+// EXPECT_EQ(2222L, dataHolder[0]->GetElapsedTimestampNs());
+// EXPECT_EQ(1, dataHolder[0]->size());
+// EXPECT_EQ(44, dataHolder[0]->getValues()[0].mValue.int_value);
+//}
+//
+//TEST_F(StatsPullerTest, PullFailAfterSuccess) {
+// pullData.push_back(createSimpleEvent(1111L, 33));
+//
+// pullSuccess = true;
+//
+// vector<std::shared_ptr<LogEvent>> dataHolder;
+// EXPECT_TRUE(puller.Pull(&dataHolder));
+// EXPECT_EQ(1, dataHolder.size());
+// EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
+// EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
+// EXPECT_EQ(1, dataHolder[0]->size());
+// EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
+//
+// sleep_for(std::chrono::seconds(1));
+//
+// pullData.clear();
+// pullData.push_back(createSimpleEvent(2222L, 44));
+//
+// pullSuccess = false;
+// dataHolder.clear();
+// EXPECT_FALSE(puller.Pull(&dataHolder));
+// EXPECT_EQ(0, dataHolder.size());
+//
+// pullSuccess = true;
+// dataHolder.clear();
+// EXPECT_FALSE(puller.Pull(&dataHolder));
+// EXPECT_EQ(0, dataHolder.size());
+//}
+//
+//// Test pull takes longer than timeout, 2nd pull happens shorter than cooldown
+//TEST_F(StatsPullerTest, PullTakeTooLongAndPullFast) {
+// pullData.push_back(createSimpleEvent(1111L, 33));
+// pullSuccess = true;
+// // timeout is 0.5
+// pullDelayNs = (long)(0.8 * NS_PER_SEC);
+//
+// vector<std::shared_ptr<LogEvent>> dataHolder;
+// EXPECT_FALSE(puller.Pull(&dataHolder));
+// EXPECT_EQ(0, dataHolder.size());
+//
+// pullData.clear();
+// pullData.push_back(createSimpleEvent(2222L, 44));
+//
+// pullSuccess = true;
+// dataHolder.clear();
+// EXPECT_FALSE(puller.Pull(&dataHolder));
+// EXPECT_EQ(0, dataHolder.size());
+//}
+//
+//TEST_F(StatsPullerTest, PullFail) {
+// pullData.push_back(createSimpleEvent(1111L, 33));
+//
+// pullSuccess = false;
+//
+// vector<std::shared_ptr<LogEvent>> dataHolder;
+// EXPECT_FALSE(puller.Pull(&dataHolder));
+// EXPECT_EQ(0, dataHolder.size());
+//}
+//
+//TEST_F(StatsPullerTest, PullTakeTooLong) {
+// pullData.push_back(createSimpleEvent(1111L, 33));
+//
+// pullSuccess = true;
+// pullDelayNs = NS_PER_SEC;
+//
+// vector<std::shared_ptr<LogEvent>> dataHolder;
+// EXPECT_FALSE(puller.Pull(&dataHolder));
+// EXPECT_EQ(0, dataHolder.size());
+//}
+//
+//TEST_F(StatsPullerTest, PullTooFast) {
+// pullData.push_back(createSimpleEvent(1111L, 33));
+//
+// pullSuccess = true;
+//
+// vector<std::shared_ptr<LogEvent>> dataHolder;
+// EXPECT_TRUE(puller.Pull(&dataHolder));
+// EXPECT_EQ(1, dataHolder.size());
+// EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
+// EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
+// EXPECT_EQ(1, dataHolder[0]->size());
+// EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
+//
+// pullData.clear();
+// pullData.push_back(createSimpleEvent(2222L, 44));
+//
+// pullSuccess = true;
+//
+// dataHolder.clear();
+// EXPECT_TRUE(puller.Pull(&dataHolder));
+// EXPECT_EQ(1, dataHolder.size());
+// EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
+// EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
+// EXPECT_EQ(1, dataHolder[0]->size());
+// EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
+//}
+//
+//TEST_F(StatsPullerTest, PullFailsAndTooFast) {
+// pullData.push_back(createSimpleEvent(1111L, 33));
+//
+// pullSuccess = false;
+//
+// vector<std::shared_ptr<LogEvent>> dataHolder;
+// EXPECT_FALSE(puller.Pull(&dataHolder));
+// EXPECT_EQ(0, dataHolder.size());
+//
+// pullData.clear();
+// pullData.push_back(createSimpleEvent(2222L, 44));
+//
+// pullSuccess = true;
+//
+// EXPECT_FALSE(puller.Pull(&dataHolder));
+// EXPECT_EQ(0, dataHolder.size());
+//}
} // namespace statsd
} // namespace os
diff --git a/cmds/statsd/tests/external/puller_util_test.cpp b/cmds/statsd/tests/external/puller_util_test.cpp
index c25e657..81590a2 100644
--- a/cmds/statsd/tests/external/puller_util_test.cpp
+++ b/cmds/statsd/tests/external/puller_util_test.cpp
@@ -60,209 +60,210 @@
}
} // anonymous namespace
-TEST(puller_util, MergeNoDimension) {
- vector<shared_ptr<LogEvent>> inputData;
- shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
- // 30->22->31
- event->write(isolatedUid);
- event->write(hostNonAdditiveData);
- event->write(isolatedAdditiveData);
- event->init();
- inputData.push_back(event);
-
- // 20->22->21
- event = make_shared<LogEvent>(uidAtomTagId, timestamp);
- event->write(hostUid);
- event->write(hostNonAdditiveData);
- event->write(hostAdditiveData);
- event->init();
- inputData.push_back(event);
-
- sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
- EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid))
- .WillRepeatedly(Return(hostUid));
- EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
- .WillRepeatedly(ReturnArg<0>());
- mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
-
- vector<vector<int>> actual;
- extractIntoVector(inputData, actual);
- vector<int> expectedV1 = {20, 22, 52};
- EXPECT_EQ(1, (int)actual.size());
- EXPECT_THAT(actual, Contains(expectedV1));
-}
-
-TEST(puller_util, MergeWithDimension) {
- vector<shared_ptr<LogEvent>> inputData;
- shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
- // 30->32->31
- event->write(isolatedUid);
- event->write(isolatedNonAdditiveData);
- event->write(isolatedAdditiveData);
- event->init();
- inputData.push_back(event);
-
- // 20->32->21
- event = make_shared<LogEvent>(uidAtomTagId, timestamp);
- event->write(hostUid);
- event->write(isolatedNonAdditiveData);
- event->write(hostAdditiveData);
- event->init();
- inputData.push_back(event);
-
- // 20->22->21
- event = make_shared<LogEvent>(uidAtomTagId, timestamp);
- event->write(hostUid);
- event->write(hostNonAdditiveData);
- event->write(hostAdditiveData);
- event->init();
- inputData.push_back(event);
-
- sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
- EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid))
- .WillRepeatedly(Return(hostUid));
- EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
- .WillRepeatedly(ReturnArg<0>());
- mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
-
- vector<vector<int>> actual;
- extractIntoVector(inputData, actual);
- vector<int> expectedV1 = {20, 22, 21};
- vector<int> expectedV2 = {20, 32, 52};
- EXPECT_EQ(2, (int)actual.size());
- EXPECT_THAT(actual, Contains(expectedV1));
- EXPECT_THAT(actual, Contains(expectedV2));
-}
-
-TEST(puller_util, NoMergeHostUidOnly) {
- vector<shared_ptr<LogEvent>> inputData;
- shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
- // 20->32->31
- event->write(hostUid);
- event->write(isolatedNonAdditiveData);
- event->write(isolatedAdditiveData);
- event->init();
- inputData.push_back(event);
-
- // 20->22->21
- event = make_shared<LogEvent>(uidAtomTagId, timestamp);
- event->write(hostUid);
- event->write(hostNonAdditiveData);
- event->write(hostAdditiveData);
- event->init();
- inputData.push_back(event);
-
- sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
- EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid))
- .WillRepeatedly(Return(hostUid));
- EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
- .WillRepeatedly(ReturnArg<0>());
- mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
-
- // 20->32->31
- // 20->22->21
- vector<vector<int>> actual;
- extractIntoVector(inputData, actual);
- vector<int> expectedV1 = {20, 32, 31};
- vector<int> expectedV2 = {20, 22, 21};
- EXPECT_EQ(2, (int)actual.size());
- EXPECT_THAT(actual, Contains(expectedV1));
- EXPECT_THAT(actual, Contains(expectedV2));
-}
-
-TEST(puller_util, IsolatedUidOnly) {
- vector<shared_ptr<LogEvent>> inputData;
- shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
- // 30->32->31
- event->write(hostUid);
- event->write(isolatedNonAdditiveData);
- event->write(isolatedAdditiveData);
- event->init();
- inputData.push_back(event);
-
- // 30->22->21
- event = make_shared<LogEvent>(uidAtomTagId, timestamp);
- event->write(hostUid);
- event->write(hostNonAdditiveData);
- event->write(hostAdditiveData);
- event->init();
- inputData.push_back(event);
-
- sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
- EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid))
- .WillRepeatedly(Return(hostUid));
- EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
- .WillRepeatedly(ReturnArg<0>());
- mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
-
- // 20->32->31
- // 20->22->21
- vector<vector<int>> actual;
- extractIntoVector(inputData, actual);
- vector<int> expectedV1 = {20, 32, 31};
- vector<int> expectedV2 = {20, 22, 21};
- EXPECT_EQ(2, (int)actual.size());
- EXPECT_THAT(actual, Contains(expectedV1));
- EXPECT_THAT(actual, Contains(expectedV2));
-}
-
-TEST(puller_util, MultipleIsolatedUidToOneHostUid) {
- vector<shared_ptr<LogEvent>> inputData;
- shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
- // 30->32->31
- event->write(isolatedUid);
- event->write(isolatedNonAdditiveData);
- event->write(isolatedAdditiveData);
- event->init();
- inputData.push_back(event);
-
- // 31->32->21
- event = make_shared<LogEvent>(uidAtomTagId, timestamp);
- event->write(isolatedUid + 1);
- event->write(isolatedNonAdditiveData);
- event->write(hostAdditiveData);
- event->init();
- inputData.push_back(event);
-
- // 20->32->21
- event = make_shared<LogEvent>(uidAtomTagId, timestamp);
- event->write(hostUid);
- event->write(isolatedNonAdditiveData);
- event->write(hostAdditiveData);
- event->init();
- inputData.push_back(event);
-
- sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
- EXPECT_CALL(*uidMap, getHostUidOrSelf(_)).WillRepeatedly(Return(hostUid));
- mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
-
- vector<vector<int>> actual;
- extractIntoVector(inputData, actual);
- vector<int> expectedV1 = {20, 32, 73};
- EXPECT_EQ(1, (int)actual.size());
- EXPECT_THAT(actual, Contains(expectedV1));
-}
-
-TEST(puller_util, NoNeedToMerge) {
- vector<shared_ptr<LogEvent>> inputData;
- shared_ptr<LogEvent> event =
- make_shared<LogEvent>(nonUidAtomTagId, timestamp);
- // 32
- event->write(isolatedNonAdditiveData);
- event->init();
- inputData.push_back(event);
-
- event = make_shared<LogEvent>(nonUidAtomTagId, timestamp);
- // 22
- event->write(hostNonAdditiveData);
- event->init();
- inputData.push_back(event);
-
- sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
- mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, nonUidAtomTagId, {} /*no additive fields*/);
-
- EXPECT_EQ(2, (int)inputData.size());
-}
+// TODO(b/149590301): Update these tests to use new socket schema.
+//TEST(puller_util, MergeNoDimension) {
+// vector<shared_ptr<LogEvent>> inputData;
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+// // 30->22->31
+// event->write(isolatedUid);
+// event->write(hostNonAdditiveData);
+// event->write(isolatedAdditiveData);
+// event->init();
+// inputData.push_back(event);
+//
+// // 20->22->21
+// event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+// event->write(hostUid);
+// event->write(hostNonAdditiveData);
+// event->write(hostAdditiveData);
+// event->init();
+// inputData.push_back(event);
+//
+// sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
+// EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid))
+// .WillRepeatedly(Return(hostUid));
+// EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
+// .WillRepeatedly(ReturnArg<0>());
+// mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
+//
+// vector<vector<int>> actual;
+// extractIntoVector(inputData, actual);
+// vector<int> expectedV1 = {20, 22, 52};
+// EXPECT_EQ(1, (int)actual.size());
+// EXPECT_THAT(actual, Contains(expectedV1));
+//}
+//
+//TEST(puller_util, MergeWithDimension) {
+// vector<shared_ptr<LogEvent>> inputData;
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+// // 30->32->31
+// event->write(isolatedUid);
+// event->write(isolatedNonAdditiveData);
+// event->write(isolatedAdditiveData);
+// event->init();
+// inputData.push_back(event);
+//
+// // 20->32->21
+// event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+// event->write(hostUid);
+// event->write(isolatedNonAdditiveData);
+// event->write(hostAdditiveData);
+// event->init();
+// inputData.push_back(event);
+//
+// // 20->22->21
+// event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+// event->write(hostUid);
+// event->write(hostNonAdditiveData);
+// event->write(hostAdditiveData);
+// event->init();
+// inputData.push_back(event);
+//
+// sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
+// EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid))
+// .WillRepeatedly(Return(hostUid));
+// EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
+// .WillRepeatedly(ReturnArg<0>());
+// mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
+//
+// vector<vector<int>> actual;
+// extractIntoVector(inputData, actual);
+// vector<int> expectedV1 = {20, 22, 21};
+// vector<int> expectedV2 = {20, 32, 52};
+// EXPECT_EQ(2, (int)actual.size());
+// EXPECT_THAT(actual, Contains(expectedV1));
+// EXPECT_THAT(actual, Contains(expectedV2));
+//}
+//
+//TEST(puller_util, NoMergeHostUidOnly) {
+// vector<shared_ptr<LogEvent>> inputData;
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+// // 20->32->31
+// event->write(hostUid);
+// event->write(isolatedNonAdditiveData);
+// event->write(isolatedAdditiveData);
+// event->init();
+// inputData.push_back(event);
+//
+// // 20->22->21
+// event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+// event->write(hostUid);
+// event->write(hostNonAdditiveData);
+// event->write(hostAdditiveData);
+// event->init();
+// inputData.push_back(event);
+//
+// sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
+// EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid))
+// .WillRepeatedly(Return(hostUid));
+// EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
+// .WillRepeatedly(ReturnArg<0>());
+// mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
+//
+// // 20->32->31
+// // 20->22->21
+// vector<vector<int>> actual;
+// extractIntoVector(inputData, actual);
+// vector<int> expectedV1 = {20, 32, 31};
+// vector<int> expectedV2 = {20, 22, 21};
+// EXPECT_EQ(2, (int)actual.size());
+// EXPECT_THAT(actual, Contains(expectedV1));
+// EXPECT_THAT(actual, Contains(expectedV2));
+//}
+//
+//TEST(puller_util, IsolatedUidOnly) {
+// vector<shared_ptr<LogEvent>> inputData;
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+// // 30->32->31
+// event->write(hostUid);
+// event->write(isolatedNonAdditiveData);
+// event->write(isolatedAdditiveData);
+// event->init();
+// inputData.push_back(event);
+//
+// // 30->22->21
+// event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+// event->write(hostUid);
+// event->write(hostNonAdditiveData);
+// event->write(hostAdditiveData);
+// event->init();
+// inputData.push_back(event);
+//
+// sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
+// EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid))
+// .WillRepeatedly(Return(hostUid));
+// EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
+// .WillRepeatedly(ReturnArg<0>());
+// mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
+//
+// // 20->32->31
+// // 20->22->21
+// vector<vector<int>> actual;
+// extractIntoVector(inputData, actual);
+// vector<int> expectedV1 = {20, 32, 31};
+// vector<int> expectedV2 = {20, 22, 21};
+// EXPECT_EQ(2, (int)actual.size());
+// EXPECT_THAT(actual, Contains(expectedV1));
+// EXPECT_THAT(actual, Contains(expectedV2));
+//}
+//
+//TEST(puller_util, MultipleIsolatedUidToOneHostUid) {
+// vector<shared_ptr<LogEvent>> inputData;
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+// // 30->32->31
+// event->write(isolatedUid);
+// event->write(isolatedNonAdditiveData);
+// event->write(isolatedAdditiveData);
+// event->init();
+// inputData.push_back(event);
+//
+// // 31->32->21
+// event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+// event->write(isolatedUid + 1);
+// event->write(isolatedNonAdditiveData);
+// event->write(hostAdditiveData);
+// event->init();
+// inputData.push_back(event);
+//
+// // 20->32->21
+// event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+// event->write(hostUid);
+// event->write(isolatedNonAdditiveData);
+// event->write(hostAdditiveData);
+// event->init();
+// inputData.push_back(event);
+//
+// sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
+// EXPECT_CALL(*uidMap, getHostUidOrSelf(_)).WillRepeatedly(Return(hostUid));
+// mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
+//
+// vector<vector<int>> actual;
+// extractIntoVector(inputData, actual);
+// vector<int> expectedV1 = {20, 32, 73};
+// EXPECT_EQ(1, (int)actual.size());
+// EXPECT_THAT(actual, Contains(expectedV1));
+//}
+//
+//TEST(puller_util, NoNeedToMerge) {
+// vector<shared_ptr<LogEvent>> inputData;
+// shared_ptr<LogEvent> event =
+// make_shared<LogEvent>(nonUidAtomTagId, timestamp);
+// // 32
+// event->write(isolatedNonAdditiveData);
+// event->init();
+// inputData.push_back(event);
+//
+// event = make_shared<LogEvent>(nonUidAtomTagId, timestamp);
+// // 22
+// event->write(hostNonAdditiveData);
+// event->init();
+// inputData.push_back(event);
+//
+// sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
+// mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, nonUidAtomTagId, {} /*no additive fields*/);
+//
+// EXPECT_EQ(2, (int)inputData.size());
+//}
} // namespace statsd
} // namespace os
diff --git a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
index 8915c73..b882678 100644
--- a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
@@ -37,365 +37,366 @@
const ConfigKey kConfigKey(0, 12345);
-TEST(CountMetricProducerTest, TestFirstBucket) {
- CountMetric metric;
- metric.set_id(1);
- metric.set_bucket(ONE_MINUTE);
- 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);
- EXPECT_EQ(600500000000, countProducer.mCurrentBucketStartTimeNs);
- EXPECT_EQ(10, countProducer.mCurrentBucketNum);
- EXPECT_EQ(660000000005, countProducer.getCurrentBucketEndTimeNs());
-}
-
-TEST(CountMetricProducerTest, TestNonDimensionalEvents) {
- int64_t bucketStartTimeNs = 10000000000;
- int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
- int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
- int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
- int tagId = 1;
-
- CountMetric metric;
- metric.set_id(1);
- metric.set_bucket(ONE_MINUTE);
-
- LogEvent event1(tagId, bucketStartTimeNs + 1);
- event1.init();
- LogEvent event2(tagId, bucketStartTimeNs + 2);
- event2.init();
-
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-
- CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
- bucketStartTimeNs, bucketStartTimeNs);
-
- // 2 events in bucket 1.
- countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
- countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
-
- // Flushes at event #2.
- countProducer.flushIfNeededLocked(bucketStartTimeNs + 2);
- EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
-
- // Flushes.
- countProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
- EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
- EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
- countProducer.mPastBuckets.end());
- const auto& buckets = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
- EXPECT_EQ(1UL, buckets.size());
- EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[0].mBucketEndNs);
- EXPECT_EQ(2LL, buckets[0].mCount);
-
- // 1 matched event happens in bucket 2.
- LogEvent event3(tagId, bucketStartTimeNs + bucketSizeNs + 2);
- event3.init();
-
- countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
- countProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
- EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
- EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
- countProducer.mPastBuckets.end());
- EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- const auto& bucketInfo2 = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1];
- EXPECT_EQ(bucket2StartTimeNs, bucketInfo2.mBucketStartNs);
- EXPECT_EQ(bucket2StartTimeNs + bucketSizeNs, bucketInfo2.mBucketEndNs);
- EXPECT_EQ(1LL, bucketInfo2.mCount);
-
- // nothing happens in bucket 3. we should not record anything for bucket 3.
- countProducer.flushIfNeededLocked(bucketStartTimeNs + 3 * bucketSizeNs + 1);
- EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
- EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
- countProducer.mPastBuckets.end());
- const auto& buckets3 = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
- EXPECT_EQ(2UL, buckets3.size());
-}
-
-TEST(CountMetricProducerTest, TestEventsWithNonSlicedCondition) {
- int64_t bucketStartTimeNs = 10000000000;
- int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
-
- CountMetric metric;
- metric.set_id(1);
- metric.set_bucket(ONE_MINUTE);
- metric.set_condition(StringToId("SCREEN_ON"));
-
- LogEvent event1(1, bucketStartTimeNs + 1);
- event1.init();
-
- LogEvent event2(1, bucketStartTimeNs + 10);
- event2.init();
-
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-
- CountMetricProducer countProducer(kConfigKey, metric, 1, wizard, bucketStartTimeNs,
- bucketStartTimeNs);
-
- countProducer.onConditionChanged(true, bucketStartTimeNs);
- countProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
- EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
-
- countProducer.onConditionChanged(false /*new condition*/, bucketStartTimeNs + 2);
- // Upon this match event, the matched event1 is flushed.
- countProducer.onMatchedLogEvent(1 /*matcher index*/, event2);
- EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
-
- countProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
- EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
- EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
- countProducer.mPastBuckets.end());
- {
- const auto& buckets = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
- EXPECT_EQ(1UL, buckets.size());
- const auto& bucketInfo = buckets[0];
- EXPECT_EQ(bucketStartTimeNs, bucketInfo.mBucketStartNs);
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.mBucketEndNs);
- EXPECT_EQ(1LL, bucketInfo.mCount);
- }
-}
-
-TEST(CountMetricProducerTest, TestEventsWithSlicedCondition) {
- int64_t bucketStartTimeNs = 10000000000;
- int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
-
- int tagId = 1;
- int conditionTagId = 2;
-
- CountMetric metric;
- metric.set_id(1);
- metric.set_bucket(ONE_MINUTE);
- metric.set_condition(StringToId("APP_IN_BACKGROUND_PER_UID_AND_SCREEN_ON"));
- MetricConditionLink* link = metric.add_links();
- link->set_condition(StringToId("APP_IN_BACKGROUND_PER_UID"));
- buildSimpleAtomFieldMatcher(tagId, 1, link->mutable_fields_in_what());
- buildSimpleAtomFieldMatcher(conditionTagId, 2, link->mutable_fields_in_condition());
-
- LogEvent event1(tagId, bucketStartTimeNs + 1);
- event1.write("111"); // uid
- event1.init();
- ConditionKey key1;
- key1[StringToId("APP_IN_BACKGROUND_PER_UID")] =
- {getMockedDimensionKey(conditionTagId, 2, "111")};
-
- LogEvent event2(tagId, bucketStartTimeNs + 10);
- event2.write("222"); // uid
- event2.init();
- ConditionKey key2;
- key2[StringToId("APP_IN_BACKGROUND_PER_UID")] =
- {getMockedDimensionKey(conditionTagId, 2, "222")};
-
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- EXPECT_CALL(*wizard, query(_, key1, _)).WillOnce(Return(ConditionState::kFalse));
-
- EXPECT_CALL(*wizard, query(_, key2, _)).WillOnce(Return(ConditionState::kTrue));
-
- CountMetricProducer countProducer(kConfigKey, metric, 1 /*condition tracker index*/, wizard,
- bucketStartTimeNs, bucketStartTimeNs);
-
- countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
- countProducer.flushIfNeededLocked(bucketStartTimeNs + 1);
- EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
-
- countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
- countProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
- EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
- EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
- countProducer.mPastBuckets.end());
- const auto& buckets = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
- EXPECT_EQ(1UL, buckets.size());
- const auto& bucketInfo = buckets[0];
- EXPECT_EQ(bucketStartTimeNs, bucketInfo.mBucketStartNs);
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.mBucketEndNs);
- EXPECT_EQ(1LL, bucketInfo.mCount);
-}
-
-TEST(CountMetricProducerTest, TestEventWithAppUpgrade) {
- sp<AlarmMonitor> alarmMonitor;
- int64_t bucketStartTimeNs = 10000000000;
- int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
- int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
-
- int tagId = 1;
- int conditionTagId = 2;
-
- CountMetric metric;
- metric.set_id(1);
- metric.set_bucket(ONE_MINUTE);
- Alert alert;
- alert.set_num_buckets(3);
- alert.set_trigger_if_sum_gt(2);
- LogEvent event1(tagId, bucketStartTimeNs + 1);
- event1.write("111"); // uid
- event1.init();
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- CountMetricProducer countProducer(kConfigKey, metric, -1 /* no condition */, wizard,
- bucketStartTimeNs, bucketStartTimeNs);
-
- sp<AnomalyTracker> anomalyTracker = countProducer.addAnomalyTracker(alert, alarmMonitor);
- EXPECT_TRUE(anomalyTracker != nullptr);
-
- // Bucket is flushed yet.
- countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
- EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
- EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
-
- // App upgrade forces bucket flush.
- // Check that there's a past bucket and the bucket end is not adjusted.
- countProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
- EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ((long long)bucketStartTimeNs,
- countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
- EXPECT_EQ((long long)eventUpgradeTimeNs,
- countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketEndNs);
- EXPECT_EQ(eventUpgradeTimeNs, countProducer.mCurrentBucketStartTimeNs);
- // Anomaly tracker only contains full buckets.
- EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
-
- int64_t lastEndTimeNs = countProducer.getCurrentBucketEndTimeNs();
- // Next event occurs in same bucket as partial bucket created.
- LogEvent event2(tagId, bucketStartTimeNs + 59 * NS_PER_SEC + 10);
- event2.write("222"); // uid
- event2.init();
- countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
- EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ(eventUpgradeTimeNs, countProducer.mCurrentBucketStartTimeNs);
- EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
-
- // Third event in following bucket.
- LogEvent event3(tagId, bucketStartTimeNs + 62 * NS_PER_SEC + 10);
- event3.write("333"); // uid
- event3.init();
- countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
- EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ(lastEndTimeNs, countProducer.mCurrentBucketStartTimeNs);
- EXPECT_EQ(2, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
-}
-
-TEST(CountMetricProducerTest, TestEventWithAppUpgradeInNextBucket) {
- int64_t bucketStartTimeNs = 10000000000;
- int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
- int64_t eventUpgradeTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
-
- int tagId = 1;
- int conditionTagId = 2;
-
- CountMetric metric;
- metric.set_id(1);
- metric.set_bucket(ONE_MINUTE);
- LogEvent event1(tagId, bucketStartTimeNs + 1);
- event1.write("111"); // uid
- event1.init();
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- CountMetricProducer countProducer(kConfigKey, metric, -1 /* no condition */, wizard,
- bucketStartTimeNs, bucketStartTimeNs);
-
- // Bucket is flushed yet.
- countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
- EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
-
- // App upgrade forces bucket flush.
- // Check that there's a past bucket and the bucket end is not adjusted.
- countProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
- EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ((int64_t)bucketStartTimeNs,
- countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
- countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketEndNs);
- EXPECT_EQ(eventUpgradeTimeNs, countProducer.mCurrentBucketStartTimeNs);
-
- // Next event occurs in same bucket as partial bucket created.
- LogEvent event2(tagId, bucketStartTimeNs + 70 * NS_PER_SEC + 10);
- event2.write("222"); // uid
- event2.init();
- countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
- EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-
- // Third event in following bucket.
- LogEvent event3(tagId, bucketStartTimeNs + 121 * NS_PER_SEC + 10);
- event3.write("333"); // uid
- event3.init();
- countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
- EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ((int64_t)eventUpgradeTimeNs,
- countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mBucketStartNs);
- EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
- countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mBucketEndNs);
-}
-
-TEST(CountMetricProducerTest, TestAnomalyDetectionUnSliced) {
- sp<AlarmMonitor> alarmMonitor;
- Alert alert;
- alert.set_id(11);
- alert.set_metric_id(1);
- alert.set_trigger_if_sum_gt(2);
- alert.set_num_buckets(2);
- const int32_t refPeriodSec = 1;
- alert.set_refractory_period_secs(refPeriodSec);
-
- int64_t bucketStartTimeNs = 10000000000;
- int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
- int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
- int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
-
- CountMetric metric;
- metric.set_id(1);
- metric.set_bucket(ONE_MINUTE);
-
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
- bucketStartTimeNs, bucketStartTimeNs);
-
- sp<AnomalyTracker> anomalyTracker = countProducer.addAnomalyTracker(alert, alarmMonitor);
-
- int tagId = 1;
- LogEvent event1(tagId, bucketStartTimeNs + 1);
- event1.init();
- LogEvent event2(tagId, bucketStartTimeNs + 2);
- event2.init();
- LogEvent event3(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 1);
- event3.init();
- LogEvent event4(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 1);
- event4.init();
- LogEvent event5(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2);
- event5.init();
- LogEvent event6(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 3);
- event6.init();
- LogEvent event7(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2 * NS_PER_SEC);
- event7.init();
-
- // Two events in bucket #0.
- countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
- countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
-
- EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
- EXPECT_EQ(2L, countProducer.mCurrentSlicedCounter->begin()->second);
- EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
-
- // One event in bucket #2. No alarm as bucket #0 is trashed out.
- countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
- EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
- EXPECT_EQ(1L, countProducer.mCurrentSlicedCounter->begin()->second);
- EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
-
- // Two events in bucket #3.
- countProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
- countProducer.onMatchedLogEvent(1 /*log matcher index*/, event5);
- countProducer.onMatchedLogEvent(1 /*log matcher index*/, event6);
- EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
- EXPECT_EQ(3L, countProducer.mCurrentSlicedCounter->begin()->second);
- // Anomaly at event 6 is within refractory period. The alarm is at event 5 timestamp not event 6
- EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
- std::ceil(1.0 * event5.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
-
- countProducer.onMatchedLogEvent(1 /*log matcher index*/, event7);
- EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
- EXPECT_EQ(4L, countProducer.mCurrentSlicedCounter->begin()->second);
- EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
- std::ceil(1.0 * event7.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
-}
+// TODO(b/149590301): Update these tests to use new socket schema.
+//TEST(CountMetricProducerTest, TestFirstBucket) {
+// CountMetric metric;
+// metric.set_id(1);
+// metric.set_bucket(ONE_MINUTE);
+// 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);
+// EXPECT_EQ(600500000000, countProducer.mCurrentBucketStartTimeNs);
+// EXPECT_EQ(10, countProducer.mCurrentBucketNum);
+// EXPECT_EQ(660000000005, countProducer.getCurrentBucketEndTimeNs());
+//}
+//
+//TEST(CountMetricProducerTest, TestNonDimensionalEvents) {
+// int64_t bucketStartTimeNs = 10000000000;
+// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+// int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
+// int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
+// int tagId = 1;
+//
+// CountMetric metric;
+// metric.set_id(1);
+// metric.set_bucket(ONE_MINUTE);
+//
+// LogEvent event1(tagId, bucketStartTimeNs + 1);
+// event1.init();
+// LogEvent event2(tagId, bucketStartTimeNs + 2);
+// event2.init();
+//
+// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//
+// CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+// bucketStartTimeNs, bucketStartTimeNs);
+//
+// // 2 events in bucket 1.
+// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
+// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
+//
+// // Flushes at event #2.
+// countProducer.flushIfNeededLocked(bucketStartTimeNs + 2);
+// EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
+//
+// // Flushes.
+// countProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
+// EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
+// EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
+// countProducer.mPastBuckets.end());
+// const auto& buckets = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
+// EXPECT_EQ(1UL, buckets.size());
+// EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[0].mBucketEndNs);
+// EXPECT_EQ(2LL, buckets[0].mCount);
+//
+// // 1 matched event happens in bucket 2.
+// LogEvent event3(tagId, bucketStartTimeNs + bucketSizeNs + 2);
+// event3.init();
+//
+// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
+// countProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
+// EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
+// EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
+// countProducer.mPastBuckets.end());
+// EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+// const auto& bucketInfo2 = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1];
+// EXPECT_EQ(bucket2StartTimeNs, bucketInfo2.mBucketStartNs);
+// EXPECT_EQ(bucket2StartTimeNs + bucketSizeNs, bucketInfo2.mBucketEndNs);
+// EXPECT_EQ(1LL, bucketInfo2.mCount);
+//
+// // nothing happens in bucket 3. we should not record anything for bucket 3.
+// countProducer.flushIfNeededLocked(bucketStartTimeNs + 3 * bucketSizeNs + 1);
+// EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
+// EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
+// countProducer.mPastBuckets.end());
+// const auto& buckets3 = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
+// EXPECT_EQ(2UL, buckets3.size());
+//}
+//
+//TEST(CountMetricProducerTest, TestEventsWithNonSlicedCondition) {
+// int64_t bucketStartTimeNs = 10000000000;
+// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+//
+// CountMetric metric;
+// metric.set_id(1);
+// metric.set_bucket(ONE_MINUTE);
+// metric.set_condition(StringToId("SCREEN_ON"));
+//
+// LogEvent event1(1, bucketStartTimeNs + 1);
+// event1.init();
+//
+// LogEvent event2(1, bucketStartTimeNs + 10);
+// event2.init();
+//
+// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//
+// CountMetricProducer countProducer(kConfigKey, metric, 1, wizard, bucketStartTimeNs,
+// bucketStartTimeNs);
+//
+// countProducer.onConditionChanged(true, bucketStartTimeNs);
+// countProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
+// EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
+//
+// countProducer.onConditionChanged(false /*new condition*/, bucketStartTimeNs + 2);
+// // Upon this match event, the matched event1 is flushed.
+// countProducer.onMatchedLogEvent(1 /*matcher index*/, event2);
+// EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
+//
+// countProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
+// EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
+// EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
+// countProducer.mPastBuckets.end());
+// {
+// const auto& buckets = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
+// EXPECT_EQ(1UL, buckets.size());
+// const auto& bucketInfo = buckets[0];
+// EXPECT_EQ(bucketStartTimeNs, bucketInfo.mBucketStartNs);
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.mBucketEndNs);
+// EXPECT_EQ(1LL, bucketInfo.mCount);
+// }
+//}
+//
+//TEST(CountMetricProducerTest, TestEventsWithSlicedCondition) {
+// int64_t bucketStartTimeNs = 10000000000;
+// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+//
+// int tagId = 1;
+// int conditionTagId = 2;
+//
+// CountMetric metric;
+// metric.set_id(1);
+// metric.set_bucket(ONE_MINUTE);
+// metric.set_condition(StringToId("APP_IN_BACKGROUND_PER_UID_AND_SCREEN_ON"));
+// MetricConditionLink* link = metric.add_links();
+// link->set_condition(StringToId("APP_IN_BACKGROUND_PER_UID"));
+// buildSimpleAtomFieldMatcher(tagId, 1, link->mutable_fields_in_what());
+// buildSimpleAtomFieldMatcher(conditionTagId, 2, link->mutable_fields_in_condition());
+//
+// LogEvent event1(tagId, bucketStartTimeNs + 1);
+// event1.write("111"); // uid
+// event1.init();
+// ConditionKey key1;
+// key1[StringToId("APP_IN_BACKGROUND_PER_UID")] =
+// {getMockedDimensionKey(conditionTagId, 2, "111")};
+//
+// LogEvent event2(tagId, bucketStartTimeNs + 10);
+// event2.write("222"); // uid
+// event2.init();
+// ConditionKey key2;
+// key2[StringToId("APP_IN_BACKGROUND_PER_UID")] =
+// {getMockedDimensionKey(conditionTagId, 2, "222")};
+//
+// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+// EXPECT_CALL(*wizard, query(_, key1, _)).WillOnce(Return(ConditionState::kFalse));
+//
+// EXPECT_CALL(*wizard, query(_, key2, _)).WillOnce(Return(ConditionState::kTrue));
+//
+// CountMetricProducer countProducer(kConfigKey, metric, 1 /*condition tracker index*/, wizard,
+// bucketStartTimeNs, bucketStartTimeNs);
+//
+// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
+// countProducer.flushIfNeededLocked(bucketStartTimeNs + 1);
+// EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
+//
+// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
+// countProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
+// EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
+// EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
+// countProducer.mPastBuckets.end());
+// const auto& buckets = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
+// EXPECT_EQ(1UL, buckets.size());
+// const auto& bucketInfo = buckets[0];
+// EXPECT_EQ(bucketStartTimeNs, bucketInfo.mBucketStartNs);
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.mBucketEndNs);
+// EXPECT_EQ(1LL, bucketInfo.mCount);
+//}
+//
+//TEST(CountMetricProducerTest, TestEventWithAppUpgrade) {
+// sp<AlarmMonitor> alarmMonitor;
+// int64_t bucketStartTimeNs = 10000000000;
+// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+// int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
+//
+// int tagId = 1;
+// int conditionTagId = 2;
+//
+// CountMetric metric;
+// metric.set_id(1);
+// metric.set_bucket(ONE_MINUTE);
+// Alert alert;
+// alert.set_num_buckets(3);
+// alert.set_trigger_if_sum_gt(2);
+// LogEvent event1(tagId, bucketStartTimeNs + 1);
+// event1.write("111"); // uid
+// event1.init();
+// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+// CountMetricProducer countProducer(kConfigKey, metric, -1 /* no condition */, wizard,
+// bucketStartTimeNs, bucketStartTimeNs);
+//
+// sp<AnomalyTracker> anomalyTracker = countProducer.addAnomalyTracker(alert, alarmMonitor);
+// EXPECT_TRUE(anomalyTracker != nullptr);
+//
+// // Bucket is flushed yet.
+// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
+// EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
+// EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
+//
+// // App upgrade forces bucket flush.
+// // Check that there's a past bucket and the bucket end is not adjusted.
+// countProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+// EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+// EXPECT_EQ((long long)bucketStartTimeNs,
+// countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
+// EXPECT_EQ((long long)eventUpgradeTimeNs,
+// countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketEndNs);
+// EXPECT_EQ(eventUpgradeTimeNs, countProducer.mCurrentBucketStartTimeNs);
+// // Anomaly tracker only contains full buckets.
+// EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
+//
+// int64_t lastEndTimeNs = countProducer.getCurrentBucketEndTimeNs();
+// // Next event occurs in same bucket as partial bucket created.
+// LogEvent event2(tagId, bucketStartTimeNs + 59 * NS_PER_SEC + 10);
+// event2.write("222"); // uid
+// event2.init();
+// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
+// EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+// EXPECT_EQ(eventUpgradeTimeNs, countProducer.mCurrentBucketStartTimeNs);
+// EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
+//
+// // Third event in following bucket.
+// LogEvent event3(tagId, bucketStartTimeNs + 62 * NS_PER_SEC + 10);
+// event3.write("333"); // uid
+// event3.init();
+// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
+// EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+// EXPECT_EQ(lastEndTimeNs, countProducer.mCurrentBucketStartTimeNs);
+// EXPECT_EQ(2, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
+//}
+//
+//TEST(CountMetricProducerTest, TestEventWithAppUpgradeInNextBucket) {
+// int64_t bucketStartTimeNs = 10000000000;
+// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+// int64_t eventUpgradeTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
+//
+// int tagId = 1;
+// int conditionTagId = 2;
+//
+// CountMetric metric;
+// metric.set_id(1);
+// metric.set_bucket(ONE_MINUTE);
+// LogEvent event1(tagId, bucketStartTimeNs + 1);
+// event1.write("111"); // uid
+// event1.init();
+// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+// CountMetricProducer countProducer(kConfigKey, metric, -1 /* no condition */, wizard,
+// bucketStartTimeNs, bucketStartTimeNs);
+//
+// // Bucket is flushed yet.
+// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
+// EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
+//
+// // App upgrade forces bucket flush.
+// // Check that there's a past bucket and the bucket end is not adjusted.
+// countProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+// EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+// EXPECT_EQ((int64_t)bucketStartTimeNs,
+// countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
+// countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketEndNs);
+// EXPECT_EQ(eventUpgradeTimeNs, countProducer.mCurrentBucketStartTimeNs);
+//
+// // Next event occurs in same bucket as partial bucket created.
+// LogEvent event2(tagId, bucketStartTimeNs + 70 * NS_PER_SEC + 10);
+// event2.write("222"); // uid
+// event2.init();
+// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
+// EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+//
+// // Third event in following bucket.
+// LogEvent event3(tagId, bucketStartTimeNs + 121 * NS_PER_SEC + 10);
+// event3.write("333"); // uid
+// event3.init();
+// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
+// EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+// EXPECT_EQ((int64_t)eventUpgradeTimeNs,
+// countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mBucketStartNs);
+// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+// countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mBucketEndNs);
+//}
+//
+//TEST(CountMetricProducerTest, TestAnomalyDetectionUnSliced) {
+// sp<AlarmMonitor> alarmMonitor;
+// Alert alert;
+// alert.set_id(11);
+// alert.set_metric_id(1);
+// alert.set_trigger_if_sum_gt(2);
+// alert.set_num_buckets(2);
+// const int32_t refPeriodSec = 1;
+// alert.set_refractory_period_secs(refPeriodSec);
+//
+// int64_t bucketStartTimeNs = 10000000000;
+// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+// int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
+// int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
+//
+// CountMetric metric;
+// metric.set_id(1);
+// metric.set_bucket(ONE_MINUTE);
+//
+// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+// CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+// bucketStartTimeNs, bucketStartTimeNs);
+//
+// sp<AnomalyTracker> anomalyTracker = countProducer.addAnomalyTracker(alert, alarmMonitor);
+//
+// int tagId = 1;
+// LogEvent event1(tagId, bucketStartTimeNs + 1);
+// event1.init();
+// LogEvent event2(tagId, bucketStartTimeNs + 2);
+// event2.init();
+// LogEvent event3(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 1);
+// event3.init();
+// LogEvent event4(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 1);
+// event4.init();
+// LogEvent event5(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2);
+// event5.init();
+// LogEvent event6(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 3);
+// event6.init();
+// LogEvent event7(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2 * NS_PER_SEC);
+// event7.init();
+//
+// // Two events in bucket #0.
+// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
+// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
+//
+// EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
+// EXPECT_EQ(2L, countProducer.mCurrentSlicedCounter->begin()->second);
+// EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
+//
+// // One event in bucket #2. No alarm as bucket #0 is trashed out.
+// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
+// EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
+// EXPECT_EQ(1L, countProducer.mCurrentSlicedCounter->begin()->second);
+// EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
+//
+// // Two events in bucket #3.
+// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
+// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event5);
+// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event6);
+// EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
+// EXPECT_EQ(3L, countProducer.mCurrentSlicedCounter->begin()->second);
+// // Anomaly at event 6 is within refractory period. The alarm is at event 5 timestamp not event 6
+// EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
+// std::ceil(1.0 * event5.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
+//
+// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event7);
+// EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
+// EXPECT_EQ(4L, countProducer.mCurrentSlicedCounter->begin()->second);
+// EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
+// std::ceil(1.0 * event7.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
+//}
TEST(CountMetricProducerTest, TestOneWeekTimeUnit) {
CountMetric metric;
diff --git a/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp b/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp
index b294cad..6661374 100644
--- a/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp
@@ -56,382 +56,383 @@
EXPECT_EQ(660000000005, durationProducer.getCurrentBucketEndTimeNs());
}
-TEST(DurationMetricTrackerTest, TestNoCondition) {
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- int64_t bucketStartTimeNs = 10000000000;
- int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
-
- DurationMetric metric;
- metric.set_id(1);
- metric.set_bucket(ONE_MINUTE);
- metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
-
- int tagId = 1;
- LogEvent event1(tagId, bucketStartTimeNs + 1);
- event1.init();
- LogEvent event2(tagId, bucketStartTimeNs + bucketSizeNs + 2);
- event2.init();
-
- 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);
-
- durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
- durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
- durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
- EXPECT_EQ(1UL, durationProducer.mPastBuckets.size());
- EXPECT_TRUE(durationProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
- durationProducer.mPastBuckets.end());
- const auto& buckets = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
- EXPECT_EQ(2UL, buckets.size());
- EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[0].mBucketEndNs);
- EXPECT_EQ(bucketSizeNs - 1LL, buckets[0].mDuration);
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[1].mBucketStartNs);
- EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[1].mBucketEndNs);
- EXPECT_EQ(2LL, buckets[1].mDuration);
-}
-
-TEST(DurationMetricTrackerTest, TestNonSlicedCondition) {
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- int64_t bucketStartTimeNs = 10000000000;
- int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
-
- DurationMetric metric;
- metric.set_id(1);
- metric.set_bucket(ONE_MINUTE);
- metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
-
- int tagId = 1;
- LogEvent event1(tagId, bucketStartTimeNs + 1);
- event1.init();
- LogEvent event2(tagId, bucketStartTimeNs + 2);
- event2.init();
- LogEvent event3(tagId, bucketStartTimeNs + bucketSizeNs + 1);
- event3.init();
- LogEvent event4(tagId, bucketStartTimeNs + bucketSizeNs + 3);
- event4.init();
-
- FieldMatcher dimensions;
- DurationMetricProducer durationProducer(
- kConfigKey, metric, 0 /* condition index */, 1 /* start index */, 2 /* stop index */,
- 3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
- durationProducer.mCondition = ConditionState::kFalse;
-
- EXPECT_FALSE(durationProducer.mCondition);
- EXPECT_FALSE(durationProducer.isConditionSliced());
-
- durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
- durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
- durationProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
- EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
-
- durationProducer.onMatchedLogEvent(1 /* start index*/, event3);
- durationProducer.onConditionChanged(true /* condition */, bucketStartTimeNs + bucketSizeNs + 2);
- durationProducer.onMatchedLogEvent(2 /* stop index*/, event4);
- durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
- EXPECT_EQ(1UL, durationProducer.mPastBuckets.size());
- EXPECT_TRUE(durationProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
- durationProducer.mPastBuckets.end());
- const auto& buckets2 = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
- EXPECT_EQ(1UL, buckets2.size());
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets2[0].mBucketStartNs);
- EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets2[0].mBucketEndNs);
- EXPECT_EQ(1LL, buckets2[0].mDuration);
-}
-
-TEST(DurationMetricTrackerTest, TestNonSlicedConditionUnknownState) {
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- int64_t bucketStartTimeNs = 10000000000;
- int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
-
- DurationMetric metric;
- metric.set_id(1);
- metric.set_bucket(ONE_MINUTE);
- metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
-
- int tagId = 1;
- LogEvent event1(tagId, bucketStartTimeNs + 1);
- event1.init();
- LogEvent event2(tagId, bucketStartTimeNs + 2);
- event2.init();
- LogEvent event3(tagId, bucketStartTimeNs + bucketSizeNs + 1);
- event3.init();
- LogEvent event4(tagId, bucketStartTimeNs + bucketSizeNs + 3);
- event4.init();
-
- FieldMatcher dimensions;
- DurationMetricProducer durationProducer(
- kConfigKey, metric, 0 /* condition index */, 1 /* start index */, 2 /* stop index */,
- 3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
-
- EXPECT_EQ(ConditionState::kUnknown, durationProducer.mCondition);
- EXPECT_FALSE(durationProducer.isConditionSliced());
-
- durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
- durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
- durationProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
- EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
-
- durationProducer.onMatchedLogEvent(1 /* start index*/, event3);
- durationProducer.onConditionChanged(true /* condition */, bucketStartTimeNs + bucketSizeNs + 2);
- durationProducer.onMatchedLogEvent(2 /* stop index*/, event4);
- durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
- EXPECT_EQ(1UL, durationProducer.mPastBuckets.size());
- const auto& buckets2 = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
- EXPECT_EQ(1UL, buckets2.size());
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets2[0].mBucketStartNs);
- EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets2[0].mBucketEndNs);
- EXPECT_EQ(1LL, buckets2[0].mDuration);
-}
-
-TEST(DurationMetricTrackerTest, TestSumDurationWithUpgrade) {
- /**
- * The duration starts from the first bucket, through the two partial buckets (10-70sec),
- * another bucket, and ends at the beginning of the next full bucket.
- * Expected buckets:
- * - [10,25]: 14 secs
- * - [25,70]: All 45 secs
- * - [70,130]: All 60 secs
- * - [130, 210]: Only 5 secs (event ended at 135sec)
- */
- int64_t bucketStartTimeNs = 10000000000;
- int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
- int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
- int64_t startTimeNs = bucketStartTimeNs + 1 * NS_PER_SEC;
- int64_t endTimeNs = startTimeNs + 125 * NS_PER_SEC;
-
- int tagId = 1;
-
- DurationMetric metric;
- metric.set_id(1);
- metric.set_bucket(ONE_MINUTE);
- metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
- 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);
-
- LogEvent start_event(tagId, startTimeNs);
- start_event.init();
- durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
- EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
- EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
-
- durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
- EXPECT_EQ(1UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- std::vector<DurationBucket> buckets =
- durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
- EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
- EXPECT_EQ(eventUpgradeTimeNs, buckets[0].mBucketEndNs);
- EXPECT_EQ(eventUpgradeTimeNs - startTimeNs, buckets[0].mDuration);
- EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
-
- // We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
- LogEvent end_event(tagId, endTimeNs);
- end_event.init();
- durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
- buckets = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
- EXPECT_EQ(3UL, buckets.size());
- EXPECT_EQ(eventUpgradeTimeNs, buckets[1].mBucketStartNs);
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[1].mBucketEndNs);
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - eventUpgradeTimeNs, buckets[1].mDuration);
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[2].mBucketStartNs);
- EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[2].mBucketEndNs);
- EXPECT_EQ(bucketSizeNs, buckets[2].mDuration);
-}
-
-TEST(DurationMetricTrackerTest, TestSumDurationWithUpgradeInFollowingBucket) {
- /**
- * Expected buckets (start at 11s, upgrade at 75s, end at 135s):
- * - [10,70]: 59 secs
- * - [70,75]: 5 sec
- * - [75,130]: 55 secs
- */
- int64_t bucketStartTimeNs = 10000000000;
- int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
- int64_t eventUpgradeTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
- int64_t startTimeNs = bucketStartTimeNs + 1 * NS_PER_SEC;
- int64_t endTimeNs = startTimeNs + 125 * NS_PER_SEC;
-
- int tagId = 1;
-
- DurationMetric metric;
- metric.set_id(1);
- metric.set_bucket(ONE_MINUTE);
- metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
- 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);
-
- LogEvent start_event(tagId, startTimeNs);
- start_event.init();
- durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
- EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
- EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
-
- durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
- EXPECT_EQ(2UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- std::vector<DurationBucket> buckets =
- durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
- EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[0].mBucketEndNs);
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - startTimeNs, buckets[0].mDuration);
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[1].mBucketStartNs);
- EXPECT_EQ(eventUpgradeTimeNs, buckets[1].mBucketEndNs);
- EXPECT_EQ(eventUpgradeTimeNs - (bucketStartTimeNs + bucketSizeNs), buckets[1].mDuration);
- EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
-
- // We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
- LogEvent end_event(tagId, endTimeNs);
- end_event.init();
- durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
- buckets = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
- EXPECT_EQ(3UL, buckets.size());
- EXPECT_EQ(eventUpgradeTimeNs, buckets[2].mBucketStartNs);
- EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[2].mBucketEndNs);
- EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs - eventUpgradeTimeNs, buckets[2].mDuration);
-}
-
-TEST(DurationMetricTrackerTest, TestSumDurationAnomalyWithUpgrade) {
- sp<AlarmMonitor> alarmMonitor;
- int64_t bucketStartTimeNs = 10000000000;
- int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
- int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
- int64_t startTimeNs = bucketStartTimeNs + 1;
- int64_t endTimeNs = startTimeNs + 65 * NS_PER_SEC;
-
- int tagId = 1;
-
- // Setup metric with alert.
- DurationMetric metric;
- metric.set_id(1);
- metric.set_bucket(ONE_MINUTE);
- metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
- Alert alert;
- alert.set_num_buckets(3);
- alert.set_trigger_if_sum_gt(2);
-
- 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);
-
- sp<AnomalyTracker> anomalyTracker = durationProducer.addAnomalyTracker(alert, alarmMonitor);
- EXPECT_TRUE(anomalyTracker != nullptr);
-
- LogEvent start_event(tagId, startTimeNs);
- start_event.init();
- durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
- durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
- // We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
- LogEvent end_event(tagId, endTimeNs);
- end_event.init();
- durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
-
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - startTimeNs,
- anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
-}
-
-TEST(DurationMetricTrackerTest, TestMaxDurationWithUpgrade) {
- int64_t bucketStartTimeNs = 10000000000;
- int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
- int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
- int64_t startTimeNs = bucketStartTimeNs + 1;
- int64_t endTimeNs = startTimeNs + 125 * NS_PER_SEC;
-
- int tagId = 1;
-
- DurationMetric metric;
- metric.set_id(1);
- metric.set_bucket(ONE_MINUTE);
- metric.set_aggregation_type(DurationMetric_AggregationType_MAX_SPARSE);
- LogEvent event1(tagId, startTimeNs);
- event1.write("111"); // uid
- event1.init();
- 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);
-
- LogEvent start_event(tagId, startTimeNs);
- start_event.init();
- durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
- EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
- EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
-
- durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
- EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
-
- // We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
- LogEvent end_event(tagId, endTimeNs);
- end_event.init();
- durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
- EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-
- durationProducer.flushIfNeededLocked(bucketStartTimeNs + 3 * bucketSizeNs + 1);
- std::vector<DurationBucket> buckets =
- durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
- EXPECT_EQ(1UL, buckets.size());
- EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[0].mBucketStartNs);
- EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs, buckets[0].mBucketEndNs);
- EXPECT_EQ(endTimeNs - startTimeNs, buckets[0].mDuration);
-}
-
-TEST(DurationMetricTrackerTest, TestMaxDurationWithUpgradeInNextBucket) {
- int64_t bucketStartTimeNs = 10000000000;
- int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
- int64_t eventUpgradeTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
- int64_t startTimeNs = bucketStartTimeNs + 1;
- int64_t endTimeNs = startTimeNs + 115 * NS_PER_SEC;
-
- int tagId = 1;
-
- DurationMetric metric;
- metric.set_id(1);
- metric.set_bucket(ONE_MINUTE);
- metric.set_aggregation_type(DurationMetric_AggregationType_MAX_SPARSE);
- LogEvent event1(tagId, startTimeNs);
- event1.write("111"); // uid
- event1.init();
- 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);
-
- LogEvent start_event(tagId, startTimeNs);
- start_event.init();
- durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
- EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
- EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
-
- durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
- EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
-
- // Stop occurs in the same partial bucket as created for the app upgrade.
- LogEvent end_event(tagId, endTimeNs);
- end_event.init();
- durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
- EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
-
- durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
- std::vector<DurationBucket> buckets =
- durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
- EXPECT_EQ(1UL, buckets.size());
- EXPECT_EQ(eventUpgradeTimeNs, buckets[0].mBucketStartNs);
- EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[0].mBucketEndNs);
- EXPECT_EQ(endTimeNs - startTimeNs, buckets[0].mDuration);
-}
+// TODO(b/149590301): Update these to use new socket schema.
+//TEST(DurationMetricTrackerTest, TestNoCondition) {
+// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+// int64_t bucketStartTimeNs = 10000000000;
+// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+//
+// DurationMetric metric;
+// metric.set_id(1);
+// metric.set_bucket(ONE_MINUTE);
+// metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
+//
+// int tagId = 1;
+// LogEvent event1(tagId, bucketStartTimeNs + 1);
+// event1.init();
+// LogEvent event2(tagId, bucketStartTimeNs + bucketSizeNs + 2);
+// event2.init();
+//
+// 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);
+//
+// durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
+// durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
+// durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
+// EXPECT_EQ(1UL, durationProducer.mPastBuckets.size());
+// EXPECT_TRUE(durationProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
+// durationProducer.mPastBuckets.end());
+// const auto& buckets = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
+// EXPECT_EQ(2UL, buckets.size());
+// EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[0].mBucketEndNs);
+// EXPECT_EQ(bucketSizeNs - 1LL, buckets[0].mDuration);
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[1].mBucketStartNs);
+// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[1].mBucketEndNs);
+// EXPECT_EQ(2LL, buckets[1].mDuration);
+//}
+//
+//TEST(DurationMetricTrackerTest, TestNonSlicedCondition) {
+// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+// int64_t bucketStartTimeNs = 10000000000;
+// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+//
+// DurationMetric metric;
+// metric.set_id(1);
+// metric.set_bucket(ONE_MINUTE);
+// metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
+//
+// int tagId = 1;
+// LogEvent event1(tagId, bucketStartTimeNs + 1);
+// event1.init();
+// LogEvent event2(tagId, bucketStartTimeNs + 2);
+// event2.init();
+// LogEvent event3(tagId, bucketStartTimeNs + bucketSizeNs + 1);
+// event3.init();
+// LogEvent event4(tagId, bucketStartTimeNs + bucketSizeNs + 3);
+// event4.init();
+//
+// FieldMatcher dimensions;
+// DurationMetricProducer durationProducer(
+// kConfigKey, metric, 0 /* condition index */, 1 /* start index */, 2 /* stop index */,
+// 3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
+// durationProducer.mCondition = ConditionState::kFalse;
+//
+// EXPECT_FALSE(durationProducer.mCondition);
+// EXPECT_FALSE(durationProducer.isConditionSliced());
+//
+// durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
+// durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
+// durationProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
+// EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
+//
+// durationProducer.onMatchedLogEvent(1 /* start index*/, event3);
+// durationProducer.onConditionChanged(true /* condition */, bucketStartTimeNs + bucketSizeNs + 2);
+// durationProducer.onMatchedLogEvent(2 /* stop index*/, event4);
+// durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
+// EXPECT_EQ(1UL, durationProducer.mPastBuckets.size());
+// EXPECT_TRUE(durationProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
+// durationProducer.mPastBuckets.end());
+// const auto& buckets2 = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
+// EXPECT_EQ(1UL, buckets2.size());
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets2[0].mBucketStartNs);
+// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets2[0].mBucketEndNs);
+// EXPECT_EQ(1LL, buckets2[0].mDuration);
+//}
+//
+//TEST(DurationMetricTrackerTest, TestNonSlicedConditionUnknownState) {
+// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+// int64_t bucketStartTimeNs = 10000000000;
+// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+//
+// DurationMetric metric;
+// metric.set_id(1);
+// metric.set_bucket(ONE_MINUTE);
+// metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
+//
+// int tagId = 1;
+// LogEvent event1(tagId, bucketStartTimeNs + 1);
+// event1.init();
+// LogEvent event2(tagId, bucketStartTimeNs + 2);
+// event2.init();
+// LogEvent event3(tagId, bucketStartTimeNs + bucketSizeNs + 1);
+// event3.init();
+// LogEvent event4(tagId, bucketStartTimeNs + bucketSizeNs + 3);
+// event4.init();
+//
+// FieldMatcher dimensions;
+// DurationMetricProducer durationProducer(
+// kConfigKey, metric, 0 /* condition index */, 1 /* start index */, 2 /* stop index */,
+// 3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
+//
+// EXPECT_EQ(ConditionState::kUnknown, durationProducer.mCondition);
+// EXPECT_FALSE(durationProducer.isConditionSliced());
+//
+// durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
+// durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
+// durationProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
+// EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
+//
+// durationProducer.onMatchedLogEvent(1 /* start index*/, event3);
+// durationProducer.onConditionChanged(true /* condition */, bucketStartTimeNs + bucketSizeNs + 2);
+// durationProducer.onMatchedLogEvent(2 /* stop index*/, event4);
+// durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
+// EXPECT_EQ(1UL, durationProducer.mPastBuckets.size());
+// const auto& buckets2 = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
+// EXPECT_EQ(1UL, buckets2.size());
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets2[0].mBucketStartNs);
+// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets2[0].mBucketEndNs);
+// EXPECT_EQ(1LL, buckets2[0].mDuration);
+//}
+//
+//TEST(DurationMetricTrackerTest, TestSumDurationWithUpgrade) {
+// /**
+// * The duration starts from the first bucket, through the two partial buckets (10-70sec),
+// * another bucket, and ends at the beginning of the next full bucket.
+// * Expected buckets:
+// * - [10,25]: 14 secs
+// * - [25,70]: All 45 secs
+// * - [70,130]: All 60 secs
+// * - [130, 210]: Only 5 secs (event ended at 135sec)
+// */
+// int64_t bucketStartTimeNs = 10000000000;
+// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+// int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
+// int64_t startTimeNs = bucketStartTimeNs + 1 * NS_PER_SEC;
+// int64_t endTimeNs = startTimeNs + 125 * NS_PER_SEC;
+//
+// int tagId = 1;
+//
+// DurationMetric metric;
+// metric.set_id(1);
+// metric.set_bucket(ONE_MINUTE);
+// metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
+// 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);
+//
+// LogEvent start_event(tagId, startTimeNs);
+// start_event.init();
+// durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
+// EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
+// EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
+//
+// durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+// EXPECT_EQ(1UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+// std::vector<DurationBucket> buckets =
+// durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
+// EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
+// EXPECT_EQ(eventUpgradeTimeNs, buckets[0].mBucketEndNs);
+// EXPECT_EQ(eventUpgradeTimeNs - startTimeNs, buckets[0].mDuration);
+// EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
+//
+// // We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
+// LogEvent end_event(tagId, endTimeNs);
+// end_event.init();
+// durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
+// buckets = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
+// EXPECT_EQ(3UL, buckets.size());
+// EXPECT_EQ(eventUpgradeTimeNs, buckets[1].mBucketStartNs);
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[1].mBucketEndNs);
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - eventUpgradeTimeNs, buckets[1].mDuration);
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[2].mBucketStartNs);
+// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[2].mBucketEndNs);
+// EXPECT_EQ(bucketSizeNs, buckets[2].mDuration);
+//}
+//
+//TEST(DurationMetricTrackerTest, TestSumDurationWithUpgradeInFollowingBucket) {
+// /**
+// * Expected buckets (start at 11s, upgrade at 75s, end at 135s):
+// * - [10,70]: 59 secs
+// * - [70,75]: 5 sec
+// * - [75,130]: 55 secs
+// */
+// int64_t bucketStartTimeNs = 10000000000;
+// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+// int64_t eventUpgradeTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
+// int64_t startTimeNs = bucketStartTimeNs + 1 * NS_PER_SEC;
+// int64_t endTimeNs = startTimeNs + 125 * NS_PER_SEC;
+//
+// int tagId = 1;
+//
+// DurationMetric metric;
+// metric.set_id(1);
+// metric.set_bucket(ONE_MINUTE);
+// metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
+// 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);
+//
+// LogEvent start_event(tagId, startTimeNs);
+// start_event.init();
+// durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
+// EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
+// EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
+//
+// durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+// EXPECT_EQ(2UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+// std::vector<DurationBucket> buckets =
+// durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
+// EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[0].mBucketEndNs);
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - startTimeNs, buckets[0].mDuration);
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[1].mBucketStartNs);
+// EXPECT_EQ(eventUpgradeTimeNs, buckets[1].mBucketEndNs);
+// EXPECT_EQ(eventUpgradeTimeNs - (bucketStartTimeNs + bucketSizeNs), buckets[1].mDuration);
+// EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
+//
+// // We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
+// LogEvent end_event(tagId, endTimeNs);
+// end_event.init();
+// durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
+// buckets = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
+// EXPECT_EQ(3UL, buckets.size());
+// EXPECT_EQ(eventUpgradeTimeNs, buckets[2].mBucketStartNs);
+// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[2].mBucketEndNs);
+// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs - eventUpgradeTimeNs, buckets[2].mDuration);
+//}
+//
+//TEST(DurationMetricTrackerTest, TestSumDurationAnomalyWithUpgrade) {
+// sp<AlarmMonitor> alarmMonitor;
+// int64_t bucketStartTimeNs = 10000000000;
+// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+// int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
+// int64_t startTimeNs = bucketStartTimeNs + 1;
+// int64_t endTimeNs = startTimeNs + 65 * NS_PER_SEC;
+//
+// int tagId = 1;
+//
+// // Setup metric with alert.
+// DurationMetric metric;
+// metric.set_id(1);
+// metric.set_bucket(ONE_MINUTE);
+// metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
+// Alert alert;
+// alert.set_num_buckets(3);
+// alert.set_trigger_if_sum_gt(2);
+//
+// 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);
+//
+// sp<AnomalyTracker> anomalyTracker = durationProducer.addAnomalyTracker(alert, alarmMonitor);
+// EXPECT_TRUE(anomalyTracker != nullptr);
+//
+// LogEvent start_event(tagId, startTimeNs);
+// start_event.init();
+// durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
+// durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+// // We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
+// LogEvent end_event(tagId, endTimeNs);
+// end_event.init();
+// durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
+//
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - startTimeNs,
+// anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
+//}
+//
+//TEST(DurationMetricTrackerTest, TestMaxDurationWithUpgrade) {
+// int64_t bucketStartTimeNs = 10000000000;
+// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+// int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
+// int64_t startTimeNs = bucketStartTimeNs + 1;
+// int64_t endTimeNs = startTimeNs + 125 * NS_PER_SEC;
+//
+// int tagId = 1;
+//
+// DurationMetric metric;
+// metric.set_id(1);
+// metric.set_bucket(ONE_MINUTE);
+// metric.set_aggregation_type(DurationMetric_AggregationType_MAX_SPARSE);
+// LogEvent event1(tagId, startTimeNs);
+// event1.write("111"); // uid
+// event1.init();
+// 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);
+//
+// LogEvent start_event(tagId, startTimeNs);
+// start_event.init();
+// durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
+// EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
+// EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
+//
+// durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+// EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+// EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
+//
+// // We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
+// LogEvent end_event(tagId, endTimeNs);
+// end_event.init();
+// durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
+// EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+//
+// durationProducer.flushIfNeededLocked(bucketStartTimeNs + 3 * bucketSizeNs + 1);
+// std::vector<DurationBucket> buckets =
+// durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
+// EXPECT_EQ(1UL, buckets.size());
+// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[0].mBucketStartNs);
+// EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs, buckets[0].mBucketEndNs);
+// EXPECT_EQ(endTimeNs - startTimeNs, buckets[0].mDuration);
+//}
+//
+//TEST(DurationMetricTrackerTest, TestMaxDurationWithUpgradeInNextBucket) {
+// int64_t bucketStartTimeNs = 10000000000;
+// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+// int64_t eventUpgradeTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
+// int64_t startTimeNs = bucketStartTimeNs + 1;
+// int64_t endTimeNs = startTimeNs + 115 * NS_PER_SEC;
+//
+// int tagId = 1;
+//
+// DurationMetric metric;
+// metric.set_id(1);
+// metric.set_bucket(ONE_MINUTE);
+// metric.set_aggregation_type(DurationMetric_AggregationType_MAX_SPARSE);
+// LogEvent event1(tagId, startTimeNs);
+// event1.write("111"); // uid
+// event1.init();
+// 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);
+//
+// LogEvent start_event(tagId, startTimeNs);
+// start_event.init();
+// durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
+// EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
+// EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
+//
+// durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+// EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+// EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
+//
+// // Stop occurs in the same partial bucket as created for the app upgrade.
+// LogEvent end_event(tagId, endTimeNs);
+// end_event.init();
+// durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
+// EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+// EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
+//
+// durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
+// std::vector<DurationBucket> buckets =
+// durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
+// EXPECT_EQ(1UL, buckets.size());
+// EXPECT_EQ(eventUpgradeTimeNs, buckets[0].mBucketStartNs);
+// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[0].mBucketEndNs);
+// EXPECT_EQ(endTimeNs - startTimeNs, buckets[0].mDuration);
+//}
} // namespace statsd
} // namespace os
diff --git a/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp b/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
index f30873b..0f39efd5 100644
--- a/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
@@ -85,46 +85,47 @@
// eventProducer.onDumpReport();
}
-TEST(EventMetricProducerTest, TestEventsWithSlicedCondition) {
- int64_t bucketStartTimeNs = 10000000000;
- int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
-
- int tagId = 1;
- int conditionTagId = 2;
-
- EventMetric metric;
- metric.set_id(1);
- metric.set_condition(StringToId("APP_IN_BACKGROUND_PER_UID_AND_SCREEN_ON"));
- MetricConditionLink* link = metric.add_links();
- link->set_condition(StringToId("APP_IN_BACKGROUND_PER_UID"));
- buildSimpleAtomFieldMatcher(tagId, 1, link->mutable_fields_in_what());
- buildSimpleAtomFieldMatcher(conditionTagId, 2, link->mutable_fields_in_condition());
-
- LogEvent event1(tagId, bucketStartTimeNs + 1);
- EXPECT_TRUE(event1.write("111"));
- event1.init();
- ConditionKey key1;
- key1[StringToId("APP_IN_BACKGROUND_PER_UID")] = {getMockedDimensionKey(conditionTagId, 2, "111")};
-
- LogEvent event2(tagId, bucketStartTimeNs + 10);
- EXPECT_TRUE(event2.write("222"));
- event2.init();
- ConditionKey key2;
- key2[StringToId("APP_IN_BACKGROUND_PER_UID")] = {getMockedDimensionKey(conditionTagId, 2, "222")};
-
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- EXPECT_CALL(*wizard, query(_, key1, _)).WillOnce(Return(ConditionState::kFalse));
-
- EXPECT_CALL(*wizard, query(_, key2, _)).WillOnce(Return(ConditionState::kTrue));
-
- EventMetricProducer eventProducer(kConfigKey, metric, 1, wizard, bucketStartTimeNs);
-
- eventProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
- eventProducer.onMatchedLogEvent(1 /*matcher index*/, event2);
-
- // TODO: get the report and check the content after the ProtoOutputStream change is done.
- // eventProducer.onDumpReport();
-}
+// TODO(b/149590301): Update this test to use new socket schema.
+//TEST(EventMetricProducerTest, TestEventsWithSlicedCondition) {
+// int64_t bucketStartTimeNs = 10000000000;
+// int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
+//
+// int tagId = 1;
+// int conditionTagId = 2;
+//
+// EventMetric metric;
+// metric.set_id(1);
+// metric.set_condition(StringToId("APP_IN_BACKGROUND_PER_UID_AND_SCREEN_ON"));
+// MetricConditionLink* link = metric.add_links();
+// link->set_condition(StringToId("APP_IN_BACKGROUND_PER_UID"));
+// buildSimpleAtomFieldMatcher(tagId, 1, link->mutable_fields_in_what());
+// buildSimpleAtomFieldMatcher(conditionTagId, 2, link->mutable_fields_in_condition());
+//
+// LogEvent event1(tagId, bucketStartTimeNs + 1);
+// EXPECT_TRUE(event1.write("111"));
+// event1.init();
+// ConditionKey key1;
+// key1[StringToId("APP_IN_BACKGROUND_PER_UID")] = {getMockedDimensionKey(conditionTagId, 2, "111")};
+//
+// LogEvent event2(tagId, bucketStartTimeNs + 10);
+// EXPECT_TRUE(event2.write("222"));
+// event2.init();
+// ConditionKey key2;
+// key2[StringToId("APP_IN_BACKGROUND_PER_UID")] = {getMockedDimensionKey(conditionTagId, 2, "222")};
+//
+// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+// EXPECT_CALL(*wizard, query(_, key1, _)).WillOnce(Return(ConditionState::kFalse));
+//
+// EXPECT_CALL(*wizard, query(_, key2, _)).WillOnce(Return(ConditionState::kTrue));
+//
+// EventMetricProducer eventProducer(kConfigKey, metric, 1, wizard, bucketStartTimeNs);
+//
+// eventProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
+// eventProducer.onMatchedLogEvent(1 /*matcher index*/, event2);
+//
+// // TODO: get the report and check the content after the ProtoOutputStream change is done.
+// // eventProducer.onDumpReport();
+//}
} // namespace statsd
} // namespace os
diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
index 308c43d..609324e 100644
--- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
@@ -88,768 +88,769 @@
EXPECT_EQ(660000000005, gaugeProducer.getCurrentBucketEndTimeNs());
}
-TEST(GaugeMetricProducerTest, TestPulledEventsNoCondition) {
- GaugeMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_gauge_fields_filter()->set_include_all(false);
- metric.set_max_pull_delay_sec(INT_MAX);
- auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
- gaugeFieldMatcher->set_field(tagId);
- gaugeFieldMatcher->add_child()->set_field(1);
- gaugeFieldMatcher->add_child()->set_field(3);
-
- 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<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
- event->write(3);
- event->write("some value");
- event->write(11);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
- logEventMatcherIndex, eventMatcherWizard,
- tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
- pullerManager);
-
- vector<shared_ptr<LogEvent>> allData;
- allData.clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
- event->write(10);
- event->write("some value");
- event->write(11);
- event->init();
- allData.push_back(event);
-
- gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
- EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
- auto it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin();
- EXPECT_EQ(INT, it->mValue.getType());
- EXPECT_EQ(10, it->mValue.int_value);
- it++;
- EXPECT_EQ(11, it->mValue.int_value);
- EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
- EXPECT_EQ(3, gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms
- .front().mFields->begin()->mValue.int_value);
-
- allData.clear();
- std::shared_ptr<LogEvent> event2 = std::make_shared<LogEvent>(tagId, bucket3StartTimeNs + 10);
- event2->write(24);
- event2->write("some value");
- event2->write(25);
- event2->init();
- allData.push_back(event2);
- gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
- EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
- it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin();
- EXPECT_EQ(INT, it->mValue.getType());
- EXPECT_EQ(24, it->mValue.int_value);
- it++;
- EXPECT_EQ(INT, it->mValue.getType());
- EXPECT_EQ(25, it->mValue.int_value);
- // One dimension.
- EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
- EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size());
- it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.front().mFields->begin();
- EXPECT_EQ(INT, it->mValue.getType());
- EXPECT_EQ(10L, it->mValue.int_value);
- it++;
- EXPECT_EQ(INT, it->mValue.getType());
- EXPECT_EQ(11L, it->mValue.int_value);
-
- gaugeProducer.flushIfNeededLocked(bucket4StartTimeNs);
- EXPECT_EQ(0UL, gaugeProducer.mCurrentSlicedBucket->size());
- // One dimension.
- EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
- EXPECT_EQ(3UL, gaugeProducer.mPastBuckets.begin()->second.size());
- it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.front().mFields->begin();
- EXPECT_EQ(INT, it->mValue.getType());
- EXPECT_EQ(24L, it->mValue.int_value);
- it++;
- EXPECT_EQ(INT, it->mValue.getType());
- EXPECT_EQ(25L, it->mValue.int_value);
-}
-
-TEST(GaugeMetricProducerTest, TestPushedEventsWithUpgrade) {
- sp<AlarmMonitor> alarmMonitor;
- GaugeMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_gauge_fields_filter()->set_include_all(true);
-
- Alert alert;
- alert.set_id(101);
- alert.set_metric_id(metricId);
- alert.set_trigger_if_sum_gt(25);
- alert.set_num_buckets(100);
- 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)});
-
- GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
- logEventMatcherIndex, eventMatcherWizard,
- -1 /* -1 means no pulling */, -1, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
-
- sp<AnomalyTracker> anomalyTracker = gaugeProducer.addAnomalyTracker(alert, alarmMonitor);
- EXPECT_TRUE(anomalyTracker != nullptr);
-
- shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
- event1->write(1);
- event1->write(10);
- event1->init();
- gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
- EXPECT_EQ(1UL, (*gaugeProducer.mCurrentSlicedBucket).count(DEFAULT_METRIC_DIMENSION_KEY));
-
- gaugeProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
- EXPECT_EQ(0UL, (*gaugeProducer.mCurrentSlicedBucket).count(DEFAULT_METRIC_DIMENSION_KEY));
- EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ(0L, gaugeProducer.mCurrentBucketNum);
- EXPECT_EQ(eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
- // Partial buckets are not sent to anomaly tracker.
- EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
-
- // Create an event in the same partial bucket.
- shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 59 * NS_PER_SEC);
- event2->write(1);
- event2->write(10);
- event2->init();
- gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
- EXPECT_EQ(0L, gaugeProducer.mCurrentBucketNum);
- EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ((int64_t)eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
- // Partial buckets are not sent to anomaly tracker.
- EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
-
- // Next event should trigger creation of new bucket and send previous full bucket to anomaly
- // tracker.
- shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 65 * NS_PER_SEC);
- event3->write(1);
- event3->write(10);
- event3->init();
- gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
- EXPECT_EQ(1L, gaugeProducer.mCurrentBucketNum);
- EXPECT_EQ(2UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ((int64_t)bucketStartTimeNs + bucketSizeNs, gaugeProducer.mCurrentBucketStartTimeNs);
- EXPECT_EQ(1, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
-
- // Next event should trigger creation of new bucket.
- shared_ptr<LogEvent> event4 =
- make_shared<LogEvent>(tagId, bucketStartTimeNs + 125 * NS_PER_SEC);
- event4->write(1);
- event4->write(10);
- event4->init();
- gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
- EXPECT_EQ(2L, gaugeProducer.mCurrentBucketNum);
- EXPECT_EQ(3UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ(2, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
-}
-
-TEST(GaugeMetricProducerTest, TestPulledWithUpgrade) {
- GaugeMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.set_max_pull_delay_sec(INT_MAX);
- auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
- gaugeFieldMatcher->set_field(tagId);
- gaugeFieldMatcher->add_child()->set_field(2);
-
- 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<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Return(false))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, eventUpgradeTimeNs);
- event->write("some value");
- event->write(2);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
- logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
- bucketStartTimeNs, bucketStartTimeNs, pullerManager);
-
- vector<shared_ptr<LogEvent>> allData;
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
- event->write("some value");
- event->write(1);
- event->init();
- allData.push_back(event);
- gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
- EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
- EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin()
- ->second.front()
- .mFields->begin()
- ->mValue.int_value);
-
- gaugeProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
- EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ(0L, gaugeProducer.mCurrentBucketNum);
- EXPECT_EQ((int64_t)eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
- EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
- EXPECT_EQ(2, gaugeProducer.mCurrentSlicedBucket->begin()
- ->second.front()
- .mFields->begin()
- ->mValue.int_value);
-
- allData.clear();
- event = make_shared<LogEvent>(tagId, bucketStartTimeNs + bucketSizeNs + 1);
- event->write("some value");
- event->write(3);
- event->init();
- allData.push_back(event);
- gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + bucketSizeNs);
- EXPECT_EQ(2UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
- EXPECT_EQ(3, gaugeProducer.mCurrentSlicedBucket->begin()
- ->second.front()
- .mFields->begin()
- ->mValue.int_value);
-}
-
-TEST(GaugeMetricProducerTest, TestPulledWithAppUpgradeDisabled) {
- GaugeMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.set_max_pull_delay_sec(INT_MAX);
- metric.set_split_bucket_for_app_upgrade(false);
- auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
- gaugeFieldMatcher->set_field(tagId);
- gaugeFieldMatcher->add_child()->set_field(2);
-
- 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<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(false));
-
- GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
- logEventMatcherIndex, eventMatcherWizard,
- tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
- pullerManager);
-
- vector<shared_ptr<LogEvent>> allData;
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
- event->write("some value");
- event->write(1);
- event->init();
- allData.push_back(event);
- gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
- EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
- EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin()
- ->second.front()
- .mFields->begin()
- ->mValue.int_value);
-
- gaugeProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
- EXPECT_EQ(0UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ(0L, gaugeProducer.mCurrentBucketNum);
- EXPECT_EQ(bucketStartTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
- EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
- EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin()
- ->second.front()
- .mFields->begin()
- ->mValue.int_value);
-}
-
-TEST(GaugeMetricProducerTest, TestPulledEventsWithCondition) {
- GaugeMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.set_max_pull_delay_sec(INT_MAX);
- auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
- gaugeFieldMatcher->set_field(tagId);
- gaugeFieldMatcher->add_child()->set_field(2);
- metric.set_condition(StringToId("SCREEN_ON"));
-
- 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<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
- event->write("some value");
- event->write(100);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard,
- logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
- bucketStartTimeNs, bucketStartTimeNs, pullerManager);
-
- gaugeProducer.onConditionChanged(true, bucketStartTimeNs + 8);
- EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
- EXPECT_EQ(100, gaugeProducer.mCurrentSlicedBucket->begin()
- ->second.front()
- .mFields->begin()
- ->mValue.int_value);
- EXPECT_EQ(0UL, gaugeProducer.mPastBuckets.size());
-
- vector<shared_ptr<LogEvent>> allData;
- allData.clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
- event->write("some value");
- event->write(110);
- event->init();
- allData.push_back(event);
- gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-
- EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
- EXPECT_EQ(110, gaugeProducer.mCurrentSlicedBucket->begin()
- ->second.front()
- .mFields->begin()
- ->mValue.int_value);
- EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
- EXPECT_EQ(100, gaugeProducer.mPastBuckets.begin()
- ->second.back()
- .mGaugeAtoms.front()
- .mFields->begin()
- ->mValue.int_value);
-
- gaugeProducer.onConditionChanged(false, bucket2StartTimeNs + 10);
- gaugeProducer.flushIfNeededLocked(bucket3StartTimeNs + 10);
- EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
- EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size());
- EXPECT_EQ(110L, gaugeProducer.mPastBuckets.begin()
- ->second.back()
- .mGaugeAtoms.front()
- .mFields->begin()
- ->mValue.int_value);
-}
-
-TEST(GaugeMetricProducerTest, TestPulledEventsWithSlicedCondition) {
- const int conditionTag = 65;
- GaugeMetric metric;
- metric.set_id(1111111);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_gauge_fields_filter()->set_include_all(true);
- metric.set_condition(StringToId("APP_DIED"));
- metric.set_max_pull_delay_sec(INT_MAX);
- auto dim = metric.mutable_dimensions_in_what();
- 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)});
-
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- EXPECT_CALL(*wizard, query(_, _, _))
- .WillRepeatedly(
- Invoke([](const int conditionIndex, const ConditionKey& conditionParameters,
- const bool isPartialLink) {
- int pos[] = {1, 0, 0};
- Field f(conditionTag, pos, 0);
- HashableDimensionKey key;
- key.mutableValues()->emplace_back(f, Value((int32_t)1000000));
-
- return ConditionState::kTrue;
- }));
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
- event->write(1000);
- event->write(100);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard,
- logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
- bucketStartTimeNs, bucketStartTimeNs, pullerManager);
-
- gaugeProducer.onSlicedConditionMayChange(true, bucketStartTimeNs + 8);
-
- EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
- const auto& key = gaugeProducer.mCurrentSlicedBucket->begin()->first;
- EXPECT_EQ(1UL, key.getDimensionKeyInWhat().getValues().size());
- EXPECT_EQ(1000, key.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
-
- EXPECT_EQ(0UL, gaugeProducer.mPastBuckets.size());
-
- vector<shared_ptr<LogEvent>> allData;
- allData.clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
- event->write(1000);
- event->write(110);
- event->init();
- allData.push_back(event);
- gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-
- EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
- EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
-}
-
-TEST(GaugeMetricProducerTest, TestPulledEventsAnomalyDetection) {
- sp<AlarmMonitor> alarmMonitor;
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(false));
-
- GaugeMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.set_max_pull_delay_sec(INT_MAX);
- auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
- 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)});
-
- GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
- logEventMatcherIndex, eventMatcherWizard,
- tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
- pullerManager);
-
- Alert alert;
- alert.set_id(101);
- alert.set_metric_id(metricId);
- alert.set_trigger_if_sum_gt(25);
- alert.set_num_buckets(2);
- const int32_t refPeriodSec = 60;
- alert.set_refractory_period_secs(refPeriodSec);
- sp<AnomalyTracker> anomalyTracker = gaugeProducer.addAnomalyTracker(alert, alarmMonitor);
-
- int tagId = 1;
- std::shared_ptr<LogEvent> event1 = std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
- event1->write("some value");
- event1->write(13);
- event1->init();
-
- gaugeProducer.onDataPulled({event1}, /** succeed */ true, bucketStartTimeNs);
- EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
- EXPECT_EQ(13L, gaugeProducer.mCurrentSlicedBucket->begin()
- ->second.front()
- .mFields->begin()
- ->mValue.int_value);
- EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
-
- std::shared_ptr<LogEvent> event2 =
- std::make_shared<LogEvent>(tagId, bucketStartTimeNs + bucketSizeNs + 20);
- event2->write("some value");
- event2->write(15);
- event2->init();
-
- gaugeProducer.onDataPulled({event2}, /** succeed */ true, bucketStartTimeNs + bucketSizeNs);
- EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
- EXPECT_EQ(15L, gaugeProducer.mCurrentSlicedBucket->begin()
- ->second.front()
- .mFields->begin()
- ->mValue.int_value);
- EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
- std::ceil(1.0 * event2->GetElapsedTimestampNs() / NS_PER_SEC) + refPeriodSec);
-
- std::shared_ptr<LogEvent> event3 =
- std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 10);
- event3->write("some value");
- event3->write(26);
- event3->init();
-
- gaugeProducer.onDataPulled({event3}, /** succeed */ true, bucket2StartTimeNs + 2 * bucketSizeNs);
- EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
- EXPECT_EQ(26L, gaugeProducer.mCurrentSlicedBucket->begin()
- ->second.front()
- .mFields->begin()
- ->mValue.int_value);
- EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
- std::ceil(1.0 * event2->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
-
- // The event4 does not have the gauge field. Thus the current bucket value is 0.
- std::shared_ptr<LogEvent> event4 =
- std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 10);
- event4->write("some value");
- event4->init();
- gaugeProducer.onDataPulled({event4}, /** succeed */ true, bucketStartTimeNs + 3 * bucketSizeNs);
- EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
- EXPECT_TRUE(gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->empty());
-}
-
-TEST(GaugeMetricProducerTest, TestPullOnTrigger) {
- GaugeMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.set_sampling_type(GaugeMetric::FIRST_N_SAMPLES);
- metric.mutable_gauge_fields_filter()->set_include_all(false);
- metric.set_max_pull_delay_sec(INT_MAX);
- auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
- gaugeFieldMatcher->set_field(tagId);
- gaugeFieldMatcher->add_child()->set_field(1);
-
- 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<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
- event->write(4);
- event->init();
- data->push_back(event);
- return true;
- }))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
- event->write(5);
- event->init();
- data->push_back(event);
- return true;
- }))
- .WillOnce(Return(true));
-
- int triggerId = 5;
- GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
- logEventMatcherIndex, eventMatcherWizard,
- tagId, triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
- pullerManager);
-
- vector<shared_ptr<LogEvent>> allData;
-
- EXPECT_EQ(0UL, gaugeProducer.mCurrentSlicedBucket->size());
- LogEvent trigger(triggerId, bucketStartTimeNs + 10);
- trigger.init();
- gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
- EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
- trigger.setElapsedTimestampNs(bucketStartTimeNs + 20);
- gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
- EXPECT_EQ(2UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
- trigger.setElapsedTimestampNs(bucket2StartTimeNs + 1);
- gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
-
- EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
- EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.size());
- EXPECT_EQ(4, gaugeProducer.mPastBuckets.begin()
- ->second.back()
- .mGaugeAtoms[0]
- .mFields->begin()
- ->mValue.int_value);
- EXPECT_EQ(5, gaugeProducer.mPastBuckets.begin()
- ->second.back()
- .mGaugeAtoms[1]
- .mFields->begin()
- ->mValue.int_value);
-}
-
-TEST(GaugeMetricProducerTest, TestRemoveDimensionInOutput) {
- GaugeMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.set_sampling_type(GaugeMetric::FIRST_N_SAMPLES);
- metric.mutable_gauge_fields_filter()->set_include_all(true);
- metric.set_max_pull_delay_sec(INT_MAX);
- auto dimensionMatcher = metric.mutable_dimensions_in_what();
- // use field 1 as dimension.
- dimensionMatcher->set_field(tagId);
- dimensionMatcher->add_child()->set_field(1);
-
- 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<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3);
- event->write(3);
- event->write(4);
- event->init();
- data->push_back(event);
- return true;
- }))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
- event->write(4);
- event->write(5);
- event->init();
- data->push_back(event);
- return true;
- }))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
- event->write(4);
- event->write(6);
- event->init();
- data->push_back(event);
- return true;
- }))
- .WillOnce(Return(true));
-
- int triggerId = 5;
- GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
- logEventMatcherIndex, eventMatcherWizard,
- tagId, triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
- pullerManager);
-
- vector<shared_ptr<LogEvent>> allData;
-
- LogEvent trigger(triggerId, bucketStartTimeNs + 3);
- trigger.init();
- gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
- EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
- trigger.setElapsedTimestampNs(bucketStartTimeNs + 10);
- gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
- EXPECT_EQ(2UL, gaugeProducer.mCurrentSlicedBucket->size());
- EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
- trigger.setElapsedTimestampNs(bucketStartTimeNs + 20);
- gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
- EXPECT_EQ(2UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
- trigger.setElapsedTimestampNs(bucket2StartTimeNs + 1);
- gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
-
- EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.size());
- auto bucketIt = gaugeProducer.mPastBuckets.begin();
- EXPECT_EQ(1UL, bucketIt->second.back().mGaugeAtoms.size());
- EXPECT_EQ(3, bucketIt->first.getDimensionKeyInWhat().getValues().begin()->mValue.int_value);
- EXPECT_EQ(4, bucketIt->second.back().mGaugeAtoms[0].mFields->begin()->mValue.int_value);
- bucketIt++;
- EXPECT_EQ(2UL, bucketIt->second.back().mGaugeAtoms.size());
- EXPECT_EQ(4, bucketIt->first.getDimensionKeyInWhat().getValues().begin()->mValue.int_value);
- EXPECT_EQ(5, bucketIt->second.back().mGaugeAtoms[0].mFields->begin()->mValue.int_value);
- EXPECT_EQ(6, bucketIt->second.back().mGaugeAtoms[1].mFields->begin()->mValue.int_value);
-}
-
-/*
- * Test that BUCKET_TOO_SMALL dump reason is logged when a flushed bucket size
- * is smaller than the "min_bucket_size_nanos" specified in the metric config.
- */
-TEST(GaugeMetricProducerTest_BucketDrop, TestBucketDropWhenBucketTooSmall) {
- GaugeMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(FIVE_MINUTES);
- metric.set_sampling_type(GaugeMetric::FIRST_N_SAMPLES);
- metric.set_min_bucket_size_nanos(10000000000); // 10 seconds
-
- 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<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // Bucket start.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
- event->write("field1");
- event->write(10);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- int triggerId = 5;
- GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
- logEventMatcherIndex, eventMatcherWizard,
- tagId, triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
- pullerManager);
-
- LogEvent trigger(triggerId, bucketStartTimeNs + 3);
- trigger.init();
- gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
-
- // Check dump report.
- ProtoOutputStream output;
- std::set<string> strSet;
- gaugeProducer.onDumpReport(bucketStartTimeNs + 9000000, true /* include recent buckets */,
- true, FAST /* dump_latency */, &strSet, &output);
-
- StatsLogReport report = outputStreamToProto(&output);
- EXPECT_TRUE(report.has_gauge_metrics());
- EXPECT_EQ(0, report.gauge_metrics().data_size());
- EXPECT_EQ(1, report.gauge_metrics().skipped_size());
-
- EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
- report.gauge_metrics().skipped(0).start_bucket_elapsed_millis());
- EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 9000000),
- report.gauge_metrics().skipped(0).end_bucket_elapsed_millis());
- EXPECT_EQ(1, report.gauge_metrics().skipped(0).drop_event_size());
-
- auto dropEvent = report.gauge_metrics().skipped(0).drop_event(0);
- EXPECT_EQ(BucketDropReason::BUCKET_TOO_SMALL, dropEvent.drop_reason());
- EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 9000000), dropEvent.drop_time_millis());
-}
+// TODO(b/149590301): Update these tests to use new socket schema.
+//TEST(GaugeMetricProducerTest, TestPulledEventsNoCondition) {
+// GaugeMetric metric;
+// metric.set_id(metricId);
+// metric.set_bucket(ONE_MINUTE);
+// metric.mutable_gauge_fields_filter()->set_include_all(false);
+// metric.set_max_pull_delay_sec(INT_MAX);
+// auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
+// gaugeFieldMatcher->set_field(tagId);
+// gaugeFieldMatcher->add_child()->set_field(1);
+// gaugeFieldMatcher->add_child()->set_field(3);
+//
+// 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<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+// EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+// event->write(3);
+// event->write("some value");
+// event->write(11);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+// logEventMatcherIndex, eventMatcherWizard,
+// tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
+// pullerManager);
+//
+// vector<shared_ptr<LogEvent>> allData;
+// allData.clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+// event->write(10);
+// event->write("some value");
+// event->write(11);
+// event->init();
+// allData.push_back(event);
+//
+// gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+// EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+// auto it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin();
+// EXPECT_EQ(INT, it->mValue.getType());
+// EXPECT_EQ(10, it->mValue.int_value);
+// it++;
+// EXPECT_EQ(11, it->mValue.int_value);
+// EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
+// EXPECT_EQ(3, gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms
+// .front().mFields->begin()->mValue.int_value);
+//
+// allData.clear();
+// std::shared_ptr<LogEvent> event2 = std::make_shared<LogEvent>(tagId, bucket3StartTimeNs + 10);
+// event2->write(24);
+// event2->write("some value");
+// event2->write(25);
+// event2->init();
+// allData.push_back(event2);
+// gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+// EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+// it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin();
+// EXPECT_EQ(INT, it->mValue.getType());
+// EXPECT_EQ(24, it->mValue.int_value);
+// it++;
+// EXPECT_EQ(INT, it->mValue.getType());
+// EXPECT_EQ(25, it->mValue.int_value);
+// // One dimension.
+// EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
+// EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size());
+// it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.front().mFields->begin();
+// EXPECT_EQ(INT, it->mValue.getType());
+// EXPECT_EQ(10L, it->mValue.int_value);
+// it++;
+// EXPECT_EQ(INT, it->mValue.getType());
+// EXPECT_EQ(11L, it->mValue.int_value);
+//
+// gaugeProducer.flushIfNeededLocked(bucket4StartTimeNs);
+// EXPECT_EQ(0UL, gaugeProducer.mCurrentSlicedBucket->size());
+// // One dimension.
+// EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
+// EXPECT_EQ(3UL, gaugeProducer.mPastBuckets.begin()->second.size());
+// it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.front().mFields->begin();
+// EXPECT_EQ(INT, it->mValue.getType());
+// EXPECT_EQ(24L, it->mValue.int_value);
+// it++;
+// EXPECT_EQ(INT, it->mValue.getType());
+// EXPECT_EQ(25L, it->mValue.int_value);
+//}
+//
+//TEST(GaugeMetricProducerTest, TestPushedEventsWithUpgrade) {
+// sp<AlarmMonitor> alarmMonitor;
+// GaugeMetric metric;
+// metric.set_id(metricId);
+// metric.set_bucket(ONE_MINUTE);
+// metric.mutable_gauge_fields_filter()->set_include_all(true);
+//
+// Alert alert;
+// alert.set_id(101);
+// alert.set_metric_id(metricId);
+// alert.set_trigger_if_sum_gt(25);
+// alert.set_num_buckets(100);
+// 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)});
+//
+// GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+// logEventMatcherIndex, eventMatcherWizard,
+// -1 /* -1 means no pulling */, -1, tagId, bucketStartTimeNs,
+// bucketStartTimeNs, pullerManager);
+//
+// sp<AnomalyTracker> anomalyTracker = gaugeProducer.addAnomalyTracker(alert, alarmMonitor);
+// EXPECT_TRUE(anomalyTracker != nullptr);
+//
+// shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+// event1->write(1);
+// event1->write(10);
+// event1->init();
+// gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
+// EXPECT_EQ(1UL, (*gaugeProducer.mCurrentSlicedBucket).count(DEFAULT_METRIC_DIMENSION_KEY));
+//
+// gaugeProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+// EXPECT_EQ(0UL, (*gaugeProducer.mCurrentSlicedBucket).count(DEFAULT_METRIC_DIMENSION_KEY));
+// EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+// EXPECT_EQ(0L, gaugeProducer.mCurrentBucketNum);
+// EXPECT_EQ(eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
+// // Partial buckets are not sent to anomaly tracker.
+// EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
+//
+// // Create an event in the same partial bucket.
+// shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 59 * NS_PER_SEC);
+// event2->write(1);
+// event2->write(10);
+// event2->init();
+// gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
+// EXPECT_EQ(0L, gaugeProducer.mCurrentBucketNum);
+// EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+// EXPECT_EQ((int64_t)eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
+// // Partial buckets are not sent to anomaly tracker.
+// EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
+//
+// // Next event should trigger creation of new bucket and send previous full bucket to anomaly
+// // tracker.
+// shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 65 * NS_PER_SEC);
+// event3->write(1);
+// event3->write(10);
+// event3->init();
+// gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
+// EXPECT_EQ(1L, gaugeProducer.mCurrentBucketNum);
+// EXPECT_EQ(2UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+// EXPECT_EQ((int64_t)bucketStartTimeNs + bucketSizeNs, gaugeProducer.mCurrentBucketStartTimeNs);
+// EXPECT_EQ(1, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
+//
+// // Next event should trigger creation of new bucket.
+// shared_ptr<LogEvent> event4 =
+// make_shared<LogEvent>(tagId, bucketStartTimeNs + 125 * NS_PER_SEC);
+// event4->write(1);
+// event4->write(10);
+// event4->init();
+// gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
+// EXPECT_EQ(2L, gaugeProducer.mCurrentBucketNum);
+// EXPECT_EQ(3UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+// EXPECT_EQ(2, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
+//}
+//
+//TEST(GaugeMetricProducerTest, TestPulledWithUpgrade) {
+// GaugeMetric metric;
+// metric.set_id(metricId);
+// metric.set_bucket(ONE_MINUTE);
+// metric.set_max_pull_delay_sec(INT_MAX);
+// auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
+// gaugeFieldMatcher->set_field(tagId);
+// gaugeFieldMatcher->add_child()->set_field(2);
+//
+// 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<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+// EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// .WillOnce(Return(false))
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, eventUpgradeTimeNs);
+// event->write("some value");
+// event->write(2);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+// logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
+// bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+//
+// vector<shared_ptr<LogEvent>> allData;
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
+// event->write("some value");
+// event->write(1);
+// event->init();
+// allData.push_back(event);
+// gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
+// EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+// EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin()
+// ->second.front()
+// .mFields->begin()
+// ->mValue.int_value);
+//
+// gaugeProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+// EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+// EXPECT_EQ(0L, gaugeProducer.mCurrentBucketNum);
+// EXPECT_EQ((int64_t)eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
+// EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+// EXPECT_EQ(2, gaugeProducer.mCurrentSlicedBucket->begin()
+// ->second.front()
+// .mFields->begin()
+// ->mValue.int_value);
+//
+// allData.clear();
+// event = make_shared<LogEvent>(tagId, bucketStartTimeNs + bucketSizeNs + 1);
+// event->write("some value");
+// event->write(3);
+// event->init();
+// allData.push_back(event);
+// gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + bucketSizeNs);
+// EXPECT_EQ(2UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+// EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+// EXPECT_EQ(3, gaugeProducer.mCurrentSlicedBucket->begin()
+// ->second.front()
+// .mFields->begin()
+// ->mValue.int_value);
+//}
+//
+//TEST(GaugeMetricProducerTest, TestPulledWithAppUpgradeDisabled) {
+// GaugeMetric metric;
+// metric.set_id(metricId);
+// metric.set_bucket(ONE_MINUTE);
+// metric.set_max_pull_delay_sec(INT_MAX);
+// metric.set_split_bucket_for_app_upgrade(false);
+// auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
+// gaugeFieldMatcher->set_field(tagId);
+// gaugeFieldMatcher->add_child()->set_field(2);
+//
+// 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<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+// EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
+// EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(false));
+//
+// GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+// logEventMatcherIndex, eventMatcherWizard,
+// tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
+// pullerManager);
+//
+// vector<shared_ptr<LogEvent>> allData;
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
+// event->write("some value");
+// event->write(1);
+// event->init();
+// allData.push_back(event);
+// gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
+// EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+// EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin()
+// ->second.front()
+// .mFields->begin()
+// ->mValue.int_value);
+//
+// gaugeProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+// EXPECT_EQ(0UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+// EXPECT_EQ(0L, gaugeProducer.mCurrentBucketNum);
+// EXPECT_EQ(bucketStartTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
+// EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+// EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin()
+// ->second.front()
+// .mFields->begin()
+// ->mValue.int_value);
+//}
+//
+//TEST(GaugeMetricProducerTest, TestPulledEventsWithCondition) {
+// GaugeMetric metric;
+// metric.set_id(metricId);
+// metric.set_bucket(ONE_MINUTE);
+// metric.set_max_pull_delay_sec(INT_MAX);
+// auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
+// gaugeFieldMatcher->set_field(tagId);
+// gaugeFieldMatcher->add_child()->set_field(2);
+// metric.set_condition(StringToId("SCREEN_ON"));
+//
+// 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<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+// EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+// event->write("some value");
+// event->write(100);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard,
+// logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
+// bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+//
+// gaugeProducer.onConditionChanged(true, bucketStartTimeNs + 8);
+// EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+// EXPECT_EQ(100, gaugeProducer.mCurrentSlicedBucket->begin()
+// ->second.front()
+// .mFields->begin()
+// ->mValue.int_value);
+// EXPECT_EQ(0UL, gaugeProducer.mPastBuckets.size());
+//
+// vector<shared_ptr<LogEvent>> allData;
+// allData.clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+// event->write("some value");
+// event->write(110);
+// event->init();
+// allData.push_back(event);
+// gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//
+// EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+// EXPECT_EQ(110, gaugeProducer.mCurrentSlicedBucket->begin()
+// ->second.front()
+// .mFields->begin()
+// ->mValue.int_value);
+// EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
+// EXPECT_EQ(100, gaugeProducer.mPastBuckets.begin()
+// ->second.back()
+// .mGaugeAtoms.front()
+// .mFields->begin()
+// ->mValue.int_value);
+//
+// gaugeProducer.onConditionChanged(false, bucket2StartTimeNs + 10);
+// gaugeProducer.flushIfNeededLocked(bucket3StartTimeNs + 10);
+// EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
+// EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size());
+// EXPECT_EQ(110L, gaugeProducer.mPastBuckets.begin()
+// ->second.back()
+// .mGaugeAtoms.front()
+// .mFields->begin()
+// ->mValue.int_value);
+//}
+//
+//TEST(GaugeMetricProducerTest, TestPulledEventsWithSlicedCondition) {
+// const int conditionTag = 65;
+// GaugeMetric metric;
+// metric.set_id(1111111);
+// metric.set_bucket(ONE_MINUTE);
+// metric.mutable_gauge_fields_filter()->set_include_all(true);
+// metric.set_condition(StringToId("APP_DIED"));
+// metric.set_max_pull_delay_sec(INT_MAX);
+// auto dim = metric.mutable_dimensions_in_what();
+// 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)});
+//
+// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+// EXPECT_CALL(*wizard, query(_, _, _))
+// .WillRepeatedly(
+// Invoke([](const int conditionIndex, const ConditionKey& conditionParameters,
+// const bool isPartialLink) {
+// int pos[] = {1, 0, 0};
+// Field f(conditionTag, pos, 0);
+// HashableDimensionKey key;
+// key.mutableValues()->emplace_back(f, Value((int32_t)1000000));
+//
+// return ConditionState::kTrue;
+// }));
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+// EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+// event->write(1000);
+// event->write(100);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard,
+// logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
+// bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+//
+// gaugeProducer.onSlicedConditionMayChange(true, bucketStartTimeNs + 8);
+//
+// EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+// const auto& key = gaugeProducer.mCurrentSlicedBucket->begin()->first;
+// EXPECT_EQ(1UL, key.getDimensionKeyInWhat().getValues().size());
+// EXPECT_EQ(1000, key.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+//
+// EXPECT_EQ(0UL, gaugeProducer.mPastBuckets.size());
+//
+// vector<shared_ptr<LogEvent>> allData;
+// allData.clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+// event->write(1000);
+// event->write(110);
+// event->init();
+// allData.push_back(event);
+// gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//
+// EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+// EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
+//}
+//
+//TEST(GaugeMetricProducerTest, TestPulledEventsAnomalyDetection) {
+// sp<AlarmMonitor> alarmMonitor;
+// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+// EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
+// EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(false));
+//
+// GaugeMetric metric;
+// metric.set_id(metricId);
+// metric.set_bucket(ONE_MINUTE);
+// metric.set_max_pull_delay_sec(INT_MAX);
+// auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
+// 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)});
+//
+// GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+// logEventMatcherIndex, eventMatcherWizard,
+// tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
+// pullerManager);
+//
+// Alert alert;
+// alert.set_id(101);
+// alert.set_metric_id(metricId);
+// alert.set_trigger_if_sum_gt(25);
+// alert.set_num_buckets(2);
+// const int32_t refPeriodSec = 60;
+// alert.set_refractory_period_secs(refPeriodSec);
+// sp<AnomalyTracker> anomalyTracker = gaugeProducer.addAnomalyTracker(alert, alarmMonitor);
+//
+// int tagId = 1;
+// std::shared_ptr<LogEvent> event1 = std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
+// event1->write("some value");
+// event1->write(13);
+// event1->init();
+//
+// gaugeProducer.onDataPulled({event1}, /** succeed */ true, bucketStartTimeNs);
+// EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+// EXPECT_EQ(13L, gaugeProducer.mCurrentSlicedBucket->begin()
+// ->second.front()
+// .mFields->begin()
+// ->mValue.int_value);
+// EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
+//
+// std::shared_ptr<LogEvent> event2 =
+// std::make_shared<LogEvent>(tagId, bucketStartTimeNs + bucketSizeNs + 20);
+// event2->write("some value");
+// event2->write(15);
+// event2->init();
+//
+// gaugeProducer.onDataPulled({event2}, /** succeed */ true, bucketStartTimeNs + bucketSizeNs);
+// EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+// EXPECT_EQ(15L, gaugeProducer.mCurrentSlicedBucket->begin()
+// ->second.front()
+// .mFields->begin()
+// ->mValue.int_value);
+// EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
+// std::ceil(1.0 * event2->GetElapsedTimestampNs() / NS_PER_SEC) + refPeriodSec);
+//
+// std::shared_ptr<LogEvent> event3 =
+// std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 10);
+// event3->write("some value");
+// event3->write(26);
+// event3->init();
+//
+// gaugeProducer.onDataPulled({event3}, /** succeed */ true, bucket2StartTimeNs + 2 * bucketSizeNs);
+// EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+// EXPECT_EQ(26L, gaugeProducer.mCurrentSlicedBucket->begin()
+// ->second.front()
+// .mFields->begin()
+// ->mValue.int_value);
+// EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
+// std::ceil(1.0 * event2->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
+//
+// // The event4 does not have the gauge field. Thus the current bucket value is 0.
+// std::shared_ptr<LogEvent> event4 =
+// std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 10);
+// event4->write("some value");
+// event4->init();
+// gaugeProducer.onDataPulled({event4}, /** succeed */ true, bucketStartTimeNs + 3 * bucketSizeNs);
+// EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+// EXPECT_TRUE(gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->empty());
+//}
+//
+//TEST(GaugeMetricProducerTest, TestPullOnTrigger) {
+// GaugeMetric metric;
+// metric.set_id(metricId);
+// metric.set_bucket(ONE_MINUTE);
+// metric.set_sampling_type(GaugeMetric::FIRST_N_SAMPLES);
+// metric.mutable_gauge_fields_filter()->set_include_all(false);
+// metric.set_max_pull_delay_sec(INT_MAX);
+// auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
+// gaugeFieldMatcher->set_field(tagId);
+// gaugeFieldMatcher->add_child()->set_field(1);
+//
+// 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<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+// event->write(4);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
+// event->write(5);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// .WillOnce(Return(true));
+//
+// int triggerId = 5;
+// GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+// logEventMatcherIndex, eventMatcherWizard,
+// tagId, triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
+// pullerManager);
+//
+// vector<shared_ptr<LogEvent>> allData;
+//
+// EXPECT_EQ(0UL, gaugeProducer.mCurrentSlicedBucket->size());
+// LogEvent trigger(triggerId, bucketStartTimeNs + 10);
+// trigger.init();
+// gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
+// EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
+// trigger.setElapsedTimestampNs(bucketStartTimeNs + 20);
+// gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
+// EXPECT_EQ(2UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
+// trigger.setElapsedTimestampNs(bucket2StartTimeNs + 1);
+// gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
+//
+// EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
+// EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.size());
+// EXPECT_EQ(4, gaugeProducer.mPastBuckets.begin()
+// ->second.back()
+// .mGaugeAtoms[0]
+// .mFields->begin()
+// ->mValue.int_value);
+// EXPECT_EQ(5, gaugeProducer.mPastBuckets.begin()
+// ->second.back()
+// .mGaugeAtoms[1]
+// .mFields->begin()
+// ->mValue.int_value);
+//}
+//
+//TEST(GaugeMetricProducerTest, TestRemoveDimensionInOutput) {
+// GaugeMetric metric;
+// metric.set_id(metricId);
+// metric.set_bucket(ONE_MINUTE);
+// metric.set_sampling_type(GaugeMetric::FIRST_N_SAMPLES);
+// metric.mutable_gauge_fields_filter()->set_include_all(true);
+// metric.set_max_pull_delay_sec(INT_MAX);
+// auto dimensionMatcher = metric.mutable_dimensions_in_what();
+// // use field 1 as dimension.
+// dimensionMatcher->set_field(tagId);
+// dimensionMatcher->add_child()->set_field(1);
+//
+// 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<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3);
+// event->write(3);
+// event->write(4);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+// event->write(4);
+// event->write(5);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
+// event->write(4);
+// event->write(6);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// .WillOnce(Return(true));
+//
+// int triggerId = 5;
+// GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+// logEventMatcherIndex, eventMatcherWizard,
+// tagId, triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
+// pullerManager);
+//
+// vector<shared_ptr<LogEvent>> allData;
+//
+// LogEvent trigger(triggerId, bucketStartTimeNs + 3);
+// trigger.init();
+// gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
+// EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+// trigger.setElapsedTimestampNs(bucketStartTimeNs + 10);
+// gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
+// EXPECT_EQ(2UL, gaugeProducer.mCurrentSlicedBucket->size());
+// EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
+// trigger.setElapsedTimestampNs(bucketStartTimeNs + 20);
+// gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
+// EXPECT_EQ(2UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
+// trigger.setElapsedTimestampNs(bucket2StartTimeNs + 1);
+// gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
+//
+// EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.size());
+// auto bucketIt = gaugeProducer.mPastBuckets.begin();
+// EXPECT_EQ(1UL, bucketIt->second.back().mGaugeAtoms.size());
+// EXPECT_EQ(3, bucketIt->first.getDimensionKeyInWhat().getValues().begin()->mValue.int_value);
+// EXPECT_EQ(4, bucketIt->second.back().mGaugeAtoms[0].mFields->begin()->mValue.int_value);
+// bucketIt++;
+// EXPECT_EQ(2UL, bucketIt->second.back().mGaugeAtoms.size());
+// EXPECT_EQ(4, bucketIt->first.getDimensionKeyInWhat().getValues().begin()->mValue.int_value);
+// EXPECT_EQ(5, bucketIt->second.back().mGaugeAtoms[0].mFields->begin()->mValue.int_value);
+// EXPECT_EQ(6, bucketIt->second.back().mGaugeAtoms[1].mFields->begin()->mValue.int_value);
+//}
+//
+///*
+// * Test that BUCKET_TOO_SMALL dump reason is logged when a flushed bucket size
+// * is smaller than the "min_bucket_size_nanos" specified in the metric config.
+// */
+//TEST(GaugeMetricProducerTest_BucketDrop, TestBucketDropWhenBucketTooSmall) {
+// GaugeMetric metric;
+// metric.set_id(metricId);
+// metric.set_bucket(FIVE_MINUTES);
+// metric.set_sampling_type(GaugeMetric::FIRST_N_SAMPLES);
+// metric.set_min_bucket_size_nanos(10000000000); // 10 seconds
+//
+// 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<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // Bucket start.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+// event->write("field1");
+// event->write(10);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// int triggerId = 5;
+// GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+// logEventMatcherIndex, eventMatcherWizard,
+// tagId, triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
+// pullerManager);
+//
+// LogEvent trigger(triggerId, bucketStartTimeNs + 3);
+// trigger.init();
+// gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
+//
+// // Check dump report.
+// ProtoOutputStream output;
+// std::set<string> strSet;
+// gaugeProducer.onDumpReport(bucketStartTimeNs + 9000000, true /* include recent buckets */,
+// true, FAST /* dump_latency */, &strSet, &output);
+//
+// StatsLogReport report = outputStreamToProto(&output);
+// EXPECT_TRUE(report.has_gauge_metrics());
+// EXPECT_EQ(0, report.gauge_metrics().data_size());
+// EXPECT_EQ(1, report.gauge_metrics().skipped_size());
+//
+// EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+// report.gauge_metrics().skipped(0).start_bucket_elapsed_millis());
+// EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 9000000),
+// report.gauge_metrics().skipped(0).end_bucket_elapsed_millis());
+// EXPECT_EQ(1, report.gauge_metrics().skipped(0).drop_event_size());
+//
+// auto dropEvent = report.gauge_metrics().skipped(0).drop_event(0);
+// EXPECT_EQ(BucketDropReason::BUCKET_TOO_SMALL, dropEvent.drop_reason());
+// EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 9000000), dropEvent.drop_time_millis());
+//}
} // namespace statsd
} // namespace os
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index f6245ac..e48f378 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -79,4533 +79,4535 @@
}
}
-class ValueMetricProducerTestHelper {
-
- public:
- static shared_ptr<LogEvent> createEvent(int64_t eventTimeNs, int64_t value) {
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, eventTimeNs);
- event->write(tagId);
- event->write(value);
- event->write(value);
- event->init();
- return event;
- }
-
- 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)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-
- sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
- kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
- logEventMatcherIndex, eventMatcherWizard, tagId,
- bucketStartTimeNs, bucketStartTimeNs, pullerManager);
- return valueProducer;
- }
-
- static sp<ValueMetricProducer> createValueProducerWithCondition(
- 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)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-
- sp<ValueMetricProducer> valueProducer =
- new ValueMetricProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
- valueProducer->mCondition = ConditionState::kFalse;
- return valueProducer;
- }
-
- static sp<ValueMetricProducer> createValueProducerWithNoInitialCondition(
- 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)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-
- sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
- kConfigKey, metric, 1, wizard, logEventMatcherIndex, eventMatcherWizard, tagId,
- bucketStartTimeNs, bucketStartTimeNs, pullerManager);
- return valueProducer;
- }
-
- static sp<ValueMetricProducer> createValueProducerWithState(
- 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)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
- sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
- kConfigKey, metric, -1 /* no condition */, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager, {},
- {}, slicedStateAtoms, stateGroupMap);
- return valueProducer;
- }
-
- static ValueMetric createMetric() {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
- metric.set_max_pull_delay_sec(INT_MAX);
- return metric;
- }
-
- static ValueMetric createMetricWithCondition() {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- metric.set_condition(StringToId("SCREEN_ON"));
- return metric;
- }
-
- static ValueMetric createMetricWithState(string state) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- metric.add_slice_by_state(StringToId(state));
- return metric;
- }
-};
-
-/*
- * Tests that the first bucket works correctly
- */
-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)});
- 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);
-
- EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
- EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
- EXPECT_EQ(60 * NS_PER_SEC + startTimeBase,
- valueProducer.calcPreviousBucketEndTime(2 * 60 * NS_PER_SEC));
- EXPECT_EQ(2 * 60 * NS_PER_SEC + startTimeBase,
- valueProducer.calcPreviousBucketEndTime(3 * 60 * NS_PER_SEC));
-}
-
-/*
- * Tests that the first bucket works correctly
- */
-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)});
- 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);
-
- EXPECT_EQ(600500000000, valueProducer.mCurrentBucketStartTimeNs);
- EXPECT_EQ(10, valueProducer.mCurrentBucketNum);
- EXPECT_EQ(660000000005, valueProducer.getCurrentBucketEndTimeNs());
-}
-
-/*
- * Tests pulled atoms with no conditions
- */
-TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
- event->write(tagId);
- event->write(3);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-
- vector<shared_ptr<LogEvent>> allData;
- allData.clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
- event->write(tagId);
- event->write(11);
- event->init();
- allData.push_back(event);
-
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
- // has one slice
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(11, curBaseInfo.base.long_value);
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(8, curInterval.value.long_value);
- EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
- EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
- EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
-
- allData.clear();
- event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
- event->write(tagId);
- event->write(23);
- event->init();
- allData.push_back(event);
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
- // has one slice
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(23, curBaseInfo.base.long_value);
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(12, curInterval.value.long_value);
- EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
- EXPECT_EQ(2UL, valueProducer->mPastBuckets.begin()->second.size());
- EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
- EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
- EXPECT_EQ(12, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
- EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs);
-
- allData.clear();
- event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
- event->write(tagId);
- event->write(36);
- event->init();
- allData.push_back(event);
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(36, curBaseInfo.base.long_value);
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(13, curInterval.value.long_value);
- EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
- EXPECT_EQ(3UL, valueProducer->mPastBuckets.begin()->second.size());
- EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
- EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
- EXPECT_EQ(12, valueProducer->mPastBuckets.begin()->second[1].values[0].long_value);
- EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[1].mConditionTrueNs);
- EXPECT_EQ(13, valueProducer->mPastBuckets.begin()->second[2].values[0].long_value);
- EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[2].mConditionTrueNs);
-}
-
-TEST(ValueMetricProducerTest, TestPartialBucketCreated) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // Initialize bucket.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
- event->write(tagId);
- event->write(1);
- event->init();
- data->push_back(event);
- return true;
- }))
- // Partial bucket.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
- event->write(tagId);
- event->write(5);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-
- // First bucket ends.
- vector<shared_ptr<LogEvent>> allData;
- allData.clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
- event->write(tagId);
- event->write(2);
- event->init();
- allData.push_back(event);
- valueProducer->onDataPulled(allData, /** success */ true, bucket2StartTimeNs);
-
- // Partial buckets created in 2nd bucket.
- valueProducer->notifyAppUpgrade(bucket2StartTimeNs + 2, "com.foo", 10000, 1);
-
- // One full bucket and one partial bucket.
- EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
- vector<ValueBucket> buckets = valueProducer->mPastBuckets.begin()->second;
- EXPECT_EQ(2UL, buckets.size());
- // Full bucket (2 - 1)
- EXPECT_EQ(1, buckets[0].values[0].long_value);
- EXPECT_EQ(bucketSizeNs, buckets[0].mConditionTrueNs);
- // Full bucket (5 - 3)
- EXPECT_EQ(3, buckets[1].values[0].long_value);
- // partial bucket [bucket2StartTimeNs, bucket2StartTimeNs + 2]
- EXPECT_EQ(2, buckets[1].mConditionTrueNs);
-}
-
-/*
- * Tests pulled atoms with filtering
- */
-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);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
- event->write(3);
- event->write(3);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
- kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
-
- vector<shared_ptr<LogEvent>> allData;
- allData.clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
- event->write(3);
- event->write(11);
- event->init();
- allData.push_back(event);
-
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
- // has one slice
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(11, curBaseInfo.base.long_value);
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(8, curInterval.value.long_value);
- EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
- EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
- EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
-
- allData.clear();
- event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
- event->write(4);
- event->write(23);
- event->init();
- allData.push_back(event);
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
- // No new data seen, so data has been cleared.
- EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
-
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(11, curBaseInfo.base.long_value);
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(8, curInterval.value.long_value);
- EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
- EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
- EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
-
- allData.clear();
- event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
- event->write(3);
- event->write(36);
- event->init();
- allData.push_back(event);
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-
- // the base was reset
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(36, curBaseInfo.base.long_value);
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
- EXPECT_EQ(1UL, valueProducer->mPastBuckets.begin()->second.size());
- EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
- EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs);
-}
-
-/*
- * Tests pulled atoms with no conditions and take absolute value after reset
- */
-TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- metric.set_use_absolute_value_on_reset(true);
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(true));
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-
- vector<shared_ptr<LogEvent>> allData;
- allData.clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
- event->write(tagId);
- event->write(11);
- event->init();
- allData.push_back(event);
-
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
- // has one slice
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(11, curBaseInfo.base.long_value);
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
-
- allData.clear();
- event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
- event->write(tagId);
- event->write(10);
- event->init();
- allData.push_back(event);
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
- // has one slice
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(10, curBaseInfo.base.long_value);
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(10, curInterval.value.long_value);
- EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
- EXPECT_EQ(10, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
- EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs);
-
- allData.clear();
- event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
- event->write(tagId);
- event->write(36);
- event->init();
- allData.push_back(event);
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(36, curBaseInfo.base.long_value);
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(26, curInterval.value.long_value);
- EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
- EXPECT_EQ(2UL, valueProducer->mPastBuckets.begin()->second.size());
- EXPECT_EQ(10, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
- EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
- EXPECT_EQ(26, valueProducer->mPastBuckets.begin()->second[1].values[0].long_value);
- EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[1].mConditionTrueNs);
-}
-
-/*
- * Tests pulled atoms with no conditions and take zero value after reset
- */
-TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(false));
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-
- vector<shared_ptr<LogEvent>> allData;
- allData.clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
- event->write(tagId);
- event->write(11);
- event->init();
- allData.push_back(event);
-
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
- // has one slice
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(11, curBaseInfo.base.long_value);
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
-
- allData.clear();
- event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
- event->write(tagId);
- event->write(10);
- event->init();
- allData.push_back(event);
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
- // has one slice
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(10, curBaseInfo.base.long_value);
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
-
- allData.clear();
- event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
- event->write(tagId);
- event->write(36);
- event->init();
- allData.push_back(event);
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(36, curBaseInfo.base.long_value);
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(26, curInterval.value.long_value);
- EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
- EXPECT_EQ(26, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
- EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
-}
-
-/*
- * Test pulled event with non sliced condition.
- */
-TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
- event->write(tagId);
- event->write(100);
- event->init();
- data->push_back(event);
- return true;
- }))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
- event->write(tagId);
- event->write(130);
- event->init();
- data->push_back(event);
- return true;
- }))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
- event->write(tagId);
- event->write(180);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
-
- // has one slice
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- // startUpdated:false sum:0 start:100
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(100, curBaseInfo.base.long_value);
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
-
- vector<shared_ptr<LogEvent>> allData;
- allData.clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
- event->write(1);
- event->write(110);
- event->init();
- allData.push_back(event);
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
- assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs - 8});
-
- // has one slice
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(110, curBaseInfo.base.long_value);
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(10, curInterval.value.long_value);
-
- valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
- assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs - 8});
-
- // has one slice
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasValue);
- EXPECT_EQ(20, curInterval.value.long_value);
- EXPECT_EQ(false, curBaseInfo.hasBase);
-
- valueProducer->onConditionChanged(true, bucket3StartTimeNs + 1);
- assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10, 20}, {bucketSizeNs - 8, 1});
-}
-
-TEST(ValueMetricProducerTest, TestPushedEventsWithUpgrade) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
- eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
- pullerManager);
-
- shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
- event1->write(1);
- event1->write(10);
- event1->init();
- valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-
- valueProducer.notifyAppUpgrade(bucketStartTimeNs + 150, "ANY.APP", 1, 1);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ(bucketStartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs);
-
- shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 59 * NS_PER_SEC);
- event2->write(1);
- event2->write(10);
- event2->init();
- valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ(bucketStartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs);
-
- // Next value should create a new bucket.
- shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 65 * NS_PER_SEC);
- event3->write(1);
- event3->write(10);
- event3->init();
- valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
- EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, valueProducer.mCurrentBucketStartTimeNs);
-}
-
-TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Return(true))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 149);
- event->write(tagId);
- event->write(120);
- event->init();
- data->push_back(event);
- return true;
- }));
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
-
- vector<shared_ptr<LogEvent>> allData;
- allData.clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
- event->write(tagId);
- event->write(100);
- event->init();
- allData.push_back(event);
-
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-
- valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 150, "ANY.APP", 1, 1);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ(bucket2StartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs);
- assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {20}, {150});
-
- allData.clear();
- event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
- event->write(tagId);
- event->write(150);
- event->init();
- allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
- EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ(bucket3StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
- EXPECT_EQ(20L,
- valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].values[0].long_value);
- assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {20, 30},
- {150, bucketSizeNs - 150});
-}
-
-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)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(true));
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
-
- vector<shared_ptr<LogEvent>> allData;
- allData.clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
- event->write(tagId);
- event->write(100);
- event->init();
- allData.push_back(event);
-
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-
- valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 150, "ANY.APP", 1, 1);
- EXPECT_EQ(0UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ(bucket2StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
-}
-
-TEST(ValueMetricProducerTest, TestPulledValueWithUpgradeWhileConditionFalse) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
- event->write(tagId);
- event->write(100);
- event->init();
- data->push_back(event);
- return true;
- }))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs - 100);
- event->write(tagId);
- event->write(120);
- event->init();
- data->push_back(event);
- return true;
- }));
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
-
- valueProducer->onConditionChanged(false, bucket2StartTimeNs-100);
- EXPECT_FALSE(valueProducer->mCondition);
-
- valueProducer->notifyAppUpgrade(bucket2StartTimeNs-50, "ANY.APP", 1, 1);
- // Expect one full buckets already done and starting a partial bucket.
- EXPECT_EQ(bucket2StartTimeNs-50, valueProducer->mCurrentBucketStartTimeNs);
- EXPECT_EQ(1UL, valueProducer->mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ(bucketStartTimeNs,
- valueProducer->mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
- assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20},
- {(bucket2StartTimeNs - 100) - (bucketStartTimeNs + 1)});
- EXPECT_FALSE(valueProducer->mCondition);
-}
-
-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)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
- eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
- pullerManager);
-
- shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
- event1->write(1);
- event1->write(10);
- event1->init();
- shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
- event2->write(1);
- event2->write(20);
- event2->init();
- valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
- // has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(10, curInterval.value.long_value);
- EXPECT_EQ(true, curInterval.hasValue);
-
- valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
-
- // has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(30, curInterval.value.long_value);
-
- valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
- assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {30}, {bucketSizeNs});
-}
-
-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)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
- pullerManager);
- valueProducer.mCondition = ConditionState::kFalse;
-
- shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
- event1->write(1);
- event1->write(10);
- event1->init();
- valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
- // has 1 slice
- EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
-
- valueProducer.onConditionChangedLocked(true, bucketStartTimeNs + 15);
- shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
- event2->write(1);
- event2->write(20);
- event2->init();
- valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
-
- // has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(20, curInterval.value.long_value);
-
- shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 30);
- event3->write(1);
- event3->write(30);
- event3->init();
- valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
-
- // has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(50, curInterval.value.long_value);
-
- valueProducer.onConditionChangedLocked(false, bucketStartTimeNs + 35);
- shared_ptr<LogEvent> event4 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 40);
- event4->write(1);
- event4->write(40);
- event4->init();
- valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
-
- // has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(50, curInterval.value.long_value);
-
- valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
- assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {50}, {20});
-}
-
-TEST(ValueMetricProducerTest, TestAnomalyDetection) {
- sp<AlarmMonitor> alarmMonitor;
- Alert alert;
- alert.set_id(101);
- alert.set_metric_id(metricId);
- alert.set_trigger_if_sum_gt(130);
- alert.set_num_buckets(2);
- const int32_t refPeriodSec = 3;
- alert.set_refractory_period_secs(refPeriodSec);
-
- ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
- logEventMatcherIndex, eventMatcherWizard, -1 /*not pulled*/,
- bucketStartTimeNs, bucketStartTimeNs, pullerManager);
-
- sp<AnomalyTracker> anomalyTracker = valueProducer.addAnomalyTracker(alert, alarmMonitor);
-
-
- shared_ptr<LogEvent> event1
- = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1 * NS_PER_SEC);
- event1->write(161);
- event1->write(10); // value of interest
- event1->init();
- shared_ptr<LogEvent> event2
- = make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 + NS_PER_SEC);
- event2->write(162);
- event2->write(20); // value of interest
- event2->init();
- shared_ptr<LogEvent> event3
- = make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 1 * NS_PER_SEC);
- event3->write(163);
- event3->write(130); // value of interest
- event3->init();
- shared_ptr<LogEvent> event4
- = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 1 * NS_PER_SEC);
- event4->write(35);
- event4->write(1); // value of interest
- event4->init();
- shared_ptr<LogEvent> event5
- = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2 * NS_PER_SEC);
- event5->write(45);
- event5->write(150); // value of interest
- event5->init();
- shared_ptr<LogEvent> event6
- = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 10 * NS_PER_SEC);
- event6->write(25);
- event6->write(160); // value of interest
- event6->init();
-
- // Two events in bucket #0.
- valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
- valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
- // Value sum == 30 <= 130.
- EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
-
- // One event in bucket #2. No alarm as bucket #0 is trashed out.
- valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
- // Value sum == 130 <= 130.
- EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
-
- // Three events in bucket #3.
- valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
- // Anomaly at event 4 since Value sum == 131 > 130!
- EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
- std::ceil(1.0 * event4->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
- valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event5);
- // Event 5 is within 3 sec refractory period. Thus last alarm timestamp is still event4.
- EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
- std::ceil(1.0 * event4->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
-
- valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event6);
- // Anomaly at event 6 since Value sum == 160 > 130 and after refractory period.
- EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
- std::ceil(1.0 * event6->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
-}
-
-// 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, _)).WillOnce(Return(true));
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-
- vector<shared_ptr<LogEvent>> allData;
- // pull 1
- allData.clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
- event->write(tagId);
- event->write(11);
- event->init();
- allData.push_back(event);
-
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
- // has one slice
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-
- // startUpdated:true sum:0 start:11
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(11, curBaseInfo.base.long_value);
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
-
- // pull 2 at correct time
- allData.clear();
- event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
- event->write(tagId);
- event->write(23);
- event->init();
- allData.push_back(event);
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
- // has one slice
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- // tartUpdated:false sum:12
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(23, curBaseInfo.base.long_value);
- EXPECT_EQ(false, curInterval.hasValue);
- assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {12}, {bucketSizeNs});
-
- // pull 3 come late.
- // The previous bucket gets closed with error. (Has start value 23, no ending)
- // Another bucket gets closed with error. (No start, but ending with 36)
- // The new bucket is back to normal.
- allData.clear();
- event = make_shared<LogEvent>(tagId, bucket6StartTimeNs + 1);
- event->write(tagId);
- event->write(36);
- event->init();
- allData.push_back(event);
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket6StartTimeNs);
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- // startUpdated:false sum:12
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(36, curBaseInfo.base.long_value);
- EXPECT_EQ(false, curInterval.hasValue);
- assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {12}, {bucketSizeNs});
-}
-
-/*
- * Test pulled event with non sliced condition. The pull on boundary come late because the alarm
- * was delivered late.
- */
-TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // condition becomes true
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
- event->write(tagId);
- event->write(100);
- event->init();
- data->push_back(event);
- return true;
- }))
- // condition becomes false
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
- event->write(tagId);
- event->write(120);
- event->init();
- data->push_back(event);
- return true;
- }));
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
-
- // has one slice
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(100, curBaseInfo.base.long_value);
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
-
- // 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];
- assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
- EXPECT_EQ(false, curBaseInfo.hasBase);
-
- // Now the alarm is delivered.
- // since the condition turned to off before this pull finish, it has no effect
- vector<shared_ptr<LogEvent>> allData;
- allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 110));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-
- assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(false, curBaseInfo.hasBase);
- EXPECT_EQ(false, curInterval.hasValue);
-}
-
-/*
- * Test pulled event with non sliced condition. The pull on boundary come late, after the condition
- * change to false, and then true again. This is due to alarm delivered late.
- */
-TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // condition becomes true
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
- event->write(tagId);
- event->write(100);
- event->init();
- data->push_back(event);
- return true;
- }))
- // condition becomes false
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
- event->write(tagId);
- event->write(120);
- event->init();
- data->push_back(event);
- return true;
- }))
- // condition becomes true again
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 25);
- event->write(tagId);
- event->write(130);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
-
- // has one slice
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- // startUpdated:false sum:0 start:100
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(100, curBaseInfo.base.long_value);
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
-
- // pull on bucket boundary come late, condition change happens before it
- valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
- assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(false, curBaseInfo.hasBase);
- EXPECT_EQ(false, curInterval.hasValue);
-
- // condition changed to true again, before the pull alarm is delivered
- valueProducer->onConditionChanged(true, bucket2StartTimeNs + 25);
- assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(130, curBaseInfo.base.long_value);
- EXPECT_EQ(false, curInterval.hasValue);
-
- // Now the alarm is delivered, but it is considered late, the data will be used
- // for the new bucket since it was just pulled.
- vector<shared_ptr<LogEvent>> allData;
- allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 50, 140));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 50);
-
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(140, curBaseInfo.base.long_value);
- EXPECT_EQ(true, curInterval.hasValue);
- EXPECT_EQ(10, curInterval.value.long_value);
- assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
-
- allData.clear();
- allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket3StartTimeNs, 160));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
- assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20, 30},
- {bucketSizeNs - 8, bucketSizeNs - 24});
-}
-
-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)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
- eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
- pullerManager);
-
- shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
- event1->write(1);
- event1->write(10);
- event1->init();
- shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
- event2->write(1);
- event2->write(20);
- event2->init();
- valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
- // has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(10, curInterval.value.long_value);
- EXPECT_EQ(true, curInterval.hasValue);
-
- valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
-
- // has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(10, curInterval.value.long_value);
-
- valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
- assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {10}, {bucketSizeNs});
-}
-
-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)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
- eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
- pullerManager);
-
- shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
- event1->write(1);
- event1->write(10);
- event1->init();
- shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
- event2->write(1);
- event2->write(20);
- event2->init();
- valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
- // has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(10, curInterval.value.long_value);
- EXPECT_EQ(true, curInterval.hasValue);
-
- valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
-
- // has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(20, curInterval.value.long_value);
-
- valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
- /* EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); */
- /* EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size()); */
- /* EXPECT_EQ(20, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value); */
-}
-
-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)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
- eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
- pullerManager);
-
- shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
- event1->write(1);
- event1->write(10);
- event1->init();
- shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
- event2->write(1);
- event2->write(15);
- event2->init();
- valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
- // has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval;
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(10, curInterval.value.long_value);
- EXPECT_EQ(true, curInterval.hasValue);
- EXPECT_EQ(1, curInterval.sampleSize);
-
- valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
-
- // has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(25, curInterval.value.long_value);
- EXPECT_EQ(2, curInterval.sampleSize);
-
- valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
-
- EXPECT_TRUE(std::abs(valueProducer.mPastBuckets.begin()->second.back().values[0].double_value -
- 12.5) < epsilon);
-}
-
-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)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
- eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
- pullerManager);
-
- shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
- event1->write(1);
- event1->write(10);
- event1->init();
- shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
- event2->write(1);
- event2->write(15);
- event2->init();
- valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
- // has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(10, curInterval.value.long_value);
- EXPECT_EQ(true, curInterval.hasValue);
-
- valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
-
- // has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(25, curInterval.value.long_value);
-
- valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
- assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {25}, {bucketSizeNs});
-}
-
-TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- 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)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
- eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
- pullerManager);
-
- shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
- event1->write(1);
- event1->write(10);
- event1->init();
- shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 15);
- event2->write(1);
- event2->write(15);
- event2->init();
- valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
- // has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(10, curBaseInfo.base.long_value);
- EXPECT_EQ(false, curInterval.hasValue);
-
- valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
-
- // has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasValue);
- EXPECT_EQ(5, curInterval.value.long_value);
-
- // no change in data.
- shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
- event3->write(1);
- event3->write(15);
- event3->init();
- valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(15, curBaseInfo.base.long_value);
- EXPECT_EQ(true, curInterval.hasValue);
-
- shared_ptr<LogEvent> event4 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 15);
- event4->write(1);
- event4->write(15);
- event4->init();
- valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(15, curBaseInfo.base.long_value);
- EXPECT_EQ(true, curInterval.hasValue);
-
- valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
- assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {5}, {bucketSizeNs});
-}
-
-TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- metric.mutable_value_field()->add_child()->set_field(3);
- 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)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
- eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
- pullerManager);
-
- shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
- event1->write(1);
- event1->write(10);
- event1->write(20);
- event1->init();
- shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 15);
- event2->write(1);
- event2->write(15);
- event2->write(22);
- event2->init();
- valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
- // has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(10, curBaseInfo.base.long_value);
- EXPECT_EQ(false, curInterval.hasValue);
- curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(20, curBaseInfo.base.long_value);
- EXPECT_EQ(false, curInterval.hasValue);
-
- valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
-
- // has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[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];
- EXPECT_EQ(true, curInterval.hasValue);
- EXPECT_EQ(2, curInterval.value.long_value);
-
- // no change in first value field
- shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
- event3->write(1);
- event3->write(15);
- event3->write(25);
- event3->init();
- valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[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];
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(25, curBaseInfo.base.long_value);
- EXPECT_EQ(true, curInterval.hasValue);
-
- shared_ptr<LogEvent> event4 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 15);
- event4->write(1);
- event4->write(15);
- event4->write(29);
- event4->init();
- valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[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];
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(29, curBaseInfo.base.long_value);
- EXPECT_EQ(true, curInterval.hasValue);
-
- valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
-
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size());
- EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second[0].values.size());
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second[1].values.size());
-
- EXPECT_EQ(bucketSizeNs, valueProducer.mPastBuckets.begin()->second[0].mConditionTrueNs);
- EXPECT_EQ(5, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
- EXPECT_EQ(0, valueProducer.mPastBuckets.begin()->second[0].valueIndex[0]);
- EXPECT_EQ(2, valueProducer.mPastBuckets.begin()->second[0].values[1].long_value);
- EXPECT_EQ(1, valueProducer.mPastBuckets.begin()->second[0].valueIndex[1]);
-
- EXPECT_EQ(bucketSizeNs, valueProducer.mPastBuckets.begin()->second[1].mConditionTrueNs);
- EXPECT_EQ(3, valueProducer.mPastBuckets.begin()->second[1].values[0].long_value);
- EXPECT_EQ(1, valueProducer.mPastBuckets.begin()->second[1].valueIndex[0]);
-}
-
-/*
- * Tests zero default base.
- */
-TEST(ValueMetricProducerTest, TestUseZeroDefaultBase) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- metric.mutable_dimensions_in_what()->set_field(tagId);
- metric.mutable_dimensions_in_what()->add_child()->set_field(1);
- metric.set_use_zero_default_base(true);
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
- event->write(1);
- event->write(3);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- auto iter = valueProducer->mCurrentSlicedBucket.begin();
- auto& interval1 = iter->second[0];
- auto iterBase = valueProducer->mCurrentBaseInfo.begin();
- auto& baseInfo1 = iterBase->second[0];
- EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- EXPECT_EQ(true, baseInfo1.hasBase);
- EXPECT_EQ(3, baseInfo1.base.long_value);
- EXPECT_EQ(false, interval1.hasValue);
- EXPECT_EQ(true, valueProducer->mHasGlobalBase);
- EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
- vector<shared_ptr<LogEvent>> allData;
-
- allData.clear();
- shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
- event1->write(2);
- event1->write(4);
- event1->init();
- shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
- event2->write(1);
- event2->write(11);
- event2->init();
- allData.push_back(event1);
- allData.push_back(event2);
-
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
- EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
- EXPECT_EQ(true, baseInfo1.hasBase);
- EXPECT_EQ(11, baseInfo1.base.long_value);
- EXPECT_EQ(false, interval1.hasValue);
- EXPECT_EQ(8, interval1.value.long_value);
-
- auto it = valueProducer->mCurrentSlicedBucket.begin();
- for (; it != valueProducer->mCurrentSlicedBucket.end(); it++) {
- if (it != iter) {
- break;
- }
- }
- auto itBase = valueProducer->mCurrentBaseInfo.begin();
- for (; itBase != valueProducer->mCurrentBaseInfo.end(); it++) {
- if (itBase != iterBase) {
- break;
- }
- }
- EXPECT_TRUE(it != iter);
- EXPECT_TRUE(itBase != iterBase);
- auto& interval2 = it->second[0];
- auto& baseInfo2 = itBase->second[0];
- EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- EXPECT_EQ(true, baseInfo2.hasBase);
- EXPECT_EQ(4, baseInfo2.base.long_value);
- EXPECT_EQ(false, interval2.hasValue);
- EXPECT_EQ(4, interval2.value.long_value);
-
- EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
- auto iterator = valueProducer->mPastBuckets.begin();
- EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs);
- EXPECT_EQ(8, iterator->second[0].values[0].long_value);
- iterator++;
- EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs);
- EXPECT_EQ(4, iterator->second[0].values[0].long_value);
-}
-
-/*
- * Tests using zero default base with failed pull.
- */
-TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- metric.mutable_dimensions_in_what()->set_field(tagId);
- metric.mutable_dimensions_in_what()->add_child()->set_field(1);
- metric.set_use_zero_default_base(true);
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
- event->write(1);
- event->write(3);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- auto it = valueProducer->mCurrentSlicedBucket.begin();
- auto& interval1 = it->second[0];
- auto& baseInfo1 =
- valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat())->second[0];
- EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- EXPECT_EQ(true, baseInfo1.hasBase);
- EXPECT_EQ(3, baseInfo1.base.long_value);
- EXPECT_EQ(false, interval1.hasValue);
- EXPECT_EQ(true, valueProducer->mHasGlobalBase);
- EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
- vector<shared_ptr<LogEvent>> allData;
-
- allData.clear();
- shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
- event1->write(2);
- event1->write(4);
- event1->init();
- shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
- event2->write(1);
- event2->write(11);
- event2->init();
- allData.push_back(event1);
- allData.push_back(event2);
-
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
- EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
- EXPECT_EQ(true, baseInfo1.hasBase);
- EXPECT_EQ(11, baseInfo1.base.long_value);
- EXPECT_EQ(false, interval1.hasValue);
- EXPECT_EQ(8, interval1.value.long_value);
-
- auto it2 = valueProducer->mCurrentSlicedBucket.begin();
- for (; it2 != valueProducer->mCurrentSlicedBucket.end(); it2++) {
- if (it2 != it) {
- break;
- }
- }
- // auto itBase = valueProducer->mCurrentBaseInfo.begin();
- // for (; itBase != valueProducer->mCurrentBaseInfo.end(); it++) {
- // if (itBase != iterBase) {
- // break;
- // }
- // }
- EXPECT_TRUE(it2 != it);
- // EXPECT_TRUE(itBase != iterBase);
- auto& interval2 = it2->second[0];
- auto& baseInfo2 =
- valueProducer->mCurrentBaseInfo.find(it2->first.getDimensionKeyInWhat())->second[0];
- EXPECT_EQ(2, it2->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- EXPECT_EQ(true, baseInfo2.hasBase);
- EXPECT_EQ(4, baseInfo2.base.long_value);
- EXPECT_EQ(false, interval2.hasValue);
- EXPECT_EQ(4, interval2.value.long_value);
- EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
-
- // next pull somehow did not happen, skip to end of bucket 3
- allData.clear();
- event1 = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
- event1->write(2);
- event1->write(5);
- event1->init();
- allData.push_back(event1);
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
-
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- EXPECT_EQ(true, baseInfo2.hasBase);
- EXPECT_EQ(5, baseInfo2.base.long_value);
- EXPECT_EQ(false, interval2.hasValue);
- EXPECT_EQ(true, valueProducer->mHasGlobalBase);
- EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
-
- allData.clear();
- event1 = make_shared<LogEvent>(tagId, bucket5StartTimeNs + 1);
- event1->write(2);
- event1->write(13);
- event1->init();
- allData.push_back(event1);
- event2 = make_shared<LogEvent>(tagId, bucket5StartTimeNs + 1);
- event2->write(1);
- event2->write(5);
- event2->init();
- allData.push_back(event2);
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
-
- EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
- it = valueProducer->mCurrentSlicedBucket.begin();
- it2 = std::next(valueProducer->mCurrentSlicedBucket.begin());
- interval1 = it->second[0];
- interval2 = it2->second[0];
- baseInfo1 = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat())->second[0];
- baseInfo2 = valueProducer->mCurrentBaseInfo.find(it2->first.getDimensionKeyInWhat())->second[0];
-
- EXPECT_EQ(true, baseInfo1.hasBase);
- EXPECT_EQ(5, baseInfo1.base.long_value);
- EXPECT_EQ(false, interval1.hasValue);
- EXPECT_EQ(5, interval1.value.long_value);
- EXPECT_EQ(true, valueProducer->mHasGlobalBase);
-
- EXPECT_EQ(true, baseInfo2.hasBase);
- EXPECT_EQ(13, baseInfo2.base.long_value);
- EXPECT_EQ(false, interval2.hasValue);
- EXPECT_EQ(8, interval2.value.long_value);
-
- EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
-}
-
-/*
- * Tests trim unused dimension key if no new data is seen in an entire bucket.
- */
-TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- metric.mutable_dimensions_in_what()->set_field(tagId);
- metric.mutable_dimensions_in_what()->add_child()->set_field(1);
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
- event->write(1);
- event->write(3);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- auto iter = valueProducer->mCurrentSlicedBucket.begin();
- auto& interval1 = iter->second[0];
- auto iterBase = valueProducer->mCurrentBaseInfo.begin();
- auto& baseInfo1 = iterBase->second[0];
- EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- EXPECT_EQ(true, baseInfo1.hasBase);
- EXPECT_EQ(3, baseInfo1.base.long_value);
- EXPECT_EQ(false, interval1.hasValue);
- EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
- vector<shared_ptr<LogEvent>> allData;
-
- allData.clear();
- shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
- event1->write(2);
- event1->write(4);
- event1->init();
- shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
- event2->write(1);
- event2->write(11);
- event2->init();
- allData.push_back(event1);
- allData.push_back(event2);
-
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
- EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
- EXPECT_EQ(true, baseInfo1.hasBase);
- EXPECT_EQ(11, baseInfo1.base.long_value);
- EXPECT_EQ(false, interval1.hasValue);
- EXPECT_EQ(8, interval1.value.long_value);
- EXPECT_FALSE(interval1.seenNewData);
- assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {8}, {bucketSizeNs});
-
- auto it = valueProducer->mCurrentSlicedBucket.begin();
- for (; it != valueProducer->mCurrentSlicedBucket.end(); it++) {
- if (it != iter) {
- break;
- }
- }
- auto itBase = valueProducer->mCurrentBaseInfo.begin();
- for (; itBase != valueProducer->mCurrentBaseInfo.end(); it++) {
- if (itBase != iterBase) {
- break;
- }
- }
- EXPECT_TRUE(it != iter);
- EXPECT_TRUE(itBase != iterBase);
- auto& interval2 = it->second[0];
- auto& baseInfo2 = itBase->second[0];
- EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- EXPECT_EQ(true, baseInfo2.hasBase);
- EXPECT_EQ(4, baseInfo2.base.long_value);
- EXPECT_EQ(false, interval2.hasValue);
- EXPECT_FALSE(interval2.seenNewData);
- assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {8}, {bucketSizeNs});
-
- // next pull somehow did not happen, skip to end of bucket 3
- allData.clear();
- event1 = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
- event1->write(2);
- event1->write(5);
- event1->init();
- allData.push_back(event1);
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
- // Only one interval left. One was trimmed.
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- interval2 = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- baseInfo2 = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- EXPECT_EQ(true, baseInfo2.hasBase);
- EXPECT_EQ(5, baseInfo2.base.long_value);
- EXPECT_EQ(false, interval2.hasValue);
- EXPECT_FALSE(interval2.seenNewData);
- assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {8}, {bucketSizeNs});
-
- allData.clear();
- event1 = make_shared<LogEvent>(tagId, bucket5StartTimeNs + 1);
- event1->write(2);
- event1->write(14);
- event1->init();
- allData.push_back(event1);
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
-
- interval2 = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- baseInfo2 = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(true, baseInfo2.hasBase);
- EXPECT_EQ(14, baseInfo2.base.long_value);
- EXPECT_EQ(false, interval2.hasValue);
- EXPECT_FALSE(interval2.seenNewData);
- ASSERT_EQ(2UL, valueProducer->mPastBuckets.size());
- auto iterator = valueProducer->mPastBuckets.begin();
- EXPECT_EQ(9, iterator->second[0].values[0].long_value);
- EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs);
- iterator++;
- EXPECT_EQ(8, iterator->second[0].values[0].long_value);
- EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs);
-}
-
-TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange_EndOfBucket) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- // Used by onConditionChanged.
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
- event->write(tagId);
- event->write(100);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
- // has one slice
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval& curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo& curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(100, curBaseInfo.base.long_value);
- EXPECT_EQ(false, curInterval.hasValue);
-
- vector<shared_ptr<LogEvent>> allData;
- valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- EXPECT_EQ(false, curBaseInfo.hasBase);
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(false, valueProducer->mHasGlobalBase);
-}
-
-TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
- event->write(tagId);
- event->write(100);
- event->init();
- data->push_back(event);
- return true;
- }))
- .WillOnce(Return(false));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
-
- // has one slice
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval& curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo& curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(100, curBaseInfo.base.long_value);
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
-
- valueProducer->onConditionChanged(false, bucketStartTimeNs + 20);
-
- // has one slice
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(false, curBaseInfo.hasBase);
- EXPECT_EQ(false, valueProducer->mHasGlobalBase);
-}
-
-TEST(ValueMetricProducerTest, TestResetBaseOnPullFailBeforeConditionChange) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
- event->write(tagId);
- event->write(50);
- event->init();
- data->push_back(event);
- return false;
- }))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
- event->write(tagId);
- event->write(100);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
- // Don't directly set mCondition; the real code never does that. Go through regular code path
- // to avoid unexpected behaviors.
- // valueProducer->mCondition = ConditionState::kTrue;
- valueProducer->onConditionChanged(true, bucketStartTimeNs);
-
- EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
-
- valueProducer->onConditionChanged(false, bucketStartTimeNs + 1);
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval& curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(false, curBaseInfo.hasBase);
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(false, valueProducer->mHasGlobalBase);
-}
-
-TEST(ValueMetricProducerTest, TestResetBaseOnPullDelayExceeded) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- metric.set_condition(StringToId("SCREEN_ON"));
- metric.set_max_pull_delay_sec(0);
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
- event->write(tagId);
- event->write(120);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
- valueProducer->mCondition = ConditionState::kFalse;
-
- // Max delay is set to 0 so pull will exceed max delay.
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
- EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
-}
-
-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)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucket2StartTimeNs,
- bucket2StartTimeNs, pullerManager);
- valueProducer.mCondition = ConditionState::kFalse;
-
- // Event should be skipped since it is from previous bucket.
- // Pull should not be called.
- valueProducer.onConditionChanged(true, bucketStartTimeNs);
- EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
-}
-
-TEST(ValueMetricProducerTest, TestBaseSetOnConditionChange) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
- event->write(tagId);
- event->write(100);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
- valueProducer->mCondition = ConditionState::kFalse;
- valueProducer->mHasGlobalBase = false;
-
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
- valueProducer->mHasGlobalBase = true;
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval& curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(100, curBaseInfo.base.long_value);
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(true, valueProducer->mHasGlobalBase);
-}
-
-/*
- * Tests that a bucket is marked invalid when a condition change pull fails.
- */
-TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenOneConditionFailed) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // First onConditionChanged
- .WillOnce(Return(false))
- // Second onConditionChanged
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
- event->write(tagId);
- event->write(130);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
- valueProducer->mCondition = ConditionState::kTrue;
-
- // Bucket start.
- vector<shared_ptr<LogEvent>> allData;
- allData.clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
- event->write(1);
- event->write(110);
- event->init();
- allData.push_back(event);
- valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
-
- // This will fail and should invalidate the whole bucket since we do not have all the data
- // needed to compute the metric value when the screen was on.
- valueProducer->onConditionChanged(false, bucketStartTimeNs + 2);
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 3);
-
- // Bucket end.
- allData.clear();
- shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
- event2->write(1);
- event2->write(140);
- event2->init();
- allData.push_back(event2);
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-
- valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
-
- EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
- // Contains base from last pull which was successful.
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval& curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(140, curBaseInfo.base.long_value);
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(true, valueProducer->mHasGlobalBase);
-
- // Check dump report.
- ProtoOutputStream output;
- std::set<string> strSet;
- valueProducer->onDumpReport(bucket2StartTimeNs + 10, false /* include partial bucket */, true,
- FAST /* dumpLatency */, &strSet, &output);
-
- StatsLogReport report = outputStreamToProto(&output);
- EXPECT_TRUE(report.has_value_metrics());
- EXPECT_EQ(0, report.value_metrics().data_size());
- EXPECT_EQ(1, report.value_metrics().skipped_size());
-
- EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
- report.value_metrics().skipped(0).start_bucket_elapsed_millis());
- EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
- report.value_metrics().skipped(0).end_bucket_elapsed_millis());
- EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
-
- auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
- EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
- EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 2), dropEvent.drop_time_millis());
-}
-
-/*
- * Tests that a bucket is marked invalid when the guardrail is hit.
- */
-TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenGuardRailHit) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- metric.mutable_dimensions_in_what()->set_field(tagId);
- metric.mutable_dimensions_in_what()->add_child()->set_field(1);
- metric.set_condition(StringToId("SCREEN_ON"));
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // First onConditionChanged
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- for (int i = 0; i < 2000; i++) {
- shared_ptr<LogEvent> event =
- make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
- event->write(i);
- event->write(i);
- event->init();
- data->push_back(event);
- }
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- valueProducer->mCondition = ConditionState::kFalse;
-
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 2);
- EXPECT_EQ(true, valueProducer->mCurrentBucketIsInvalid);
- EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
- EXPECT_EQ(0UL, valueProducer->mSkippedBuckets.size());
-
- // Bucket 2 start.
- vector<shared_ptr<LogEvent>> allData;
- allData.clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
- event->write(1);
- event->write(10);
- event->init();
- allData.push_back(event);
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-
- // First bucket added to mSkippedBuckets after flush.
- EXPECT_EQ(1UL, valueProducer->mSkippedBuckets.size());
-
- // Check dump report.
- ProtoOutputStream output;
- std::set<string> strSet;
- valueProducer->onDumpReport(bucket2StartTimeNs + 10000, false /* include recent buckets */,
- true, FAST /* dumpLatency */, &strSet, &output);
-
- StatsLogReport report = outputStreamToProto(&output);
- EXPECT_TRUE(report.has_value_metrics());
- EXPECT_EQ(0, report.value_metrics().data_size());
- EXPECT_EQ(1, report.value_metrics().skipped_size());
-
- EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
- report.value_metrics().skipped(0).start_bucket_elapsed_millis());
- EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
- report.value_metrics().skipped(0).end_bucket_elapsed_millis());
- EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
-
- auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
- EXPECT_EQ(BucketDropReason::DIMENSION_GUARDRAIL_REACHED, dropEvent.drop_reason());
- EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 2), dropEvent.drop_time_millis());
-}
-
-/*
- * Tests that a bucket is marked invalid when the bucket's initial pull fails.
- */
-TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenInitialPullFailed) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // First onConditionChanged
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
- event->write(tagId);
- event->write(120);
- event->init();
- data->push_back(event);
- return true;
- }))
- // Second onConditionChanged
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
- event->write(tagId);
- event->write(130);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
- valueProducer->mCondition = ConditionState::kTrue;
-
- // Bucket start.
- vector<shared_ptr<LogEvent>> allData;
- allData.clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
- event->write(1);
- event->write(110);
- event->init();
- allData.push_back(event);
- valueProducer->onDataPulled(allData, /** succeed */ false, bucketStartTimeNs);
-
- valueProducer->onConditionChanged(false, bucketStartTimeNs + 2);
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 3);
-
- // Bucket end.
- allData.clear();
- shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
- event2->write(1);
- event2->write(140);
- event2->init();
- allData.push_back(event2);
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-
- valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
-
- EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
- // Contains base from last pull which was successful.
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval& curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(140, curBaseInfo.base.long_value);
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(true, valueProducer->mHasGlobalBase);
-
- // Check dump report.
- ProtoOutputStream output;
- std::set<string> strSet;
- valueProducer->onDumpReport(bucket2StartTimeNs + 10000, false /* include recent buckets */,
- true, FAST /* dumpLatency */, &strSet, &output);
-
- StatsLogReport report = outputStreamToProto(&output);
- EXPECT_TRUE(report.has_value_metrics());
- EXPECT_EQ(0, report.value_metrics().data_size());
- EXPECT_EQ(1, report.value_metrics().skipped_size());
-
- EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
- report.value_metrics().skipped(0).start_bucket_elapsed_millis());
- EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
- report.value_metrics().skipped(0).end_bucket_elapsed_millis());
- EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
-
- auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
- EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
- EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 2), dropEvent.drop_time_millis());
-}
-
-/*
- * Tests that a bucket is marked invalid when the bucket's final pull fails
- * (i.e. failed pull on bucket boundary).
- */
-TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenLastPullFailed) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // First onConditionChanged
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
- event->write(tagId);
- event->write(120);
- event->init();
- data->push_back(event);
- return true;
- }))
- // Second onConditionChanged
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
- event->write(tagId);
- event->write(130);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
- valueProducer->mCondition = ConditionState::kTrue;
-
- // Bucket start.
- vector<shared_ptr<LogEvent>> allData;
- allData.clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
- event->write(1);
- event->write(110);
- event->init();
- allData.push_back(event);
- valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
-
- valueProducer->onConditionChanged(false, bucketStartTimeNs + 2);
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 3);
-
- // Bucket end.
- allData.clear();
- shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
- event2->write(1);
- event2->write(140);
- event2->init();
- allData.push_back(event2);
- valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
-
- valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
-
- EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
- // Last pull failed so base has been reset.
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval& curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(false, curBaseInfo.hasBase);
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(false, valueProducer->mHasGlobalBase);
-
- // Check dump report.
- ProtoOutputStream output;
- std::set<string> strSet;
- valueProducer->onDumpReport(bucket2StartTimeNs + 10000, false /* include recent buckets */,
- true, FAST /* dumpLatency */, &strSet, &output);
-
- StatsLogReport report = outputStreamToProto(&output);
- EXPECT_TRUE(report.has_value_metrics());
- EXPECT_EQ(0, report.value_metrics().data_size());
- EXPECT_EQ(1, report.value_metrics().skipped_size());
-
- EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
- report.value_metrics().skipped(0).start_bucket_elapsed_millis());
- EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
- report.value_metrics().skipped(0).end_bucket_elapsed_millis());
- EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
-
- auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
- EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
- EXPECT_EQ(NanoToMillis(bucket2StartTimeNs), dropEvent.drop_time_millis());
-}
-
-TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onDataPulled) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // Start bucket.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
- event->write(tagId);
- event->write(3);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-
- // Bucket 2 start.
- vector<shared_ptr<LogEvent>> allData;
- allData.clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
- event->write(tagId);
- event->write(110);
- event->init();
- allData.push_back(event);
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
-
- // Bucket 3 empty.
- allData.clear();
- shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
- event2->init();
- allData.push_back(event2);
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
- // Data has been trimmed.
- EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
- EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
-}
-
-TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onConditionChanged) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // First onConditionChanged
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
- event->write(tagId);
- event->write(3);
- event->init();
- data->push_back(event);
- return true;
- }))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval& curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(true, valueProducer->mHasGlobalBase);
-
- // Empty pull.
- valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(false, curBaseInfo.hasBase);
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(false, valueProducer->mHasGlobalBase);
-}
-
-TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onBucketBoundary) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // First onConditionChanged
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
- event->write(tagId);
- event->write(1);
- event->init();
- data->push_back(event);
- return true;
- }))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
- event->write(tagId);
- event->write(2);
- event->init();
- data->push_back(event);
- return true;
- }))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
- event->write(tagId);
- event->write(5);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
- valueProducer->onConditionChanged(false, bucketStartTimeNs + 11);
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 12);
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval& curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(true, curInterval.hasValue);
- EXPECT_EQ(true, valueProducer->mHasGlobalBase);
-
- // End of bucket
- vector<shared_ptr<LogEvent>> allData;
- allData.clear();
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- // Data is empty, base should be reset.
- EXPECT_EQ(false, curBaseInfo.hasBase);
- EXPECT_EQ(5, curBaseInfo.base.long_value);
- EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(true, valueProducer->mHasGlobalBase);
-
- EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
- assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {1}, {bucketSizeNs - 12 + 1});
-}
-
-TEST(ValueMetricProducerTest, TestPartialResetOnBucketBoundaries) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- metric.mutable_dimensions_in_what()->set_field(tagId);
- metric.mutable_dimensions_in_what()->add_child()->set_field(1);
- metric.set_condition(StringToId("SCREEN_ON"));
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // First onConditionChanged
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
- event->write(tagId);
- event->write(1);
- event->write(1);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-
- // End of bucket
- vector<shared_ptr<LogEvent>> allData;
- allData.clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
- event->write(2);
- event->write(2);
- event->init();
- allData.push_back(event);
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-
- // Key 1 should be reset since in not present in the most pull.
- EXPECT_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);
- 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(true, valueProducer->mHasGlobalBase);
-}
-
-TEST(ValueMetricProducerTest, TestFullBucketResetWhenLastBucketInvalid) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // Initialization.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
- return true;
- }))
- // notifyAppUpgrade.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(ValueMetricProducerTestHelper::createEvent(
- bucketStartTimeNs + bucketSizeNs / 2, 10));
- return true;
- }));
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
- ASSERT_EQ(0UL, valueProducer->mCurrentFullBucket.size());
-
- valueProducer->notifyAppUpgrade(bucketStartTimeNs + bucketSizeNs / 2, "com.foo", 10000, 1);
- ASSERT_EQ(1UL, valueProducer->mCurrentFullBucket.size());
-
- vector<shared_ptr<LogEvent>> allData;
- allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket3StartTimeNs + 1, 4));
- valueProducer->onDataPulled(allData, /** fails */ false, bucket3StartTimeNs + 1);
- ASSERT_EQ(0UL, valueProducer->mCurrentFullBucket.size());
-}
-
-TEST(ValueMetricProducerTest, TestBucketBoundariesOnConditionChange) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // Second onConditionChanged.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(
- ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 10, 5));
- return true;
- }))
- // Third onConditionChanged.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(
- ValueMetricProducerTestHelper::createEvent(bucket3StartTimeNs + 10, 7));
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- valueProducer->mCondition = ConditionState::kUnknown;
-
- valueProducer->onConditionChanged(false, bucketStartTimeNs);
- ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
-
- // End of first bucket
- vector<shared_ptr<LogEvent>> allData;
- allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 1, 4));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 1);
- ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
-
- 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];
- EXPECT_EQ(true, curBaseInfo.hasBase);
- EXPECT_EQ(5, curBaseInfo.base.long_value);
- EXPECT_EQ(false, curInterval.hasValue);
-
- valueProducer->onConditionChanged(false, bucket3StartTimeNs + 10);
-
- // Bucket should have been completed.
- assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {2}, {bucketSizeNs - 10});
-}
-
-TEST(ValueMetricProducerTest, TestLateOnDataPulledWithoutDiff) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- metric.set_use_diff(false);
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-
- vector<shared_ptr<LogEvent>> allData;
- allData.push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + 30);
-
- allData.clear();
- allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 20));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-
- // Bucket should have been completed.
- assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {30}, {bucketSizeNs});
-}
-
-TEST(ValueMetricProducerTest, TestLateOnDataPulledWithDiff) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // Initialization.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-
- vector<shared_ptr<LogEvent>> allData;
- allData.push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + 30);
-
- allData.clear();
- allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 20));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-
- // Bucket should have been completed.
- assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {19}, {bucketSizeNs});
-}
-
-TEST(ValueMetricProducerTest, TestBucketBoundariesOnAppUpgrade) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // Initialization.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
- return true;
- }))
- // notifyAppUpgrade.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(
- ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 2, 10));
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-
- valueProducer->notifyAppUpgrade(bucket2StartTimeNs + 2, "com.foo", 10000, 1);
-
- // Bucket should have been completed.
- assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {9}, {bucketSizeNs});
-}
-
-TEST(ValueMetricProducerTest, TestDataIsNotUpdatedWhenNoConditionChanged) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // First on condition changed.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
- return true;
- }))
- // Second on condition changed.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 3));
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
- valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
- valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
-
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- auto curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasValue);
- EXPECT_EQ(2, curInterval.value.long_value);
-
- vector<shared_ptr<LogEvent>> allData;
- allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 1, 10));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 1);
-
- assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {2}, {2});
-}
-
-// TODO: b/145705635 fix or delete this test
-TEST(ValueMetricProducerTest, TestBucketInvalidIfGlobalBaseIsNotSet) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // First condition change.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
- return true;
- }))
- // 2nd condition change.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 1));
- return true;
- }))
- // 3rd condition change.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 1));
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
-
- vector<shared_ptr<LogEvent>> allData;
- allData.push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 3, 10));
- valueProducer->onDataPulled(allData, /** succeed */ false, bucketStartTimeNs + 3);
-
- allData.clear();
- allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 20));
- valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
-
- valueProducer->onConditionChanged(false, bucket2StartTimeNs + 8);
- valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
-
- allData.clear();
- allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket3StartTimeNs, 30));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-
- // There was not global base available so all buckets are invalid.
- assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {});
-}
-
-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)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // Initial pull.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
- event->write(tagId);
- event->write(1);
- event->write(1);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
-
- ProtoOutputStream output;
- std::set<string> strSet;
- valueProducer.onDumpReport(bucketStartTimeNs + 10, true /* include recent buckets */, true,
- FAST, &strSet, &output);
-
- StatsLogReport report = outputStreamToProto(&output);
- // Bucket is invalid since we did not pull when dump report was called.
- EXPECT_EQ(0, report.value_metrics().data_size());
-}
-
-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)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // Initial pull.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
- event->write(tagId);
- event->write(1);
- event->write(1);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
-
- vector<shared_ptr<LogEvent>> allData;
- allData.clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
- event->write(tagId);
- event->write(2);
- event->write(2);
- event->init();
- allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-
- ProtoOutputStream output;
- std::set<string> strSet;
- valueProducer.onDumpReport(bucket4StartTimeNs, false /* include recent buckets */, true, FAST,
- &strSet, &output);
-
- StatsLogReport report = outputStreamToProto(&output);
- // Previous bucket is part of the report.
- EXPECT_EQ(1, report.value_metrics().data_size());
- EXPECT_EQ(0, report.value_metrics().data(0).bucket_info(0).bucket_num());
-}
-
-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)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // Initial pull.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
- event->write(tagId);
- event->write(1);
- event->write(1);
- event->init();
- data->push_back(event);
- return true;
- }))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
- event->write(tagId);
- event->write(3);
- event->write(3);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
-
- ProtoOutputStream output;
- std::set<string> strSet;
- valueProducer.onDumpReport(bucketStartTimeNs + 10, true /* include recent buckets */, true,
- NO_TIME_CONSTRAINTS, &strSet, &output);
-
- StatsLogReport report = outputStreamToProto(&output);
- EXPECT_EQ(1, report.value_metrics().data_size());
- EXPECT_EQ(1, report.value_metrics().data(0).bucket_info_size());
- EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
-}
-
-TEST(ValueMetricProducerTest, TestPulledData_noDiff_withoutCondition) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- metric.set_use_diff(false);
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-
- vector<shared_ptr<LogEvent>> allData;
- allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 10));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 30);
-
- // Bucket should have been completed.
- assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs});
-}
-
-TEST(ValueMetricProducerTest, TestPulledData_noDiff_withMultipleConditionChanges) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
- metric.set_use_diff(false);
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // condition becomes true
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(
- ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
- return true;
- }))
- // condition becomes false
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(
- ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 50, 20));
- return true;
- }));
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- valueProducer->mCondition = ConditionState::kFalse;
-
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
- valueProducer->onConditionChanged(false, bucketStartTimeNs + 50);
- // has one slice
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(false, curBaseInfo.hasBase);
- EXPECT_EQ(true, curInterval.hasValue);
- EXPECT_EQ(20, curInterval.value.long_value);
-
- // Now the alarm is delivered. Condition is off though.
- vector<shared_ptr<LogEvent>> allData;
- allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 110));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-
- assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {50 - 8});
- curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(false, curBaseInfo.hasBase);
- EXPECT_EQ(false, curInterval.hasValue);
-}
-
-TEST(ValueMetricProducerTest, TestPulledData_noDiff_bucketBoundaryTrue) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
- metric.set_use_diff(false);
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // condition becomes true
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(
- ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
- return true;
- }));
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- valueProducer->mCondition = ConditionState::kFalse;
-
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
-
- // Now the alarm is delivered. Condition is off though.
- vector<shared_ptr<LogEvent>> allData;
- allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 30));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-
- assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {30}, {bucketSizeNs - 8});
- ValueMetricProducer::Interval curInterval =
- valueProducer->mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(false, curBaseInfo.hasBase);
- EXPECT_EQ(false, curInterval.hasValue);
-}
-
-TEST(ValueMetricProducerTest, TestPulledData_noDiff_bucketBoundaryFalse) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
- metric.set_use_diff(false);
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- valueProducer->mCondition = ConditionState::kFalse;
-
- // Now the alarm is delivered. Condition is off though.
- vector<shared_ptr<LogEvent>> allData;
- allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 30));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-
- // Condition was always false.
- assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {});
-}
-
-TEST(ValueMetricProducerTest, TestPulledData_noDiff_withFailure) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
- metric.set_use_diff(false);
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // condition becomes true
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(
- ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
- return true;
- }))
- .WillOnce(Return(false));
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- valueProducer->mCondition = ConditionState::kFalse;
-
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
- valueProducer->onConditionChanged(false, bucketStartTimeNs + 50);
-
- // Now the alarm is delivered. Condition is off though.
- vector<shared_ptr<LogEvent>> allData;
- allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 30));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-
- // No buckets, we had a failure.
- assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {});
-}
-
-/*
- * Test that DUMP_REPORT_REQUESTED dump reason is logged.
- *
- * For the bucket to be marked invalid during a dump report requested,
- * three things must be true:
- * - we want to include the current partial bucket
- * - we need a pull (metric is pulled and condition is true)
- * - the dump latency must be FAST
- */
-TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenDumpReportRequested) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // Condition change to true.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
- event->write("field1");
- event->write(10);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
- // Condition change event.
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 20);
-
- // Check dump report.
- ProtoOutputStream output;
- std::set<string> strSet;
- valueProducer->onDumpReport(bucketStartTimeNs + 40, true /* include recent buckets */, true,
- FAST /* dumpLatency */, &strSet, &output);
-
- StatsLogReport report = outputStreamToProto(&output);
- EXPECT_TRUE(report.has_value_metrics());
- EXPECT_EQ(0, report.value_metrics().data_size());
- EXPECT_EQ(1, report.value_metrics().skipped_size());
-
- EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
- report.value_metrics().skipped(0).start_bucket_elapsed_millis());
- EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 40),
- report.value_metrics().skipped(0).end_bucket_elapsed_millis());
- EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
-
- auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
- EXPECT_EQ(BucketDropReason::DUMP_REPORT_REQUESTED, dropEvent.drop_reason());
- EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 40), dropEvent.drop_time_millis());
-}
-
-/*
- * Test that EVENT_IN_WRONG_BUCKET dump reason is logged for a late condition
- * change event (i.e. the condition change occurs in the wrong bucket).
- */
-TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenConditionEventWrongBucket) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // Condition change to true.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
- event->write("field1");
- event->write(10);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
- // Condition change event.
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
-
- // Bucket boundary pull.
- vector<shared_ptr<LogEvent>> allData;
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs);
- event->write("field1");
- event->write(15);
- event->init();
- allData.push_back(event);
- valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
-
- // Late condition change event.
- valueProducer->onConditionChanged(false, bucket2StartTimeNs - 100);
-
- // Check dump report.
- ProtoOutputStream output;
- std::set<string> strSet;
- valueProducer->onDumpReport(bucket2StartTimeNs + 100, true /* include recent buckets */, true,
- NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
-
- StatsLogReport report = outputStreamToProto(&output);
- EXPECT_TRUE(report.has_value_metrics());
- EXPECT_EQ(1, report.value_metrics().data_size());
- EXPECT_EQ(1, report.value_metrics().skipped_size());
-
- EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
- report.value_metrics().skipped(0).start_bucket_elapsed_millis());
- EXPECT_EQ(NanoToMillis(bucket2StartTimeNs + 100),
- report.value_metrics().skipped(0).end_bucket_elapsed_millis());
- EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
-
- auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
- EXPECT_EQ(BucketDropReason::EVENT_IN_WRONG_BUCKET, dropEvent.drop_reason());
- EXPECT_EQ(NanoToMillis(bucket2StartTimeNs - 100), dropEvent.drop_time_millis());
-}
-
-/*
- * Test that EVENT_IN_WRONG_BUCKET dump reason is logged for a late accumulate
- * event (i.e. the accumulate events call occurs in the wrong bucket).
- */
-TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenAccumulateEventWrongBucket) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // Condition change to true.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
- event->write("field1");
- event->write(10);
- event->init();
- data->push_back(event);
- return true;
- }))
- // Dump report requested.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 100);
- event->write("field1");
- event->write(15);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
- // Condition change event.
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
-
- // Bucket boundary pull.
- vector<shared_ptr<LogEvent>> allData;
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs);
- event->write("field1");
- event->write(15);
- event->init();
- allData.push_back(event);
- valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
-
- allData.clear();
- event = make_shared<LogEvent>(tagId, bucket2StartTimeNs - 100);
- event->write("field1");
- event->write(20);
- event->init();
- allData.push_back(event);
-
- // Late accumulateEvents event.
- valueProducer->accumulateEvents(allData, bucket2StartTimeNs - 100, bucket2StartTimeNs - 100);
-
- // Check dump report.
- ProtoOutputStream output;
- std::set<string> strSet;
- valueProducer->onDumpReport(bucket2StartTimeNs + 100, true /* include recent buckets */, true,
- NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
-
- StatsLogReport report = outputStreamToProto(&output);
- EXPECT_TRUE(report.has_value_metrics());
- EXPECT_EQ(1, report.value_metrics().data_size());
- EXPECT_EQ(1, report.value_metrics().skipped_size());
-
- EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
- report.value_metrics().skipped(0).start_bucket_elapsed_millis());
- EXPECT_EQ(NanoToMillis(bucket2StartTimeNs + 100),
- report.value_metrics().skipped(0).end_bucket_elapsed_millis());
- EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
-
- auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
- EXPECT_EQ(BucketDropReason::EVENT_IN_WRONG_BUCKET, dropEvent.drop_reason());
- EXPECT_EQ(NanoToMillis(bucket2StartTimeNs - 100), dropEvent.drop_time_millis());
-}
-
-/*
- * Test that CONDITION_UNKNOWN dump reason is logged due to an unknown condition
- * when a metric is initialized.
- */
-TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenConditionUnknown) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // Condition change to true.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
- event->write("field1");
- event->write(10);
- event->init();
- data->push_back(event);
- return true;
- }))
- // Dump report requested.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 100);
- event->write("field1");
- event->write(15);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithNoInitialCondition(pullerManager,
- metric);
-
- // Condition change event.
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
-
- // Check dump report.
- ProtoOutputStream output;
- std::set<string> strSet;
- int64_t dumpReportTimeNs = bucketStartTimeNs + 10000;
- valueProducer->onDumpReport(dumpReportTimeNs, true /* include recent buckets */, true,
- NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
-
- StatsLogReport report = outputStreamToProto(&output);
- EXPECT_TRUE(report.has_value_metrics());
- EXPECT_EQ(0, report.value_metrics().data_size());
- EXPECT_EQ(1, report.value_metrics().skipped_size());
-
- EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
- report.value_metrics().skipped(0).start_bucket_elapsed_millis());
- EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
- report.value_metrics().skipped(0).end_bucket_elapsed_millis());
- EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
-
- auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
- EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
- EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
-}
-
-/*
- * Test that PULL_FAILED dump reason is logged due to a pull failure in
- * #pullAndMatchEventsLocked.
- */
-TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenPullFailed) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // Condition change to true.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
- event->write("field1");
- event->write(10);
- event->init();
- data->push_back(event);
- return true;
- }))
- // Dump report requested, pull fails.
- .WillOnce(Return(false));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
- // Condition change event.
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
-
- // Check dump report.
- ProtoOutputStream output;
- std::set<string> strSet;
- int64_t dumpReportTimeNs = bucketStartTimeNs + 10000;
- valueProducer->onDumpReport(dumpReportTimeNs, true /* include recent buckets */, true,
- NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
-
- StatsLogReport report = outputStreamToProto(&output);
- EXPECT_TRUE(report.has_value_metrics());
- EXPECT_EQ(0, report.value_metrics().data_size());
- EXPECT_EQ(1, report.value_metrics().skipped_size());
-
- EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
- report.value_metrics().skipped(0).start_bucket_elapsed_millis());
- EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
- report.value_metrics().skipped(0).end_bucket_elapsed_millis());
- EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
-
- auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
- EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
- EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
-}
-
-/*
- * Test that MULTIPLE_BUCKETS_SKIPPED dump reason is logged when a log event
- * skips over more than one bucket.
- */
-TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenMultipleBucketsSkipped) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // Condition change to true.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
- event->write("field1");
- event->write(10);
- event->init();
- data->push_back(event);
- return true;
- }))
- // Dump report requested.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event =
- make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1000);
- event->write("field1");
- event->write(15);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
- // Condition change event.
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
-
- // Condition change event that skips forward by three buckets.
- valueProducer->onConditionChanged(false, bucket4StartTimeNs + 10);
-
- // Check dump report.
- ProtoOutputStream output;
- std::set<string> strSet;
- valueProducer->onDumpReport(bucket4StartTimeNs + 1000, true /* include recent buckets */, true,
- NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
-
- StatsLogReport report = outputStreamToProto(&output);
- EXPECT_TRUE(report.has_value_metrics());
- EXPECT_EQ(0, report.value_metrics().data_size());
- EXPECT_EQ(1, report.value_metrics().skipped_size());
-
- EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
- report.value_metrics().skipped(0).start_bucket_elapsed_millis());
- EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
- report.value_metrics().skipped(0).end_bucket_elapsed_millis());
- EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
-
- auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
- EXPECT_EQ(BucketDropReason::MULTIPLE_BUCKETS_SKIPPED, dropEvent.drop_reason());
- EXPECT_EQ(NanoToMillis(bucket4StartTimeNs + 10), dropEvent.drop_time_millis());
-}
-
-/*
- * Test that BUCKET_TOO_SMALL dump reason is logged when a flushed bucket size
- * is smaller than the "min_bucket_size_nanos" specified in the metric config.
- */
-TEST(ValueMetricProducerTest_BucketDrop, TestBucketDropWhenBucketTooSmall) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
- metric.set_min_bucket_size_nanos(10000000000); // 10 seconds
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // Condition change to true.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
- event->write("field1");
- event->write(10);
- event->init();
- data->push_back(event);
- return true;
- }))
- // Dump report requested.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event =
- make_shared<LogEvent>(tagId, bucketStartTimeNs + 9000000);
- event->write("field1");
- event->write(15);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
- // Condition change event.
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
-
- // Check dump report.
- ProtoOutputStream output;
- std::set<string> strSet;
- int64_t dumpReportTimeNs = bucketStartTimeNs + 9000000;
- valueProducer->onDumpReport(dumpReportTimeNs, true /* include recent buckets */, true,
- NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
-
- StatsLogReport report = outputStreamToProto(&output);
- EXPECT_TRUE(report.has_value_metrics());
- EXPECT_EQ(0, report.value_metrics().data_size());
- EXPECT_EQ(1, report.value_metrics().skipped_size());
-
- EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
- report.value_metrics().skipped(0).start_bucket_elapsed_millis());
- EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
- report.value_metrics().skipped(0).end_bucket_elapsed_millis());
- EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
-
- auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
- EXPECT_EQ(BucketDropReason::BUCKET_TOO_SMALL, dropEvent.drop_reason());
- EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
-}
-
-/*
- * Test multiple bucket drop events in the same bucket.
- */
-TEST(ValueMetricProducerTest_BucketDrop, TestMultipleBucketDropEvents) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // Condition change to true.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
- event->write("field1");
- event->write(10);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithNoInitialCondition(pullerManager,
- metric);
-
- // Condition change event.
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
-
- // Check dump report.
- ProtoOutputStream output;
- std::set<string> strSet;
- int64_t dumpReportTimeNs = bucketStartTimeNs + 1000;
- valueProducer->onDumpReport(dumpReportTimeNs, true /* include recent buckets */, true,
- FAST /* dumpLatency */, &strSet, &output);
-
- StatsLogReport report = outputStreamToProto(&output);
- EXPECT_TRUE(report.has_value_metrics());
- EXPECT_EQ(0, report.value_metrics().data_size());
- EXPECT_EQ(1, report.value_metrics().skipped_size());
-
- EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
- report.value_metrics().skipped(0).start_bucket_elapsed_millis());
- EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
- report.value_metrics().skipped(0).end_bucket_elapsed_millis());
- EXPECT_EQ(2, report.value_metrics().skipped(0).drop_event_size());
-
- auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
- EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
- EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 10), dropEvent.drop_time_millis());
-
- dropEvent = report.value_metrics().skipped(0).drop_event(1);
- EXPECT_EQ(BucketDropReason::DUMP_REPORT_REQUESTED, dropEvent.drop_reason());
- EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
-}
-
-/*
- * Test that the number of logged bucket drop events is capped at the maximum.
- * The maximum is currently 10 and is set in MetricProducer::maxDropEventsReached().
- */
-TEST(ValueMetricProducerTest_BucketDrop, TestMaxBucketDropEvents) {
- ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // First condition change event.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- for (int i = 0; i < 2000; i++) {
- shared_ptr<LogEvent> event =
- make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
- event->write(i);
- event->write(i);
- event->init();
- data->push_back(event);
- }
- return true;
- }))
- .WillOnce(Return(false))
- .WillOnce(Return(false))
- .WillOnce(Return(false))
- .WillOnce(Return(false))
- .WillOnce(Return(false))
- .WillOnce(Return(false))
- .WillOnce(Return(false))
- .WillOnce(Return(false))
- .WillOnce(Return(false))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 220);
- event->write("field1");
- event->write(10);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithNoInitialCondition(pullerManager,
- metric);
-
- // First condition change event causes guardrail to be reached.
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
-
- // 2-10 condition change events result in failed pulls.
- valueProducer->onConditionChanged(false, bucketStartTimeNs + 30);
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
- valueProducer->onConditionChanged(false, bucketStartTimeNs + 70);
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 90);
- valueProducer->onConditionChanged(false, bucketStartTimeNs + 100);
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 150);
- valueProducer->onConditionChanged(false, bucketStartTimeNs + 170);
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 190);
- valueProducer->onConditionChanged(false, bucketStartTimeNs + 200);
-
- // Condition change event 11
- valueProducer->onConditionChanged(true, bucketStartTimeNs + 220);
-
- // Check dump report.
- ProtoOutputStream output;
- std::set<string> strSet;
- int64_t dumpReportTimeNs = bucketStartTimeNs + 1000;
- // Because we already have 10 dump events in the current bucket,
- // this case should not be added to the list of dump events.
- valueProducer->onDumpReport(bucketStartTimeNs + 1000, true /* include recent buckets */, true,
- FAST /* dumpLatency */, &strSet, &output);
-
- StatsLogReport report = outputStreamToProto(&output);
- EXPECT_TRUE(report.has_value_metrics());
- EXPECT_EQ(0, report.value_metrics().data_size());
- EXPECT_EQ(1, report.value_metrics().skipped_size());
-
- EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
- report.value_metrics().skipped(0).start_bucket_elapsed_millis());
- EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
- report.value_metrics().skipped(0).end_bucket_elapsed_millis());
- EXPECT_EQ(10, report.value_metrics().skipped(0).drop_event_size());
-
- auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
- EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
- EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 10), dropEvent.drop_time_millis());
-
- dropEvent = report.value_metrics().skipped(0).drop_event(1);
- EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
- EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 30), dropEvent.drop_time_millis());
-
- dropEvent = report.value_metrics().skipped(0).drop_event(2);
- EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
- EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 50), dropEvent.drop_time_millis());
-
- dropEvent = report.value_metrics().skipped(0).drop_event(3);
- EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
- EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 70), dropEvent.drop_time_millis());
-
- dropEvent = report.value_metrics().skipped(0).drop_event(4);
- EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
- EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 90), dropEvent.drop_time_millis());
-
- dropEvent = report.value_metrics().skipped(0).drop_event(5);
- EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
- EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 100), dropEvent.drop_time_millis());
-
- dropEvent = report.value_metrics().skipped(0).drop_event(6);
- EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
- EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 150), dropEvent.drop_time_millis());
-
- dropEvent = report.value_metrics().skipped(0).drop_event(7);
- EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
- EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 170), dropEvent.drop_time_millis());
-
- dropEvent = report.value_metrics().skipped(0).drop_event(8);
- EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
- EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 190), dropEvent.drop_time_millis());
-
- dropEvent = report.value_metrics().skipped(0).drop_event(9);
- EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
- EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 200), dropEvent.drop_time_millis());
-}
-
-/*
- * Test metric with a simple sliced state
- * - Increasing values
- * - Using diff
- * - Second field is value field
- */
-TEST(ValueMetricProducerTest, TestSlicedState) {
- // Set up ValueMetricProducer.
- ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("SCREEN_STATE");
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // ValueMetricProducer initialized.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
- event->write("field1");
- event->write(3);
- event->init();
- data->push_back(event);
- return true;
- }))
- // Screen state change to ON.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 5);
- event->write("field1");
- event->write(5);
- event->init();
- data->push_back(event);
- return true;
- }))
- // Screen state change to OFF.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
- event->write("field1");
- event->write(9);
- event->init();
- data->push_back(event);
- return true;
- }))
- // Screen state change to ON.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 15);
- event->write("field1");
- event->write(21);
- event->init();
- data->push_back(event);
- return true;
- }))
- // Dump report requested.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
- event->write("field1");
- event->write(30);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithState(
- pullerManager, metric, {android::util::SCREEN_STATE_CHANGED}, {});
-
- // Set up StateManager and check that StateTrackers are initialized.
- StateManager::getInstance().clear();
- StateManager::getInstance().registerListener(SCREEN_STATE_ATOM_ID, valueProducer);
- EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
- EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
-
- // Bucket status after metric initialized.
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- // Base for dimension key {}
- auto it = valueProducer->mCurrentSlicedBucket.begin();
- auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_EQ(true, itBase->second[0].hasBase);
- EXPECT_EQ(3, itBase->second[0].base.long_value);
- // Value for dimension, state key {{}, kStateUnknown}
- EXPECT_EQ(false, it->second[0].hasValue);
-
- // Bucket status after screen state change kStateUnknown->ON.
- auto screenEvent = CreateScreenStateChangedEvent(
- android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 5);
- StateManager::getInstance().onLogEvent(*screenEvent);
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- // Base for dimension key {}
- it = valueProducer->mCurrentSlicedBucket.begin();
- itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_EQ(true, itBase->second[0].hasBase);
- EXPECT_EQ(5, itBase->second[0].base.long_value);
- // Value for dimension, state key {{}, kStateUnknown}
- EXPECT_EQ(true, it->second[0].hasValue);
- EXPECT_EQ(2, it->second[0].value.long_value);
-
- // Bucket status after screen state change ON->OFF.
- screenEvent = CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
- bucketStartTimeNs + 10);
- StateManager::getInstance().onLogEvent(*screenEvent);
- EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
- // Base for dimension key {}
- it = valueProducer->mCurrentSlicedBucket.begin();
- itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_EQ(true, itBase->second[0].hasBase);
- EXPECT_EQ(9, itBase->second[0].base.long_value);
- // Value for dimension, state key {{}, ON}
- EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
- it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_EQ(true, it->second[0].hasValue);
- EXPECT_EQ(4, it->second[0].value.long_value);
- // Value for dimension, state key {{}, kStateUnknown}
- it++;
- EXPECT_EQ(true, it->second[0].hasValue);
- EXPECT_EQ(2, it->second[0].value.long_value);
-
- // Bucket status after screen state change OFF->ON.
- screenEvent = CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
- bucketStartTimeNs + 15);
- StateManager::getInstance().onLogEvent(*screenEvent);
- EXPECT_EQ(3UL, valueProducer->mCurrentSlicedBucket.size());
- // Base for dimension key {}
- it = valueProducer->mCurrentSlicedBucket.begin();
- itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_EQ(true, itBase->second[0].hasBase);
- EXPECT_EQ(21, itBase->second[0].base.long_value);
- // Value for dimension, state key {{}, OFF}
- EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
- it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_EQ(true, it->second[0].hasValue);
- EXPECT_EQ(12, it->second[0].value.long_value);
- // Value for dimension, state key {{}, ON}
- it++;
- EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
- it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_EQ(true, it->second[0].hasValue);
- EXPECT_EQ(4, it->second[0].value.long_value);
- // Value for dimension, state key {{}, kStateUnknown}
- it++;
- EXPECT_EQ(true, it->second[0].hasValue);
- EXPECT_EQ(2, it->second[0].value.long_value);
-
- // Start dump report and check output.
- ProtoOutputStream output;
- std::set<string> strSet;
- valueProducer->onDumpReport(bucketStartTimeNs + 50, true /* include recent buckets */, true,
- NO_TIME_CONSTRAINTS, &strSet, &output);
-
- StatsLogReport report = outputStreamToProto(&output);
- EXPECT_TRUE(report.has_value_metrics());
- EXPECT_EQ(3, report.value_metrics().data_size());
-
- auto data = report.value_metrics().data(0);
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
-
- data = report.value_metrics().data(1);
- EXPECT_EQ(1, report.value_metrics().data(1).bucket_info_size());
- EXPECT_EQ(13, report.value_metrics().data(1).bucket_info(0).values(0).value_long());
- EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
- EXPECT_TRUE(data.slice_by_state(0).has_value());
- EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON, data.slice_by_state(0).value());
-
- data = report.value_metrics().data(2);
- EXPECT_EQ(1, report.value_metrics().data(2).bucket_info_size());
- EXPECT_EQ(12, report.value_metrics().data(2).bucket_info(0).values(0).value_long());
- EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
- EXPECT_TRUE(data.slice_by_state(0).has_value());
- EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF, data.slice_by_state(0).value());
-}
-
-/*
- * Test metric with sliced state with map
- * - Increasing values
- * - Using diff
- * - Second field is value field
- */
-TEST(ValueMetricProducerTest, TestSlicedStateWithMap) {
- // Set up ValueMetricProducer.
- ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("SCREEN_STATE_ONOFF");
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // ValueMetricProducer initialized.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
- event->write("field1");
- event->write(3);
- event->init();
- data->push_back(event);
- return true;
- }))
- // Screen state change to ON.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 5);
- event->write("field1");
- event->write(5);
- event->init();
- data->push_back(event);
- return true;
- }))
- // Screen state change to VR.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
- event->write("field1");
- event->write(9);
- event->init();
- data->push_back(event);
- return true;
- }))
- // Screen state change to OFF.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 15);
- event->write("field1");
- event->write(21);
- event->init();
- data->push_back(event);
- return true;
- }))
- // Dump report requested.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
- event->write("field1");
- event->write(30);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- const StateMap& stateMap = CreateScreenStateOnOffMap();
- const StateMap_StateGroup screenOnGroup = stateMap.group(0);
- const StateMap_StateGroup screenOffGroup = stateMap.group(1);
-
- unordered_map<int, unordered_map<int, int64_t>> stateGroupMap;
- for (auto group : stateMap.group()) {
- for (auto value : group.value()) {
- stateGroupMap[SCREEN_STATE_ATOM_ID][value] = group.group_id();
- }
- }
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithState(
- pullerManager, metric, {android::util::SCREEN_STATE_CHANGED}, stateGroupMap);
-
- // Set up StateManager and check that StateTrackers are initialized.
- StateManager::getInstance().clear();
- StateManager::getInstance().registerListener(SCREEN_STATE_ATOM_ID, valueProducer);
- EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
- EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
-
- // Bucket status after metric initialized.
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- // Base for dimension key {}
- auto it = valueProducer->mCurrentSlicedBucket.begin();
- auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_EQ(true, itBase->second[0].hasBase);
- EXPECT_EQ(3, itBase->second[0].base.long_value);
- // Value for dimension, state key {{}, {}}
- EXPECT_EQ(false, it->second[0].hasValue);
-
- // Bucket status after screen state change kStateUnknown->ON.
- auto screenEvent = CreateScreenStateChangedEvent(
- android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 5);
- StateManager::getInstance().onLogEvent(*screenEvent);
- EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- // Base for dimension key {}
- it = valueProducer->mCurrentSlicedBucket.begin();
- itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_EQ(true, itBase->second[0].hasBase);
- EXPECT_EQ(5, itBase->second[0].base.long_value);
- // Value for dimension, state key {{}, kStateUnknown}
- EXPECT_EQ(true, it->second[0].hasValue);
- EXPECT_EQ(2, it->second[0].value.long_value);
-
- // Bucket status after screen state change ON->VR (also ON).
- screenEvent = CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_VR,
- bucketStartTimeNs + 10);
- StateManager::getInstance().onLogEvent(*screenEvent);
- EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
- // Base for dimension key {}
- it = valueProducer->mCurrentSlicedBucket.begin();
- itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_EQ(true, itBase->second[0].hasBase);
- EXPECT_EQ(9, itBase->second[0].base.long_value);
- // Value for dimension, state key {{}, ON GROUP}
- EXPECT_EQ(screenOnGroup.group_id(),
- it->first.getStateValuesKey().getValues()[0].mValue.long_value);
- EXPECT_EQ(true, it->second[0].hasValue);
- EXPECT_EQ(4, it->second[0].value.long_value);
- // Value for dimension, state key {{}, kStateUnknown}
- it++;
- EXPECT_EQ(true, it->second[0].hasValue);
- EXPECT_EQ(2, it->second[0].value.long_value);
-
- // Bucket status after screen state change VR->OFF.
- screenEvent = CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
- bucketStartTimeNs + 15);
- StateManager::getInstance().onLogEvent(*screenEvent);
- EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
- // Base for dimension key {}
- it = valueProducer->mCurrentSlicedBucket.begin();
- itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_EQ(true, itBase->second[0].hasBase);
- EXPECT_EQ(21, itBase->second[0].base.long_value);
- // Value for dimension, state key {{}, ON GROUP}
- EXPECT_EQ(screenOnGroup.group_id(),
- it->first.getStateValuesKey().getValues()[0].mValue.long_value);
- EXPECT_EQ(true, it->second[0].hasValue);
- EXPECT_EQ(16, it->second[0].value.long_value);
- // Value for dimension, state key {{}, kStateUnknown}
- it++;
- EXPECT_EQ(true, it->second[0].hasValue);
- EXPECT_EQ(2, it->second[0].value.long_value);
-
- // Start dump report and check output.
- ProtoOutputStream output;
- std::set<string> strSet;
- valueProducer->onDumpReport(bucketStartTimeNs + 50, true /* include recent buckets */, true,
- NO_TIME_CONSTRAINTS, &strSet, &output);
-
- StatsLogReport report = outputStreamToProto(&output);
- EXPECT_TRUE(report.has_value_metrics());
- EXPECT_EQ(3, report.value_metrics().data_size());
-
- auto data = report.value_metrics().data(0);
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
-
- data = report.value_metrics().data(1);
- EXPECT_EQ(1, report.value_metrics().data(1).bucket_info_size());
- EXPECT_EQ(16, report.value_metrics().data(1).bucket_info(0).values(0).value_long());
- EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
- EXPECT_TRUE(data.slice_by_state(0).has_group_id());
- EXPECT_EQ(screenOnGroup.group_id(), data.slice_by_state(0).group_id());
-
- data = report.value_metrics().data(2);
- EXPECT_EQ(1, report.value_metrics().data(2).bucket_info_size());
- EXPECT_EQ(9, report.value_metrics().data(2).bucket_info(0).values(0).value_long());
- EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
- EXPECT_TRUE(data.slice_by_state(0).has_group_id());
- EXPECT_EQ(screenOffGroup.group_id(), data.slice_by_state(0).group_id());
-}
-
-/*
- * Test metric that slices by state with a primary field and has dimensions
- * - Increasing values
- * - Using diff
- * - Second field is value field
- */
-TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
- // Set up ValueMetricProducer.
- ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("UID_PROCESS_STATE");
- metric.mutable_dimensions_in_what()->set_field(tagId);
- metric.mutable_dimensions_in_what()->add_child()->set_field(1);
-
- MetricStateLink* stateLink = metric.add_state_link();
- stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
- auto fieldsInWhat = stateLink->mutable_fields_in_what();
- *fieldsInWhat = CreateDimensions(tagId, {1 /* uid */});
- auto fieldsInState = stateLink->mutable_fields_in_state();
- *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- // ValueMetricProducer initialized.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
- event->write(2 /* uid */);
- event->write(7);
- event->init();
- data->push_back(event);
-
- event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
- event->write(1 /* uid */);
- event->write(3);
- event->init();
- data->push_back(event);
- return true;
- }))
- // Uid 1 process state change from kStateUnknown -> Foreground
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
- event->write(1 /* uid */);
- event->write(6);
- event->init();
- data->push_back(event);
-
- // This event should be skipped.
- event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
- event->write(2 /* uid */);
- event->write(8);
- event->init();
- data->push_back(event);
- return true;
- }))
- // Uid 2 process state change from kStateUnknown -> Background
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 40);
- event->write(2 /* uid */);
- event->write(9);
- event->init();
- data->push_back(event);
-
- // This event should be skipped.
- event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 40);
- event->write(1 /* uid */);
- event->write(12);
- event->init();
- data->push_back(event);
- return true;
- }))
- // Uid 1 process state change from Foreground -> Background
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 20);
- event->write(1 /* uid */);
- event->write(13);
- event->init();
- data->push_back(event);
-
- // This event should be skipped.
- event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 20);
- event->write(2 /* uid */);
- event->write(11);
- event->init();
- data->push_back(event);
- return true;
- }))
- // Uid 1 process state change from Background -> Foreground
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 40);
- event->write(1 /* uid */);
- event->write(17);
- event->init();
- data->push_back(event);
-
- // This event should be skipped.
- event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 40);
- event->write(2 /* uid */);
- event->write(15);
- event->init();
- data->push_back(event);
- return true;
- }))
- // Dump report pull.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 50);
- event->write(2 /* uid */);
- event->write(20);
- event->init();
- data->push_back(event);
-
- event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 50);
- event->write(1 /* uid */);
- event->write(21);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- sp<ValueMetricProducer> valueProducer =
- ValueMetricProducerTestHelper::createValueProducerWithState(
- pullerManager, metric, {UID_PROCESS_STATE_ATOM_ID}, {});
-
- // Set up StateManager and check that StateTrackers are initialized.
- StateManager::getInstance().clear();
- StateManager::getInstance().registerListener(UID_PROCESS_STATE_ATOM_ID, valueProducer);
- EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
- EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
-
- // Bucket status after metric initialized.
- EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
- // Base for dimension key {uid 1}.
- auto it = valueProducer->mCurrentSlicedBucket.begin();
- EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_EQ(true, itBase->second[0].hasBase);
- EXPECT_EQ(3, itBase->second[0].base.long_value);
- // Value for dimension, state key {{uid 1}, kStateUnknown}
- // TODO(tsaichristine): test equality of state values key
- // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_EQ(false, it->second[0].hasValue);
- // Base for dimension key {uid 2}
- it++;
- EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_EQ(true, itBase->second[0].hasBase);
- EXPECT_EQ(7, itBase->second[0].base.long_value);
- // Value for dimension, state key {{uid 2}, kStateUnknown}
- // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_EQ(false, it->second[0].hasValue);
-
- // Bucket status after uid 1 process state change kStateUnknown -> Foreground.
- auto uidProcessEvent = CreateUidProcessStateChangedEvent(
- 1 /* uid */, android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, bucketStartTimeNs + 20);
- StateManager::getInstance().onLogEvent(*uidProcessEvent);
- EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
- // Base for dimension key {uid 1}.
- it = valueProducer->mCurrentSlicedBucket.begin();
- EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- EXPECT_EQ(true, itBase->second[0].hasBase);
- EXPECT_EQ(6, itBase->second[0].base.long_value);
- // Value for key {uid 1, kStateUnknown}.
- // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_EQ(true, it->second[0].hasValue);
- EXPECT_EQ(3, it->second[0].value.long_value);
-
- // Base for dimension key {uid 2}
- it++;
- EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- EXPECT_EQ(true, itBase->second[0].hasBase);
- EXPECT_EQ(7, itBase->second[0].base.long_value);
- // Value for key {uid 2, kStateUnknown}
- EXPECT_EQ(false, it->second[0].hasValue);
-
- // Bucket status after uid 2 process state change kStateUnknown -> Background.
- uidProcessEvent = CreateUidProcessStateChangedEvent(
- 2 /* uid */, android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, bucketStartTimeNs + 40);
- StateManager::getInstance().onLogEvent(*uidProcessEvent);
- EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
- // Base for dimension key {uid 1}.
- it = valueProducer->mCurrentSlicedBucket.begin();
- EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_EQ(true, itBase->second[0].hasBase);
- EXPECT_EQ(6, itBase->second[0].base.long_value);
- // Value for key {uid 1, kStateUnknown}.
- EXPECT_EQ(true, it->second[0].hasValue);
- EXPECT_EQ(3, it->second[0].value.long_value);
-
- // Base for dimension key {uid 2}
- it++;
- EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_EQ(true, itBase->second[0].hasBase);
- EXPECT_EQ(9, itBase->second[0].base.long_value);
- // Value for key {uid 2, kStateUnknown}
- // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_EQ(true, it->second[0].hasValue);
- EXPECT_EQ(2, it->second[0].value.long_value);
-
- // Pull at end of first bucket.
- vector<shared_ptr<LogEvent>> allData;
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs);
- event->write(1 /* uid */);
- event->write(10);
- event->init();
- allData.push_back(event);
-
- event = make_shared<LogEvent>(tagId, bucket2StartTimeNs);
- event->write(2 /* uid */);
- event->write(15);
- event->init();
- allData.push_back(event);
-
- valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
-
- // Buckets flushed after end of first bucket.
- // None of the buckets should have a value.
- EXPECT_EQ(4UL, valueProducer->mCurrentSlicedBucket.size());
- EXPECT_EQ(4UL, valueProducer->mPastBuckets.size());
- EXPECT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
- // Base for dimension key {uid 2}.
- it = valueProducer->mCurrentSlicedBucket.begin();
- EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_EQ(true, itBase->second[0].hasBase);
- EXPECT_EQ(15, itBase->second[0].base.long_value);
- // Value for key {uid 2, BACKGROUND}.
- EXPECT_EQ(1, it->first.getStateValuesKey().getValues().size());
- EXPECT_EQ(1006, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_EQ(false, it->second[0].hasValue);
-
- // Base for dimension key {uid 1}
- it++;
- EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_EQ(true, itBase->second[0].hasBase);
- EXPECT_EQ(10, itBase->second[0].base.long_value);
- // Value for key {uid 1, kStateUnknown}
- EXPECT_EQ(0, it->first.getStateValuesKey().getValues().size());
- // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_EQ(false, it->second[0].hasValue);
-
- // Value for key {uid 1, FOREGROUND}
- it++;
- EXPECT_EQ(1, it->first.getStateValuesKey().getValues().size());
- EXPECT_EQ(1005, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_EQ(false, it->second[0].hasValue);
-
- // Value for key {uid 2, kStateUnknown}
- it++;
- EXPECT_EQ(false, it->second[0].hasValue);
-
- // Bucket status after uid 1 process state change from Foreground -> Background.
- uidProcessEvent = CreateUidProcessStateChangedEvent(
- 1 /* uid */, android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, bucket2StartTimeNs + 20);
- StateManager::getInstance().onLogEvent(*uidProcessEvent);
-
- EXPECT_EQ(4UL, valueProducer->mCurrentSlicedBucket.size());
- EXPECT_EQ(4UL, valueProducer->mPastBuckets.size());
- EXPECT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
- // Base for dimension key {uid 2}.
- it = valueProducer->mCurrentSlicedBucket.begin();
- EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_EQ(true, itBase->second[0].hasBase);
- EXPECT_EQ(15, itBase->second[0].base.long_value);
- // Value for key {uid 2, BACKGROUND}.
- EXPECT_EQ(false, it->second[0].hasValue);
- // Base for dimension key {uid 1}
- it++;
- EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_EQ(true, itBase->second[0].hasBase);
- EXPECT_EQ(13, itBase->second[0].base.long_value);
- // Value for key {uid 1, kStateUnknown}
- EXPECT_EQ(false, it->second[0].hasValue);
- // Value for key {uid 1, FOREGROUND}
- it++;
- EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- EXPECT_EQ(1005, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_EQ(true, it->second[0].hasValue);
- EXPECT_EQ(3, it->second[0].value.long_value);
- // Value for key {uid 2, kStateUnknown}
- it++;
- EXPECT_EQ(false, it->second[0].hasValue);
-
- // Bucket status after uid 1 process state change Background->Foreground.
- uidProcessEvent = CreateUidProcessStateChangedEvent(
- 1 /* uid */, android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, bucket2StartTimeNs + 40);
- StateManager::getInstance().onLogEvent(*uidProcessEvent);
-
- EXPECT_EQ(5UL, valueProducer->mCurrentSlicedBucket.size());
- EXPECT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
- // Base for dimension key {uid 2}
- it = valueProducer->mCurrentSlicedBucket.begin();
- EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_EQ(true, itBase->second[0].hasBase);
- EXPECT_EQ(15, itBase->second[0].base.long_value);
- EXPECT_EQ(false, it->second[0].hasValue);
-
- it++;
- EXPECT_EQ(false, it->second[0].hasValue);
-
- // Base for dimension key {uid 1}
- it++;
- EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
- EXPECT_EQ(17, itBase->second[0].base.long_value);
- // Value for key {uid 1, BACKGROUND}
- EXPECT_EQ(1006, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_EQ(true, it->second[0].hasValue);
- EXPECT_EQ(4, it->second[0].value.long_value);
- // Value for key {uid 1, FOREGROUND}
- it++;
- EXPECT_EQ(1005, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
- EXPECT_EQ(true, it->second[0].hasValue);
- EXPECT_EQ(3, it->second[0].value.long_value);
-
- // Start dump report and check output.
- ProtoOutputStream output;
- std::set<string> strSet;
- valueProducer->onDumpReport(bucket2StartTimeNs + 50, true /* include recent buckets */, true,
- NO_TIME_CONSTRAINTS, &strSet, &output);
-
- StatsLogReport report = outputStreamToProto(&output);
- EXPECT_TRUE(report.has_value_metrics());
- EXPECT_EQ(5, report.value_metrics().data_size());
-
- auto data = report.value_metrics().data(0);
- EXPECT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(4, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
- EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
- EXPECT_TRUE(data.slice_by_state(0).has_value());
- EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
- data.slice_by_state(0).value());
-
- data = report.value_metrics().data(1);
- EXPECT_EQ(1, report.value_metrics().data(1).bucket_info_size());
- EXPECT_EQ(2, report.value_metrics().data(1).bucket_info(0).values(0).value_long());
-
- data = report.value_metrics().data(2);
- EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
- EXPECT_TRUE(data.slice_by_state(0).has_value());
- EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
- data.slice_by_state(0).value());
- EXPECT_EQ(2, report.value_metrics().data(2).bucket_info_size());
- EXPECT_EQ(4, report.value_metrics().data(2).bucket_info(0).values(0).value_long());
- EXPECT_EQ(7, report.value_metrics().data(2).bucket_info(1).values(0).value_long());
-
- data = report.value_metrics().data(3);
- EXPECT_EQ(1, report.value_metrics().data(3).bucket_info_size());
- EXPECT_EQ(3, report.value_metrics().data(3).bucket_info(0).values(0).value_long());
-
- data = report.value_metrics().data(4);
- EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
- EXPECT_TRUE(data.slice_by_state(0).has_value());
- EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
- data.slice_by_state(0).value());
- EXPECT_EQ(2, report.value_metrics().data(4).bucket_info_size());
- EXPECT_EQ(6, report.value_metrics().data(4).bucket_info(0).values(0).value_long());
- EXPECT_EQ(5, report.value_metrics().data(4).bucket_info(1).values(0).value_long());
-}
+// TODO(b/149590301): Update these tests to use new socket schema.
+//class ValueMetricProducerTestHelper {
+//
+// public:
+// static shared_ptr<LogEvent> createEvent(int64_t eventTimeNs, int64_t value) {
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, eventTimeNs);
+// event->write(tagId);
+// event->write(value);
+// event->write(value);
+// event->init();
+// return event;
+// }
+//
+// 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)});
+// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+// EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+// EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+//
+// sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
+// kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+// logEventMatcherIndex, eventMatcherWizard, tagId,
+// bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+// return valueProducer;
+// }
+//
+// static sp<ValueMetricProducer> createValueProducerWithCondition(
+// 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)});
+// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+// EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+// EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+//
+// sp<ValueMetricProducer> valueProducer =
+// new ValueMetricProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
+// eventMatcherWizard, tagId, bucketStartTimeNs,
+// bucketStartTimeNs, pullerManager);
+// valueProducer->mCondition = ConditionState::kFalse;
+// return valueProducer;
+// }
+//
+// static sp<ValueMetricProducer> createValueProducerWithNoInitialCondition(
+// 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)});
+// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+// EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+// EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+//
+// sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
+// kConfigKey, metric, 1, wizard, logEventMatcherIndex, eventMatcherWizard, tagId,
+// bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+// return valueProducer;
+// }
+//
+// static sp<ValueMetricProducer> createValueProducerWithState(
+// 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)});
+// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+// EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+// EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+// sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
+// kConfigKey, metric, -1 /* no condition */, wizard, logEventMatcherIndex,
+// eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager, {},
+// {}, slicedStateAtoms, stateGroupMap);
+// return valueProducer;
+// }
+//
+// static ValueMetric createMetric() {
+// ValueMetric metric;
+// metric.set_id(metricId);
+// metric.set_bucket(ONE_MINUTE);
+// metric.mutable_value_field()->set_field(tagId);
+// metric.mutable_value_field()->add_child()->set_field(2);
+// metric.set_max_pull_delay_sec(INT_MAX);
+// return metric;
+// }
+//
+// static ValueMetric createMetricWithCondition() {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+// metric.set_condition(StringToId("SCREEN_ON"));
+// return metric;
+// }
+//
+// static ValueMetric createMetricWithState(string state) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+// metric.add_slice_by_state(StringToId(state));
+// return metric;
+// }
+//};
+//
+///*
+// * Tests that the first bucket works correctly
+// */
+//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)});
+// 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);
+//
+// EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
+// EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
+// EXPECT_EQ(60 * NS_PER_SEC + startTimeBase,
+// valueProducer.calcPreviousBucketEndTime(2 * 60 * NS_PER_SEC));
+// EXPECT_EQ(2 * 60 * NS_PER_SEC + startTimeBase,
+// valueProducer.calcPreviousBucketEndTime(3 * 60 * NS_PER_SEC));
+//}
+//
+///*
+// * Tests that the first bucket works correctly
+// */
+//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)});
+// 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);
+//
+// EXPECT_EQ(600500000000, valueProducer.mCurrentBucketStartTimeNs);
+// EXPECT_EQ(10, valueProducer.mCurrentBucketNum);
+// EXPECT_EQ(660000000005, valueProducer.getCurrentBucketEndTimeNs());
+//}
+//
+///*
+// * Tests pulled atoms with no conditions
+// */
+//TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+// event->write(tagId);
+// event->write(3);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+//
+// vector<shared_ptr<LogEvent>> allData;
+// allData.clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+// event->write(tagId);
+// event->write(11);
+// event->init();
+// allData.push_back(event);
+//
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// ValueMetricProducer::Interval curInterval =
+// valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(11, curBaseInfo.base.long_value);
+// EXPECT_EQ(false, curInterval.hasValue);
+// EXPECT_EQ(8, curInterval.value.long_value);
+// EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+// EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
+// EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
+//
+// allData.clear();
+// event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
+// event->write(tagId);
+// event->write(23);
+// event->init();
+// allData.push_back(event);
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(23, curBaseInfo.base.long_value);
+// EXPECT_EQ(false, curInterval.hasValue);
+// EXPECT_EQ(12, curInterval.value.long_value);
+// EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+// EXPECT_EQ(2UL, valueProducer->mPastBuckets.begin()->second.size());
+// EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
+// EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
+// EXPECT_EQ(12, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
+// EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs);
+//
+// allData.clear();
+// event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
+// event->write(tagId);
+// event->write(36);
+// event->init();
+// allData.push_back(event);
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(36, curBaseInfo.base.long_value);
+// EXPECT_EQ(false, curInterval.hasValue);
+// EXPECT_EQ(13, curInterval.value.long_value);
+// EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+// EXPECT_EQ(3UL, valueProducer->mPastBuckets.begin()->second.size());
+// EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
+// EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
+// EXPECT_EQ(12, valueProducer->mPastBuckets.begin()->second[1].values[0].long_value);
+// EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[1].mConditionTrueNs);
+// EXPECT_EQ(13, valueProducer->mPastBuckets.begin()->second[2].values[0].long_value);
+// EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[2].mConditionTrueNs);
+//}
+//
+//TEST(ValueMetricProducerTest, TestPartialBucketCreated) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // Initialize bucket.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
+// event->write(tagId);
+// event->write(1);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// // Partial bucket.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
+// event->write(tagId);
+// event->write(5);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+//
+// // First bucket ends.
+// vector<shared_ptr<LogEvent>> allData;
+// allData.clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
+// event->write(tagId);
+// event->write(2);
+// event->init();
+// allData.push_back(event);
+// valueProducer->onDataPulled(allData, /** success */ true, bucket2StartTimeNs);
+//
+// // Partial buckets created in 2nd bucket.
+// valueProducer->notifyAppUpgrade(bucket2StartTimeNs + 2, "com.foo", 10000, 1);
+//
+// // One full bucket and one partial bucket.
+// EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+// vector<ValueBucket> buckets = valueProducer->mPastBuckets.begin()->second;
+// EXPECT_EQ(2UL, buckets.size());
+// // Full bucket (2 - 1)
+// EXPECT_EQ(1, buckets[0].values[0].long_value);
+// EXPECT_EQ(bucketSizeNs, buckets[0].mConditionTrueNs);
+// // Full bucket (5 - 3)
+// EXPECT_EQ(3, buckets[1].values[0].long_value);
+// // partial bucket [bucket2StartTimeNs, bucket2StartTimeNs + 2]
+// EXPECT_EQ(2, buckets[1].mConditionTrueNs);
+//}
+//
+///*
+// * Tests pulled atoms with filtering
+// */
+//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);
+// sp<EventMatcherWizard> eventMatcherWizard =
+// new EventMatcherWizard({new SimpleLogMatchingTracker(
+// atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+// EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+// event->write(3);
+// event->write(3);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
+// kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, logEventMatcherIndex,
+// eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+//
+// vector<shared_ptr<LogEvent>> allData;
+// allData.clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+// event->write(3);
+// event->write(11);
+// event->init();
+// allData.push_back(event);
+//
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// ValueMetricProducer::Interval curInterval =
+// valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(11, curBaseInfo.base.long_value);
+// EXPECT_EQ(false, curInterval.hasValue);
+// EXPECT_EQ(8, curInterval.value.long_value);
+// EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+// EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
+// EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
+//
+// allData.clear();
+// event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
+// event->write(4);
+// event->write(23);
+// event->init();
+// allData.push_back(event);
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+// // No new data seen, so data has been cleared.
+// EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
+//
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(11, curBaseInfo.base.long_value);
+// EXPECT_EQ(false, curInterval.hasValue);
+// EXPECT_EQ(8, curInterval.value.long_value);
+// EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+// EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
+// EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
+//
+// allData.clear();
+// event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
+// event->write(3);
+// event->write(36);
+// event->init();
+// allData.push_back(event);
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//
+// // the base was reset
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(36, curBaseInfo.base.long_value);
+// EXPECT_EQ(false, curInterval.hasValue);
+// EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+// EXPECT_EQ(1UL, valueProducer->mPastBuckets.begin()->second.size());
+// EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
+// EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs);
+//}
+//
+///*
+// * Tests pulled atoms with no conditions and take absolute value after reset
+// */
+//TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+// metric.set_use_absolute_value_on_reset(true);
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(true));
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+//
+// vector<shared_ptr<LogEvent>> allData;
+// allData.clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+// event->write(tagId);
+// event->write(11);
+// event->init();
+// allData.push_back(event);
+//
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(11, curBaseInfo.base.long_value);
+// EXPECT_EQ(false, curInterval.hasValue);
+// EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+//
+// allData.clear();
+// event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
+// event->write(tagId);
+// event->write(10);
+// event->init();
+// allData.push_back(event);
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(10, curBaseInfo.base.long_value);
+// EXPECT_EQ(false, curInterval.hasValue);
+// EXPECT_EQ(10, curInterval.value.long_value);
+// EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+// EXPECT_EQ(10, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
+// EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs);
+//
+// allData.clear();
+// event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
+// event->write(tagId);
+// event->write(36);
+// event->init();
+// allData.push_back(event);
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(36, curBaseInfo.base.long_value);
+// EXPECT_EQ(false, curInterval.hasValue);
+// EXPECT_EQ(26, curInterval.value.long_value);
+// EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+// EXPECT_EQ(2UL, valueProducer->mPastBuckets.begin()->second.size());
+// EXPECT_EQ(10, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
+// EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
+// EXPECT_EQ(26, valueProducer->mPastBuckets.begin()->second[1].values[0].long_value);
+// EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[1].mConditionTrueNs);
+//}
+//
+///*
+// * Tests pulled atoms with no conditions and take zero value after reset
+// */
+//TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(false));
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+//
+// vector<shared_ptr<LogEvent>> allData;
+// allData.clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+// event->write(tagId);
+// event->write(11);
+// event->init();
+// allData.push_back(event);
+//
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(11, curBaseInfo.base.long_value);
+// EXPECT_EQ(false, curInterval.hasValue);
+// EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+//
+// allData.clear();
+// event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
+// event->write(tagId);
+// event->write(10);
+// event->init();
+// allData.push_back(event);
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(10, curBaseInfo.base.long_value);
+// EXPECT_EQ(false, curInterval.hasValue);
+// EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+//
+// allData.clear();
+// event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
+// event->write(tagId);
+// event->write(36);
+// event->init();
+// allData.push_back(event);
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(36, curBaseInfo.base.long_value);
+// EXPECT_EQ(false, curInterval.hasValue);
+// EXPECT_EQ(26, curInterval.value.long_value);
+// EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+// EXPECT_EQ(26, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
+// EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
+//}
+//
+///*
+// * Test pulled event with non sliced condition.
+// */
+//TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
+// event->write(tagId);
+// event->write(100);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+// event->write(tagId);
+// event->write(130);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
+// event->write(tagId);
+// event->write(180);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+// valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
+//
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+// // startUpdated:false sum:0 start:100
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(100, curBaseInfo.base.long_value);
+// EXPECT_EQ(false, curInterval.hasValue);
+// EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+//
+// vector<shared_ptr<LogEvent>> allData;
+// allData.clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+// event->write(1);
+// event->write(110);
+// event->init();
+// allData.push_back(event);
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs - 8});
+//
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(110, curBaseInfo.base.long_value);
+// EXPECT_EQ(false, curInterval.hasValue);
+// EXPECT_EQ(10, curInterval.value.long_value);
+//
+// valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
+// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs - 8});
+//
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+// EXPECT_EQ(true, curInterval.hasValue);
+// EXPECT_EQ(20, curInterval.value.long_value);
+// EXPECT_EQ(false, curBaseInfo.hasBase);
+//
+// valueProducer->onConditionChanged(true, bucket3StartTimeNs + 1);
+// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10, 20}, {bucketSizeNs - 8, 1});
+//}
+//
+//TEST(ValueMetricProducerTest, TestPushedEventsWithUpgrade) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//
+// UidMap uidMap;
+// SimpleAtomMatcher atomMatcher;
+// atomMatcher.set_atom_id(tagId);
+// sp<EventMatcherWizard> eventMatcherWizard =
+// new EventMatcherWizard({new SimpleLogMatchingTracker(
+// atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+// eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+// pullerManager);
+//
+// shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+// event1->write(1);
+// event1->write(10);
+// event1->init();
+// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
+// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+//
+// valueProducer.notifyAppUpgrade(bucketStartTimeNs + 150, "ANY.APP", 1, 1);
+// EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+// EXPECT_EQ(bucketStartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs);
+//
+// shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 59 * NS_PER_SEC);
+// event2->write(1);
+// event2->write(10);
+// event2->init();
+// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
+// EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+// EXPECT_EQ(bucketStartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs);
+//
+// // Next value should create a new bucket.
+// shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 65 * NS_PER_SEC);
+// event3->write(1);
+// event3->write(10);
+// event3->init();
+// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
+// EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, valueProducer.mCurrentBucketStartTimeNs);
+//}
+//
+//TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//
+// UidMap uidMap;
+// SimpleAtomMatcher atomMatcher;
+// atomMatcher.set_atom_id(tagId);
+// sp<EventMatcherWizard> eventMatcherWizard =
+// new EventMatcherWizard({new SimpleLogMatchingTracker(
+// atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+// EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// .WillOnce(Return(true))
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 149);
+// event->write(tagId);
+// event->write(120);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+// ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+// eventMatcherWizard, tagId, bucketStartTimeNs,
+// bucketStartTimeNs, pullerManager);
+//
+// vector<shared_ptr<LogEvent>> allData;
+// allData.clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+// event->write(tagId);
+// event->write(100);
+// event->init();
+// allData.push_back(event);
+//
+// valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+//
+// valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 150, "ANY.APP", 1, 1);
+// EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+// EXPECT_EQ(bucket2StartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs);
+// assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {20}, {150});
+//
+// allData.clear();
+// event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
+// event->write(tagId);
+// event->write(150);
+// event->init();
+// allData.push_back(event);
+// valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+// EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+// EXPECT_EQ(bucket3StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
+// EXPECT_EQ(20L,
+// valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].values[0].long_value);
+// assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {20, 30},
+// {150, bucketSizeNs - 150});
+//}
+//
+//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)});
+// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+// EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
+// EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(true));
+// ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+// eventMatcherWizard, tagId, bucketStartTimeNs,
+// bucketStartTimeNs, pullerManager);
+//
+// vector<shared_ptr<LogEvent>> allData;
+// allData.clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+// event->write(tagId);
+// event->write(100);
+// event->init();
+// allData.push_back(event);
+//
+// valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+//
+// valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 150, "ANY.APP", 1, 1);
+// EXPECT_EQ(0UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+// EXPECT_EQ(bucket2StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
+//}
+//
+//TEST(ValueMetricProducerTest, TestPulledValueWithUpgradeWhileConditionFalse) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
+// event->write(tagId);
+// event->write(100);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs - 100);
+// event->write(tagId);
+// event->write(120);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+// valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
+//
+// valueProducer->onConditionChanged(false, bucket2StartTimeNs-100);
+// EXPECT_FALSE(valueProducer->mCondition);
+//
+// valueProducer->notifyAppUpgrade(bucket2StartTimeNs-50, "ANY.APP", 1, 1);
+// // Expect one full buckets already done and starting a partial bucket.
+// EXPECT_EQ(bucket2StartTimeNs-50, valueProducer->mCurrentBucketStartTimeNs);
+// EXPECT_EQ(1UL, valueProducer->mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+// EXPECT_EQ(bucketStartTimeNs,
+// valueProducer->mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
+// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20},
+// {(bucket2StartTimeNs - 100) - (bucketStartTimeNs + 1)});
+// EXPECT_FALSE(valueProducer->mCondition);
+//}
+//
+//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)});
+// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//
+// ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+// eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+// pullerManager);
+//
+// shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+// event1->write(1);
+// event1->write(10);
+// event1->init();
+// shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
+// event2->write(1);
+// event2->write(20);
+// event2->init();
+// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+// ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+// EXPECT_EQ(10, curInterval.value.long_value);
+// EXPECT_EQ(true, curInterval.hasValue);
+//
+// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
+//
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+// curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+// EXPECT_EQ(30, curInterval.value.long_value);
+//
+// valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
+// assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {30}, {bucketSizeNs});
+//}
+//
+//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)});
+// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//
+// ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
+// eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+// pullerManager);
+// valueProducer.mCondition = ConditionState::kFalse;
+//
+// shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+// event1->write(1);
+// event1->write(10);
+// event1->init();
+// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
+// // has 1 slice
+// EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
+//
+// valueProducer.onConditionChangedLocked(true, bucketStartTimeNs + 15);
+// shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
+// event2->write(1);
+// event2->write(20);
+// event2->init();
+// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
+//
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+// ValueMetricProducer::Interval curInterval =
+// valueProducer.mCurrentSlicedBucket.begin()->second[0];
+// curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+// EXPECT_EQ(20, curInterval.value.long_value);
+//
+// shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 30);
+// event3->write(1);
+// event3->write(30);
+// event3->init();
+// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
+//
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+// curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+// EXPECT_EQ(50, curInterval.value.long_value);
+//
+// valueProducer.onConditionChangedLocked(false, bucketStartTimeNs + 35);
+// shared_ptr<LogEvent> event4 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 40);
+// event4->write(1);
+// event4->write(40);
+// event4->init();
+// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
+//
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+// curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+// EXPECT_EQ(50, curInterval.value.long_value);
+//
+// valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
+// assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {50}, {20});
+//}
+//
+//TEST(ValueMetricProducerTest, TestAnomalyDetection) {
+// sp<AlarmMonitor> alarmMonitor;
+// Alert alert;
+// alert.set_id(101);
+// alert.set_metric_id(metricId);
+// alert.set_trigger_if_sum_gt(130);
+// alert.set_num_buckets(2);
+// const int32_t refPeriodSec = 3;
+// alert.set_refractory_period_secs(refPeriodSec);
+//
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//
+// UidMap uidMap;
+// SimpleAtomMatcher atomMatcher;
+// atomMatcher.set_atom_id(tagId);
+// sp<EventMatcherWizard> eventMatcherWizard =
+// new EventMatcherWizard({new SimpleLogMatchingTracker(
+// atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+// logEventMatcherIndex, eventMatcherWizard, -1 /*not pulled*/,
+// bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+//
+// sp<AnomalyTracker> anomalyTracker = valueProducer.addAnomalyTracker(alert, alarmMonitor);
+//
+//
+// shared_ptr<LogEvent> event1
+// = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1 * NS_PER_SEC);
+// event1->write(161);
+// event1->write(10); // value of interest
+// event1->init();
+// shared_ptr<LogEvent> event2
+// = make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 + NS_PER_SEC);
+// event2->write(162);
+// event2->write(20); // value of interest
+// event2->init();
+// shared_ptr<LogEvent> event3
+// = make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 1 * NS_PER_SEC);
+// event3->write(163);
+// event3->write(130); // value of interest
+// event3->init();
+// shared_ptr<LogEvent> event4
+// = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 1 * NS_PER_SEC);
+// event4->write(35);
+// event4->write(1); // value of interest
+// event4->init();
+// shared_ptr<LogEvent> event5
+// = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2 * NS_PER_SEC);
+// event5->write(45);
+// event5->write(150); // value of interest
+// event5->init();
+// shared_ptr<LogEvent> event6
+// = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 10 * NS_PER_SEC);
+// event6->write(25);
+// event6->write(160); // value of interest
+// event6->init();
+//
+// // Two events in bucket #0.
+// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
+// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
+// // Value sum == 30 <= 130.
+// EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
+//
+// // One event in bucket #2. No alarm as bucket #0 is trashed out.
+// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
+// // Value sum == 130 <= 130.
+// EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
+//
+// // Three events in bucket #3.
+// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
+// // Anomaly at event 4 since Value sum == 131 > 130!
+// EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
+// std::ceil(1.0 * event4->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
+// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event5);
+// // Event 5 is within 3 sec refractory period. Thus last alarm timestamp is still event4.
+// EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
+// std::ceil(1.0 * event4->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
+//
+// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event6);
+// // Anomaly at event 6 since Value sum == 160 > 130 and after refractory period.
+// EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
+// std::ceil(1.0 * event6->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
+//}
+//
+//// 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, _)).WillOnce(Return(true));
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+//
+// vector<shared_ptr<LogEvent>> allData;
+// // pull 1
+// allData.clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+// event->write(tagId);
+// event->write(11);
+// event->init();
+// allData.push_back(event);
+//
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// ValueMetricProducer::Interval curInterval =
+// valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//
+// // startUpdated:true sum:0 start:11
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(11, curBaseInfo.base.long_value);
+// EXPECT_EQ(false, curInterval.hasValue);
+// EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+//
+// // pull 2 at correct time
+// allData.clear();
+// event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
+// event->write(tagId);
+// event->write(23);
+// event->init();
+// allData.push_back(event);
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+// // tartUpdated:false sum:12
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(23, curBaseInfo.base.long_value);
+// EXPECT_EQ(false, curInterval.hasValue);
+// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {12}, {bucketSizeNs});
+//
+// // pull 3 come late.
+// // The previous bucket gets closed with error. (Has start value 23, no ending)
+// // Another bucket gets closed with error. (No start, but ending with 36)
+// // The new bucket is back to normal.
+// allData.clear();
+// event = make_shared<LogEvent>(tagId, bucket6StartTimeNs + 1);
+// event->write(tagId);
+// event->write(36);
+// event->init();
+// allData.push_back(event);
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket6StartTimeNs);
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+// // startUpdated:false sum:12
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(36, curBaseInfo.base.long_value);
+// EXPECT_EQ(false, curInterval.hasValue);
+// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {12}, {bucketSizeNs});
+//}
+//
+///*
+// * Test pulled event with non sliced condition. The pull on boundary come late because the alarm
+// * was delivered late.
+// */
+//TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // condition becomes true
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
+// event->write(tagId);
+// event->write(100);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// // condition becomes false
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+// event->write(tagId);
+// event->write(120);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+// valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
+//
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// ValueMetricProducer::Interval curInterval =
+// valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(100, curBaseInfo.base.long_value);
+// EXPECT_EQ(false, curInterval.hasValue);
+// EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+//
+// // 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];
+// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
+// EXPECT_EQ(false, curBaseInfo.hasBase);
+//
+// // Now the alarm is delivered.
+// // since the condition turned to off before this pull finish, it has no effect
+// vector<shared_ptr<LogEvent>> allData;
+// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 110));
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//
+// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
+// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+// EXPECT_EQ(false, curBaseInfo.hasBase);
+// EXPECT_EQ(false, curInterval.hasValue);
+//}
+//
+///*
+// * Test pulled event with non sliced condition. The pull on boundary come late, after the condition
+// * change to false, and then true again. This is due to alarm delivered late.
+// */
+//TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // condition becomes true
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
+// event->write(tagId);
+// event->write(100);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// // condition becomes false
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+// event->write(tagId);
+// event->write(120);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// // condition becomes true again
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 25);
+// event->write(tagId);
+// event->write(130);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+// valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
+//
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// ValueMetricProducer::Interval curInterval =
+// valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+// // startUpdated:false sum:0 start:100
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(100, curBaseInfo.base.long_value);
+// EXPECT_EQ(false, curInterval.hasValue);
+// EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+//
+// // pull on bucket boundary come late, condition change happens before it
+// valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
+// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+// EXPECT_EQ(false, curBaseInfo.hasBase);
+// EXPECT_EQ(false, curInterval.hasValue);
+//
+// // condition changed to true again, before the pull alarm is delivered
+// valueProducer->onConditionChanged(true, bucket2StartTimeNs + 25);
+// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
+// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(130, curBaseInfo.base.long_value);
+// EXPECT_EQ(false, curInterval.hasValue);
+//
+// // Now the alarm is delivered, but it is considered late, the data will be used
+// // for the new bucket since it was just pulled.
+// vector<shared_ptr<LogEvent>> allData;
+// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 50, 140));
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 50);
+//
+// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(140, curBaseInfo.base.long_value);
+// EXPECT_EQ(true, curInterval.hasValue);
+// EXPECT_EQ(10, curInterval.value.long_value);
+// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
+//
+// allData.clear();
+// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket3StartTimeNs, 160));
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20, 30},
+// {bucketSizeNs - 8, bucketSizeNs - 24});
+//}
+//
+//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)});
+// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//
+// ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+// eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+// pullerManager);
+//
+// shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+// event1->write(1);
+// event1->write(10);
+// event1->init();
+// shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
+// event2->write(1);
+// event2->write(20);
+// event2->init();
+// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+// ValueMetricProducer::Interval curInterval =
+// valueProducer.mCurrentSlicedBucket.begin()->second[0];
+// EXPECT_EQ(10, curInterval.value.long_value);
+// EXPECT_EQ(true, curInterval.hasValue);
+//
+// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
+//
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+// curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+// EXPECT_EQ(10, curInterval.value.long_value);
+//
+// valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
+// assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {10}, {bucketSizeNs});
+//}
+//
+//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)});
+// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//
+// ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+// eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+// pullerManager);
+//
+// shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+// event1->write(1);
+// event1->write(10);
+// event1->init();
+// shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
+// event2->write(1);
+// event2->write(20);
+// event2->init();
+// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+// ValueMetricProducer::Interval curInterval =
+// valueProducer.mCurrentSlicedBucket.begin()->second[0];
+// EXPECT_EQ(10, curInterval.value.long_value);
+// EXPECT_EQ(true, curInterval.hasValue);
+//
+// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
+//
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+// curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+// EXPECT_EQ(20, curInterval.value.long_value);
+//
+// valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
+// /* EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); */
+// /* EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size()); */
+// /* EXPECT_EQ(20, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value); */
+//}
+//
+//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)});
+// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//
+// ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+// eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+// pullerManager);
+//
+// shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+// event1->write(1);
+// event1->write(10);
+// event1->init();
+// shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
+// event2->write(1);
+// event2->write(15);
+// event2->init();
+// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+// ValueMetricProducer::Interval curInterval;
+// curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+// EXPECT_EQ(10, curInterval.value.long_value);
+// EXPECT_EQ(true, curInterval.hasValue);
+// EXPECT_EQ(1, curInterval.sampleSize);
+//
+// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
+//
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+// curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+// EXPECT_EQ(25, curInterval.value.long_value);
+// EXPECT_EQ(2, curInterval.sampleSize);
+//
+// valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
+// EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
+// EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
+//
+// EXPECT_TRUE(std::abs(valueProducer.mPastBuckets.begin()->second.back().values[0].double_value -
+// 12.5) < epsilon);
+//}
+//
+//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)});
+// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//
+// ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+// eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+// pullerManager);
+//
+// shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+// event1->write(1);
+// event1->write(10);
+// event1->init();
+// shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
+// event2->write(1);
+// event2->write(15);
+// event2->init();
+// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+// ValueMetricProducer::Interval curInterval =
+// valueProducer.mCurrentSlicedBucket.begin()->second[0];
+// EXPECT_EQ(10, curInterval.value.long_value);
+// EXPECT_EQ(true, curInterval.hasValue);
+//
+// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
+//
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+// curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+// EXPECT_EQ(25, curInterval.value.long_value);
+//
+// valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
+// assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {25}, {bucketSizeNs});
+//}
+//
+//TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+// 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)});
+// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//
+// ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+// eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+// pullerManager);
+//
+// shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+// event1->write(1);
+// event1->write(10);
+// event1->init();
+// shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 15);
+// event2->write(1);
+// event2->write(15);
+// event2->init();
+// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+// ValueMetricProducer::Interval curInterval =
+// valueProducer.mCurrentSlicedBucket.begin()->second[0];
+// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(10, curBaseInfo.base.long_value);
+// EXPECT_EQ(false, curInterval.hasValue);
+//
+// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
+//
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+// curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+// EXPECT_EQ(true, curInterval.hasValue);
+// EXPECT_EQ(5, curInterval.value.long_value);
+//
+// // no change in data.
+// shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
+// event3->write(1);
+// event3->write(15);
+// event3->init();
+// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
+// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+// curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+// curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(15, curBaseInfo.base.long_value);
+// EXPECT_EQ(true, curInterval.hasValue);
+//
+// shared_ptr<LogEvent> event4 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 15);
+// event4->write(1);
+// event4->write(15);
+// event4->init();
+// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
+// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+// curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+// curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(15, curBaseInfo.base.long_value);
+// EXPECT_EQ(true, curInterval.hasValue);
+//
+// valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
+// EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
+// EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
+// assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {5}, {bucketSizeNs});
+//}
+//
+//TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+// metric.mutable_value_field()->add_child()->set_field(3);
+// 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)});
+// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//
+// ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+// eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+// pullerManager);
+//
+// shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+// event1->write(1);
+// event1->write(10);
+// event1->write(20);
+// event1->init();
+// shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 15);
+// event2->write(1);
+// event2->write(15);
+// event2->write(22);
+// event2->init();
+// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+// ValueMetricProducer::Interval curInterval =
+// valueProducer.mCurrentSlicedBucket.begin()->second[0];
+// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(10, curBaseInfo.base.long_value);
+// EXPECT_EQ(false, curInterval.hasValue);
+// curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(20, curBaseInfo.base.long_value);
+// EXPECT_EQ(false, curInterval.hasValue);
+//
+// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
+//
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+// curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+// curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[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];
+// EXPECT_EQ(true, curInterval.hasValue);
+// EXPECT_EQ(2, curInterval.value.long_value);
+//
+// // no change in first value field
+// shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
+// event3->write(1);
+// event3->write(15);
+// event3->write(25);
+// event3->init();
+// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
+// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+// curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+// curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[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];
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(25, curBaseInfo.base.long_value);
+// EXPECT_EQ(true, curInterval.hasValue);
+//
+// shared_ptr<LogEvent> event4 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 15);
+// event4->write(1);
+// event4->write(15);
+// event4->write(29);
+// event4->init();
+// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
+// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+// curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+// curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[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];
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(29, curBaseInfo.base.long_value);
+// EXPECT_EQ(true, curInterval.hasValue);
+//
+// valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
+//
+// EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
+// EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size());
+// EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second[0].values.size());
+// EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second[1].values.size());
+//
+// EXPECT_EQ(bucketSizeNs, valueProducer.mPastBuckets.begin()->second[0].mConditionTrueNs);
+// EXPECT_EQ(5, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
+// EXPECT_EQ(0, valueProducer.mPastBuckets.begin()->second[0].valueIndex[0]);
+// EXPECT_EQ(2, valueProducer.mPastBuckets.begin()->second[0].values[1].long_value);
+// EXPECT_EQ(1, valueProducer.mPastBuckets.begin()->second[0].valueIndex[1]);
+//
+// EXPECT_EQ(bucketSizeNs, valueProducer.mPastBuckets.begin()->second[1].mConditionTrueNs);
+// EXPECT_EQ(3, valueProducer.mPastBuckets.begin()->second[1].values[0].long_value);
+// EXPECT_EQ(1, valueProducer.mPastBuckets.begin()->second[1].valueIndex[0]);
+//}
+//
+///*
+// * Tests zero default base.
+// */
+//TEST(ValueMetricProducerTest, TestUseZeroDefaultBase) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+// metric.mutable_dimensions_in_what()->set_field(tagId);
+// metric.mutable_dimensions_in_what()->add_child()->set_field(1);
+// metric.set_use_zero_default_base(true);
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+// event->write(1);
+// event->write(3);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+//
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// auto iter = valueProducer->mCurrentSlicedBucket.begin();
+// auto& interval1 = iter->second[0];
+// auto iterBase = valueProducer->mCurrentBaseInfo.begin();
+// auto& baseInfo1 = iterBase->second[0];
+// EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+// EXPECT_EQ(true, baseInfo1.hasBase);
+// EXPECT_EQ(3, baseInfo1.base.long_value);
+// EXPECT_EQ(false, interval1.hasValue);
+// EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+// EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+// vector<shared_ptr<LogEvent>> allData;
+//
+// allData.clear();
+// shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+// event1->write(2);
+// event1->write(4);
+// event1->init();
+// shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+// event2->write(1);
+// event2->write(11);
+// event2->init();
+// allData.push_back(event1);
+// allData.push_back(event2);
+//
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+// EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+// EXPECT_EQ(true, baseInfo1.hasBase);
+// EXPECT_EQ(11, baseInfo1.base.long_value);
+// EXPECT_EQ(false, interval1.hasValue);
+// EXPECT_EQ(8, interval1.value.long_value);
+//
+// auto it = valueProducer->mCurrentSlicedBucket.begin();
+// for (; it != valueProducer->mCurrentSlicedBucket.end(); it++) {
+// if (it != iter) {
+// break;
+// }
+// }
+// auto itBase = valueProducer->mCurrentBaseInfo.begin();
+// for (; itBase != valueProducer->mCurrentBaseInfo.end(); it++) {
+// if (itBase != iterBase) {
+// break;
+// }
+// }
+// EXPECT_TRUE(it != iter);
+// EXPECT_TRUE(itBase != iterBase);
+// auto& interval2 = it->second[0];
+// auto& baseInfo2 = itBase->second[0];
+// EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+// EXPECT_EQ(true, baseInfo2.hasBase);
+// EXPECT_EQ(4, baseInfo2.base.long_value);
+// EXPECT_EQ(false, interval2.hasValue);
+// EXPECT_EQ(4, interval2.value.long_value);
+//
+// EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
+// auto iterator = valueProducer->mPastBuckets.begin();
+// EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs);
+// EXPECT_EQ(8, iterator->second[0].values[0].long_value);
+// iterator++;
+// EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs);
+// EXPECT_EQ(4, iterator->second[0].values[0].long_value);
+//}
+//
+///*
+// * Tests using zero default base with failed pull.
+// */
+//TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+// metric.mutable_dimensions_in_what()->set_field(tagId);
+// metric.mutable_dimensions_in_what()->add_child()->set_field(1);
+// metric.set_use_zero_default_base(true);
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+// event->write(1);
+// event->write(3);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+//
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// auto it = valueProducer->mCurrentSlicedBucket.begin();
+// auto& interval1 = it->second[0];
+// auto& baseInfo1 =
+// valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat())->second[0];
+// EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+// EXPECT_EQ(true, baseInfo1.hasBase);
+// EXPECT_EQ(3, baseInfo1.base.long_value);
+// EXPECT_EQ(false, interval1.hasValue);
+// EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+// EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+// vector<shared_ptr<LogEvent>> allData;
+//
+// allData.clear();
+// shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+// event1->write(2);
+// event1->write(4);
+// event1->init();
+// shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+// event2->write(1);
+// event2->write(11);
+// event2->init();
+// allData.push_back(event1);
+// allData.push_back(event2);
+//
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+// EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+// EXPECT_EQ(true, baseInfo1.hasBase);
+// EXPECT_EQ(11, baseInfo1.base.long_value);
+// EXPECT_EQ(false, interval1.hasValue);
+// EXPECT_EQ(8, interval1.value.long_value);
+//
+// auto it2 = valueProducer->mCurrentSlicedBucket.begin();
+// for (; it2 != valueProducer->mCurrentSlicedBucket.end(); it2++) {
+// if (it2 != it) {
+// break;
+// }
+// }
+// // auto itBase = valueProducer->mCurrentBaseInfo.begin();
+// // for (; itBase != valueProducer->mCurrentBaseInfo.end(); it++) {
+// // if (itBase != iterBase) {
+// // break;
+// // }
+// // }
+// EXPECT_TRUE(it2 != it);
+// // EXPECT_TRUE(itBase != iterBase);
+// auto& interval2 = it2->second[0];
+// auto& baseInfo2 =
+// valueProducer->mCurrentBaseInfo.find(it2->first.getDimensionKeyInWhat())->second[0];
+// EXPECT_EQ(2, it2->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+// EXPECT_EQ(true, baseInfo2.hasBase);
+// EXPECT_EQ(4, baseInfo2.base.long_value);
+// EXPECT_EQ(false, interval2.hasValue);
+// EXPECT_EQ(4, interval2.value.long_value);
+// EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
+//
+// // next pull somehow did not happen, skip to end of bucket 3
+// allData.clear();
+// event1 = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
+// event1->write(2);
+// event1->write(5);
+// event1->init();
+// allData.push_back(event1);
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+//
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// EXPECT_EQ(true, baseInfo2.hasBase);
+// EXPECT_EQ(5, baseInfo2.base.long_value);
+// EXPECT_EQ(false, interval2.hasValue);
+// EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+// EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
+//
+// allData.clear();
+// event1 = make_shared<LogEvent>(tagId, bucket5StartTimeNs + 1);
+// event1->write(2);
+// event1->write(13);
+// event1->init();
+// allData.push_back(event1);
+// event2 = make_shared<LogEvent>(tagId, bucket5StartTimeNs + 1);
+// event2->write(1);
+// event2->write(5);
+// event2->init();
+// allData.push_back(event2);
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
+//
+// EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+// it = valueProducer->mCurrentSlicedBucket.begin();
+// it2 = std::next(valueProducer->mCurrentSlicedBucket.begin());
+// interval1 = it->second[0];
+// interval2 = it2->second[0];
+// baseInfo1 = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat())->second[0];
+// baseInfo2 = valueProducer->mCurrentBaseInfo.find(it2->first.getDimensionKeyInWhat())->second[0];
+//
+// EXPECT_EQ(true, baseInfo1.hasBase);
+// EXPECT_EQ(5, baseInfo1.base.long_value);
+// EXPECT_EQ(false, interval1.hasValue);
+// EXPECT_EQ(5, interval1.value.long_value);
+// EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+//
+// EXPECT_EQ(true, baseInfo2.hasBase);
+// EXPECT_EQ(13, baseInfo2.base.long_value);
+// EXPECT_EQ(false, interval2.hasValue);
+// EXPECT_EQ(8, interval2.value.long_value);
+//
+// EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
+//}
+//
+///*
+// * Tests trim unused dimension key if no new data is seen in an entire bucket.
+// */
+//TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+// metric.mutable_dimensions_in_what()->set_field(tagId);
+// metric.mutable_dimensions_in_what()->add_child()->set_field(1);
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+// event->write(1);
+// event->write(3);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+//
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// auto iter = valueProducer->mCurrentSlicedBucket.begin();
+// auto& interval1 = iter->second[0];
+// auto iterBase = valueProducer->mCurrentBaseInfo.begin();
+// auto& baseInfo1 = iterBase->second[0];
+// EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+// EXPECT_EQ(true, baseInfo1.hasBase);
+// EXPECT_EQ(3, baseInfo1.base.long_value);
+// EXPECT_EQ(false, interval1.hasValue);
+// EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+// vector<shared_ptr<LogEvent>> allData;
+//
+// allData.clear();
+// shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+// event1->write(2);
+// event1->write(4);
+// event1->init();
+// shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+// event2->write(1);
+// event2->write(11);
+// event2->init();
+// allData.push_back(event1);
+// allData.push_back(event2);
+//
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+// EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+// EXPECT_EQ(true, baseInfo1.hasBase);
+// EXPECT_EQ(11, baseInfo1.base.long_value);
+// EXPECT_EQ(false, interval1.hasValue);
+// EXPECT_EQ(8, interval1.value.long_value);
+// EXPECT_FALSE(interval1.seenNewData);
+// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {8}, {bucketSizeNs});
+//
+// auto it = valueProducer->mCurrentSlicedBucket.begin();
+// for (; it != valueProducer->mCurrentSlicedBucket.end(); it++) {
+// if (it != iter) {
+// break;
+// }
+// }
+// auto itBase = valueProducer->mCurrentBaseInfo.begin();
+// for (; itBase != valueProducer->mCurrentBaseInfo.end(); it++) {
+// if (itBase != iterBase) {
+// break;
+// }
+// }
+// EXPECT_TRUE(it != iter);
+// EXPECT_TRUE(itBase != iterBase);
+// auto& interval2 = it->second[0];
+// auto& baseInfo2 = itBase->second[0];
+// EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+// EXPECT_EQ(true, baseInfo2.hasBase);
+// EXPECT_EQ(4, baseInfo2.base.long_value);
+// EXPECT_EQ(false, interval2.hasValue);
+// EXPECT_FALSE(interval2.seenNewData);
+// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {8}, {bucketSizeNs});
+//
+// // next pull somehow did not happen, skip to end of bucket 3
+// allData.clear();
+// event1 = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
+// event1->write(2);
+// event1->write(5);
+// event1->init();
+// allData.push_back(event1);
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+// // Only one interval left. One was trimmed.
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// interval2 = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// baseInfo2 = valueProducer->mCurrentBaseInfo.begin()->second[0];
+// EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+// EXPECT_EQ(true, baseInfo2.hasBase);
+// EXPECT_EQ(5, baseInfo2.base.long_value);
+// EXPECT_EQ(false, interval2.hasValue);
+// EXPECT_FALSE(interval2.seenNewData);
+// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {8}, {bucketSizeNs});
+//
+// allData.clear();
+// event1 = make_shared<LogEvent>(tagId, bucket5StartTimeNs + 1);
+// event1->write(2);
+// event1->write(14);
+// event1->init();
+// allData.push_back(event1);
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
+//
+// interval2 = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// baseInfo2 = valueProducer->mCurrentBaseInfo.begin()->second[0];
+// EXPECT_EQ(true, baseInfo2.hasBase);
+// EXPECT_EQ(14, baseInfo2.base.long_value);
+// EXPECT_EQ(false, interval2.hasValue);
+// EXPECT_FALSE(interval2.seenNewData);
+// ASSERT_EQ(2UL, valueProducer->mPastBuckets.size());
+// auto iterator = valueProducer->mPastBuckets.begin();
+// EXPECT_EQ(9, iterator->second[0].values[0].long_value);
+// EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs);
+// iterator++;
+// EXPECT_EQ(8, iterator->second[0].values[0].long_value);
+// EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs);
+//}
+//
+//TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange_EndOfBucket) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// // Used by onConditionChanged.
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
+// event->write(tagId);
+// event->write(100);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+// valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// ValueMetricProducer::Interval& curInterval =
+// valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// ValueMetricProducer::BaseInfo& curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(100, curBaseInfo.base.long_value);
+// EXPECT_EQ(false, curInterval.hasValue);
+//
+// vector<shared_ptr<LogEvent>> allData;
+// valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// EXPECT_EQ(false, curBaseInfo.hasBase);
+// EXPECT_EQ(false, curInterval.hasValue);
+// EXPECT_EQ(false, valueProducer->mHasGlobalBase);
+//}
+//
+//TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
+// event->write(tagId);
+// event->write(100);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// .WillOnce(Return(false));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+// valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
+//
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// ValueMetricProducer::Interval& curInterval =
+// valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// ValueMetricProducer::BaseInfo& curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(100, curBaseInfo.base.long_value);
+// EXPECT_EQ(false, curInterval.hasValue);
+// EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+//
+// valueProducer->onConditionChanged(false, bucketStartTimeNs + 20);
+//
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// EXPECT_EQ(false, curInterval.hasValue);
+// EXPECT_EQ(false, curBaseInfo.hasBase);
+// EXPECT_EQ(false, valueProducer->mHasGlobalBase);
+//}
+//
+//TEST(ValueMetricProducerTest, TestResetBaseOnPullFailBeforeConditionChange) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+// event->write(tagId);
+// event->write(50);
+// event->init();
+// data->push_back(event);
+// return false;
+// }))
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
+// event->write(tagId);
+// event->write(100);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+// // Don't directly set mCondition; the real code never does that. Go through regular code path
+// // to avoid unexpected behaviors.
+// // valueProducer->mCondition = ConditionState::kTrue;
+// valueProducer->onConditionChanged(true, bucketStartTimeNs);
+//
+// EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
+//
+// valueProducer->onConditionChanged(false, bucketStartTimeNs + 1);
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// ValueMetricProducer::Interval& curInterval =
+// valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+// EXPECT_EQ(false, curBaseInfo.hasBase);
+// EXPECT_EQ(false, curInterval.hasValue);
+// EXPECT_EQ(false, valueProducer->mHasGlobalBase);
+//}
+//
+//TEST(ValueMetricProducerTest, TestResetBaseOnPullDelayExceeded) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+// metric.set_condition(StringToId("SCREEN_ON"));
+// metric.set_max_pull_delay_sec(0);
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
+// event->write(tagId);
+// event->write(120);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+// valueProducer->mCondition = ConditionState::kFalse;
+//
+// // Max delay is set to 0 so pull will exceed max delay.
+// valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
+// EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
+//}
+//
+//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)});
+// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+// EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+//
+// ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
+// eventMatcherWizard, tagId, bucket2StartTimeNs,
+// bucket2StartTimeNs, pullerManager);
+// valueProducer.mCondition = ConditionState::kFalse;
+//
+// // Event should be skipped since it is from previous bucket.
+// // Pull should not be called.
+// valueProducer.onConditionChanged(true, bucketStartTimeNs);
+// EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
+//}
+//
+//TEST(ValueMetricProducerTest, TestBaseSetOnConditionChange) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
+// event->write(tagId);
+// event->write(100);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+// valueProducer->mCondition = ConditionState::kFalse;
+// valueProducer->mHasGlobalBase = false;
+//
+// valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
+// valueProducer->mHasGlobalBase = true;
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// ValueMetricProducer::Interval& curInterval =
+// valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(100, curBaseInfo.base.long_value);
+// EXPECT_EQ(false, curInterval.hasValue);
+// EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+//}
+//
+///*
+// * Tests that a bucket is marked invalid when a condition change pull fails.
+// */
+//TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenOneConditionFailed) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // First onConditionChanged
+// .WillOnce(Return(false))
+// // Second onConditionChanged
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
+// event->write(tagId);
+// event->write(130);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+// valueProducer->mCondition = ConditionState::kTrue;
+//
+// // Bucket start.
+// vector<shared_ptr<LogEvent>> allData;
+// allData.clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
+// event->write(1);
+// event->write(110);
+// event->init();
+// allData.push_back(event);
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
+//
+// // This will fail and should invalidate the whole bucket since we do not have all the data
+// // needed to compute the metric value when the screen was on.
+// valueProducer->onConditionChanged(false, bucketStartTimeNs + 2);
+// valueProducer->onConditionChanged(true, bucketStartTimeNs + 3);
+//
+// // Bucket end.
+// allData.clear();
+// shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+// event2->write(1);
+// event2->write(140);
+// event2->init();
+// allData.push_back(event2);
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//
+// valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
+//
+// EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+// // Contains base from last pull which was successful.
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// ValueMetricProducer::Interval& curInterval =
+// valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(140, curBaseInfo.base.long_value);
+// EXPECT_EQ(false, curInterval.hasValue);
+// EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+//
+// // Check dump report.
+// ProtoOutputStream output;
+// std::set<string> strSet;
+// valueProducer->onDumpReport(bucket2StartTimeNs + 10, false /* include partial bucket */, true,
+// FAST /* dumpLatency */, &strSet, &output);
+//
+// StatsLogReport report = outputStreamToProto(&output);
+// EXPECT_TRUE(report.has_value_metrics());
+// EXPECT_EQ(0, report.value_metrics().data_size());
+// EXPECT_EQ(1, report.value_metrics().skipped_size());
+//
+// EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+// report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+// EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
+// report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+// EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+//
+// auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+// EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+// EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 2), dropEvent.drop_time_millis());
+//}
+//
+///*
+// * Tests that a bucket is marked invalid when the guardrail is hit.
+// */
+//TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenGuardRailHit) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+// metric.mutable_dimensions_in_what()->set_field(tagId);
+// metric.mutable_dimensions_in_what()->add_child()->set_field(1);
+// metric.set_condition(StringToId("SCREEN_ON"));
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // First onConditionChanged
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// for (int i = 0; i < 2000; i++) {
+// shared_ptr<LogEvent> event =
+// make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
+// event->write(i);
+// event->write(i);
+// event->init();
+// data->push_back(event);
+// }
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+// valueProducer->mCondition = ConditionState::kFalse;
+//
+// valueProducer->onConditionChanged(true, bucketStartTimeNs + 2);
+// EXPECT_EQ(true, valueProducer->mCurrentBucketIsInvalid);
+// EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
+// EXPECT_EQ(0UL, valueProducer->mSkippedBuckets.size());
+//
+// // Bucket 2 start.
+// vector<shared_ptr<LogEvent>> allData;
+// allData.clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+// event->write(1);
+// event->write(10);
+// event->init();
+// allData.push_back(event);
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//
+// // First bucket added to mSkippedBuckets after flush.
+// EXPECT_EQ(1UL, valueProducer->mSkippedBuckets.size());
+//
+// // Check dump report.
+// ProtoOutputStream output;
+// std::set<string> strSet;
+// valueProducer->onDumpReport(bucket2StartTimeNs + 10000, false /* include recent buckets */,
+// true, FAST /* dumpLatency */, &strSet, &output);
+//
+// StatsLogReport report = outputStreamToProto(&output);
+// EXPECT_TRUE(report.has_value_metrics());
+// EXPECT_EQ(0, report.value_metrics().data_size());
+// EXPECT_EQ(1, report.value_metrics().skipped_size());
+//
+// EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+// report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+// EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
+// report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+// EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+//
+// auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+// EXPECT_EQ(BucketDropReason::DIMENSION_GUARDRAIL_REACHED, dropEvent.drop_reason());
+// EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 2), dropEvent.drop_time_millis());
+//}
+//
+///*
+// * Tests that a bucket is marked invalid when the bucket's initial pull fails.
+// */
+//TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenInitialPullFailed) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // First onConditionChanged
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
+// event->write(tagId);
+// event->write(120);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// // Second onConditionChanged
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
+// event->write(tagId);
+// event->write(130);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+// valueProducer->mCondition = ConditionState::kTrue;
+//
+// // Bucket start.
+// vector<shared_ptr<LogEvent>> allData;
+// allData.clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
+// event->write(1);
+// event->write(110);
+// event->init();
+// allData.push_back(event);
+// valueProducer->onDataPulled(allData, /** succeed */ false, bucketStartTimeNs);
+//
+// valueProducer->onConditionChanged(false, bucketStartTimeNs + 2);
+// valueProducer->onConditionChanged(true, bucketStartTimeNs + 3);
+//
+// // Bucket end.
+// allData.clear();
+// shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+// event2->write(1);
+// event2->write(140);
+// event2->init();
+// allData.push_back(event2);
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//
+// valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
+//
+// EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+// // Contains base from last pull which was successful.
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// ValueMetricProducer::Interval& curInterval =
+// valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(140, curBaseInfo.base.long_value);
+// EXPECT_EQ(false, curInterval.hasValue);
+// EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+//
+// // Check dump report.
+// ProtoOutputStream output;
+// std::set<string> strSet;
+// valueProducer->onDumpReport(bucket2StartTimeNs + 10000, false /* include recent buckets */,
+// true, FAST /* dumpLatency */, &strSet, &output);
+//
+// StatsLogReport report = outputStreamToProto(&output);
+// EXPECT_TRUE(report.has_value_metrics());
+// EXPECT_EQ(0, report.value_metrics().data_size());
+// EXPECT_EQ(1, report.value_metrics().skipped_size());
+//
+// EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+// report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+// EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
+// report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+// EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+//
+// auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+// EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+// EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 2), dropEvent.drop_time_millis());
+//}
+//
+///*
+// * Tests that a bucket is marked invalid when the bucket's final pull fails
+// * (i.e. failed pull on bucket boundary).
+// */
+//TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenLastPullFailed) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // First onConditionChanged
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
+// event->write(tagId);
+// event->write(120);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// // Second onConditionChanged
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
+// event->write(tagId);
+// event->write(130);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+// valueProducer->mCondition = ConditionState::kTrue;
+//
+// // Bucket start.
+// vector<shared_ptr<LogEvent>> allData;
+// allData.clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
+// event->write(1);
+// event->write(110);
+// event->init();
+// allData.push_back(event);
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
+//
+// valueProducer->onConditionChanged(false, bucketStartTimeNs + 2);
+// valueProducer->onConditionChanged(true, bucketStartTimeNs + 3);
+//
+// // Bucket end.
+// allData.clear();
+// shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+// event2->write(1);
+// event2->write(140);
+// event2->init();
+// allData.push_back(event2);
+// valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
+//
+// valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
+//
+// EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+// // Last pull failed so base has been reset.
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// ValueMetricProducer::Interval& curInterval =
+// valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+// EXPECT_EQ(false, curBaseInfo.hasBase);
+// EXPECT_EQ(false, curInterval.hasValue);
+// EXPECT_EQ(false, valueProducer->mHasGlobalBase);
+//
+// // Check dump report.
+// ProtoOutputStream output;
+// std::set<string> strSet;
+// valueProducer->onDumpReport(bucket2StartTimeNs + 10000, false /* include recent buckets */,
+// true, FAST /* dumpLatency */, &strSet, &output);
+//
+// StatsLogReport report = outputStreamToProto(&output);
+// EXPECT_TRUE(report.has_value_metrics());
+// EXPECT_EQ(0, report.value_metrics().data_size());
+// EXPECT_EQ(1, report.value_metrics().skipped_size());
+//
+// EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+// report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+// EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
+// report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+// EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+//
+// auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+// EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+// EXPECT_EQ(NanoToMillis(bucket2StartTimeNs), dropEvent.drop_time_millis());
+//}
+//
+//TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onDataPulled) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // Start bucket.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+// event->write(tagId);
+// event->write(3);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+//
+// // Bucket 2 start.
+// vector<shared_ptr<LogEvent>> allData;
+// allData.clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+// event->write(tagId);
+// event->write(110);
+// event->init();
+// allData.push_back(event);
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+//
+// // Bucket 3 empty.
+// allData.clear();
+// shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
+// event2->init();
+// allData.push_back(event2);
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+// // Data has been trimmed.
+// EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
+// EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+//}
+//
+//TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onConditionChanged) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // First onConditionChanged
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+// event->write(tagId);
+// event->write(3);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+// valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// ValueMetricProducer::Interval& curInterval =
+// valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(false, curInterval.hasValue);
+// EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+//
+// // Empty pull.
+// valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+// EXPECT_EQ(false, curBaseInfo.hasBase);
+// EXPECT_EQ(false, curInterval.hasValue);
+// EXPECT_EQ(false, valueProducer->mHasGlobalBase);
+//}
+//
+//TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onBucketBoundary) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // First onConditionChanged
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+// event->write(tagId);
+// event->write(1);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+// event->write(tagId);
+// event->write(2);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+// event->write(tagId);
+// event->write(5);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+// valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
+// valueProducer->onConditionChanged(false, bucketStartTimeNs + 11);
+// valueProducer->onConditionChanged(true, bucketStartTimeNs + 12);
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// ValueMetricProducer::Interval& curInterval =
+// valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(true, curInterval.hasValue);
+// EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+//
+// // End of bucket
+// vector<shared_ptr<LogEvent>> allData;
+// allData.clear();
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+// // Data is empty, base should be reset.
+// EXPECT_EQ(false, curBaseInfo.hasBase);
+// EXPECT_EQ(5, curBaseInfo.base.long_value);
+// EXPECT_EQ(false, curInterval.hasValue);
+// EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+//
+// EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {1}, {bucketSizeNs - 12 + 1});
+//}
+//
+//TEST(ValueMetricProducerTest, TestPartialResetOnBucketBoundaries) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+// metric.mutable_dimensions_in_what()->set_field(tagId);
+// metric.mutable_dimensions_in_what()->add_child()->set_field(1);
+// metric.set_condition(StringToId("SCREEN_ON"));
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // First onConditionChanged
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+// event->write(tagId);
+// event->write(1);
+// event->write(1);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+// valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//
+// // End of bucket
+// vector<shared_ptr<LogEvent>> allData;
+// allData.clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+// event->write(2);
+// event->write(2);
+// event->init();
+// allData.push_back(event);
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//
+// // Key 1 should be reset since in not present in the most pull.
+// EXPECT_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);
+// 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(true, valueProducer->mHasGlobalBase);
+//}
+//
+//TEST(ValueMetricProducerTest, TestFullBucketResetWhenLastBucketInvalid) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // Initialization.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
+// return true;
+// }))
+// // notifyAppUpgrade.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// data->push_back(ValueMetricProducerTestHelper::createEvent(
+// bucketStartTimeNs + bucketSizeNs / 2, 10));
+// return true;
+// }));
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+// ASSERT_EQ(0UL, valueProducer->mCurrentFullBucket.size());
+//
+// valueProducer->notifyAppUpgrade(bucketStartTimeNs + bucketSizeNs / 2, "com.foo", 10000, 1);
+// ASSERT_EQ(1UL, valueProducer->mCurrentFullBucket.size());
+//
+// vector<shared_ptr<LogEvent>> allData;
+// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket3StartTimeNs + 1, 4));
+// valueProducer->onDataPulled(allData, /** fails */ false, bucket3StartTimeNs + 1);
+// ASSERT_EQ(0UL, valueProducer->mCurrentFullBucket.size());
+//}
+//
+//TEST(ValueMetricProducerTest, TestBucketBoundariesOnConditionChange) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // Second onConditionChanged.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// data->push_back(
+// ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 10, 5));
+// return true;
+// }))
+// // Third onConditionChanged.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// data->push_back(
+// ValueMetricProducerTestHelper::createEvent(bucket3StartTimeNs + 10, 7));
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+// valueProducer->mCondition = ConditionState::kUnknown;
+//
+// valueProducer->onConditionChanged(false, bucketStartTimeNs);
+// ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
+//
+// // End of first bucket
+// vector<shared_ptr<LogEvent>> allData;
+// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 1, 4));
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 1);
+// ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
+//
+// 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];
+// EXPECT_EQ(true, curBaseInfo.hasBase);
+// EXPECT_EQ(5, curBaseInfo.base.long_value);
+// EXPECT_EQ(false, curInterval.hasValue);
+//
+// valueProducer->onConditionChanged(false, bucket3StartTimeNs + 10);
+//
+// // Bucket should have been completed.
+// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {2}, {bucketSizeNs - 10});
+//}
+//
+//TEST(ValueMetricProducerTest, TestLateOnDataPulledWithoutDiff) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+// metric.set_use_diff(false);
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+//
+// vector<shared_ptr<LogEvent>> allData;
+// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + 30);
+//
+// allData.clear();
+// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 20));
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//
+// // Bucket should have been completed.
+// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {30}, {bucketSizeNs});
+//}
+//
+//TEST(ValueMetricProducerTest, TestLateOnDataPulledWithDiff) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // Initialization.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+//
+// vector<shared_ptr<LogEvent>> allData;
+// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + 30);
+//
+// allData.clear();
+// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 20));
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//
+// // Bucket should have been completed.
+// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {19}, {bucketSizeNs});
+//}
+//
+//TEST(ValueMetricProducerTest, TestBucketBoundariesOnAppUpgrade) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // Initialization.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
+// return true;
+// }))
+// // notifyAppUpgrade.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// data->push_back(
+// ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 2, 10));
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+//
+// valueProducer->notifyAppUpgrade(bucket2StartTimeNs + 2, "com.foo", 10000, 1);
+//
+// // Bucket should have been completed.
+// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {9}, {bucketSizeNs});
+//}
+//
+//TEST(ValueMetricProducerTest, TestDataIsNotUpdatedWhenNoConditionChanged) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // First on condition changed.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
+// return true;
+// }))
+// // Second on condition changed.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 3));
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+// valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
+// valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
+// valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
+//
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// auto curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+// EXPECT_EQ(true, curInterval.hasValue);
+// EXPECT_EQ(2, curInterval.value.long_value);
+//
+// vector<shared_ptr<LogEvent>> allData;
+// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 1, 10));
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 1);
+//
+// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {2}, {2});
+//}
+//
+//// TODO: b/145705635 fix or delete this test
+//TEST(ValueMetricProducerTest, TestBucketInvalidIfGlobalBaseIsNotSet) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // First condition change.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
+// return true;
+// }))
+// // 2nd condition change.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// data->push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 1));
+// return true;
+// }))
+// // 3rd condition change.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// data->push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 1));
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+// valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
+//
+// vector<shared_ptr<LogEvent>> allData;
+// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 3, 10));
+// valueProducer->onDataPulled(allData, /** succeed */ false, bucketStartTimeNs + 3);
+//
+// allData.clear();
+// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 20));
+// valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
+//
+// valueProducer->onConditionChanged(false, bucket2StartTimeNs + 8);
+// valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
+//
+// allData.clear();
+// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket3StartTimeNs, 30));
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//
+// // There was not global base available so all buckets are invalid.
+// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {});
+//}
+//
+//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)});
+// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+// EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+//
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // Initial pull.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+// event->write(tagId);
+// event->write(1);
+// event->write(1);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+// eventMatcherWizard, tagId, bucketStartTimeNs,
+// bucketStartTimeNs, pullerManager);
+//
+// ProtoOutputStream output;
+// std::set<string> strSet;
+// valueProducer.onDumpReport(bucketStartTimeNs + 10, true /* include recent buckets */, true,
+// FAST, &strSet, &output);
+//
+// StatsLogReport report = outputStreamToProto(&output);
+// // Bucket is invalid since we did not pull when dump report was called.
+// EXPECT_EQ(0, report.value_metrics().data_size());
+//}
+//
+//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)});
+// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+// EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+//
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // Initial pull.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+// event->write(tagId);
+// event->write(1);
+// event->write(1);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+// eventMatcherWizard, tagId, bucketStartTimeNs,
+// bucketStartTimeNs, pullerManager);
+//
+// vector<shared_ptr<LogEvent>> allData;
+// allData.clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+// event->write(tagId);
+// event->write(2);
+// event->write(2);
+// event->init();
+// allData.push_back(event);
+// valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//
+// ProtoOutputStream output;
+// std::set<string> strSet;
+// valueProducer.onDumpReport(bucket4StartTimeNs, false /* include recent buckets */, true, FAST,
+// &strSet, &output);
+//
+// StatsLogReport report = outputStreamToProto(&output);
+// // Previous bucket is part of the report.
+// EXPECT_EQ(1, report.value_metrics().data_size());
+// EXPECT_EQ(0, report.value_metrics().data(0).bucket_info(0).bucket_num());
+//}
+//
+//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)});
+// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+// EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+//
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // Initial pull.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+// event->write(tagId);
+// event->write(1);
+// event->write(1);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+// event->write(tagId);
+// event->write(3);
+// event->write(3);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+// eventMatcherWizard, tagId, bucketStartTimeNs,
+// bucketStartTimeNs, pullerManager);
+//
+// ProtoOutputStream output;
+// std::set<string> strSet;
+// valueProducer.onDumpReport(bucketStartTimeNs + 10, true /* include recent buckets */, true,
+// NO_TIME_CONSTRAINTS, &strSet, &output);
+//
+// StatsLogReport report = outputStreamToProto(&output);
+// EXPECT_EQ(1, report.value_metrics().data_size());
+// EXPECT_EQ(1, report.value_metrics().data(0).bucket_info_size());
+// EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
+//}
+//
+//TEST(ValueMetricProducerTest, TestPulledData_noDiff_withoutCondition) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+// metric.set_use_diff(false);
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+//
+// vector<shared_ptr<LogEvent>> allData;
+// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 10));
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 30);
+//
+// // Bucket should have been completed.
+// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs});
+//}
+//
+//TEST(ValueMetricProducerTest, TestPulledData_noDiff_withMultipleConditionChanges) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+// metric.set_use_diff(false);
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // condition becomes true
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// data->push_back(
+// ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
+// return true;
+// }))
+// // condition becomes false
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// data->push_back(
+// ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 50, 20));
+// return true;
+// }));
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+// valueProducer->mCondition = ConditionState::kFalse;
+//
+// valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
+// valueProducer->onConditionChanged(false, bucketStartTimeNs + 50);
+// // has one slice
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// ValueMetricProducer::Interval curInterval =
+// valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+// EXPECT_EQ(false, curBaseInfo.hasBase);
+// EXPECT_EQ(true, curInterval.hasValue);
+// EXPECT_EQ(20, curInterval.value.long_value);
+//
+// // Now the alarm is delivered. Condition is off though.
+// vector<shared_ptr<LogEvent>> allData;
+// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 110));
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//
+// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {50 - 8});
+// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+// EXPECT_EQ(false, curBaseInfo.hasBase);
+// EXPECT_EQ(false, curInterval.hasValue);
+//}
+//
+//TEST(ValueMetricProducerTest, TestPulledData_noDiff_bucketBoundaryTrue) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+// metric.set_use_diff(false);
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // condition becomes true
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// data->push_back(
+// ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
+// return true;
+// }));
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+// valueProducer->mCondition = ConditionState::kFalse;
+//
+// valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
+//
+// // Now the alarm is delivered. Condition is off though.
+// vector<shared_ptr<LogEvent>> allData;
+// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 30));
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//
+// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {30}, {bucketSizeNs - 8});
+// ValueMetricProducer::Interval curInterval =
+// valueProducer->mCurrentSlicedBucket.begin()->second[0];
+// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+// EXPECT_EQ(false, curBaseInfo.hasBase);
+// EXPECT_EQ(false, curInterval.hasValue);
+//}
+//
+//TEST(ValueMetricProducerTest, TestPulledData_noDiff_bucketBoundaryFalse) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+// metric.set_use_diff(false);
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+// valueProducer->mCondition = ConditionState::kFalse;
+//
+// // Now the alarm is delivered. Condition is off though.
+// vector<shared_ptr<LogEvent>> allData;
+// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 30));
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//
+// // Condition was always false.
+// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {});
+//}
+//
+//TEST(ValueMetricProducerTest, TestPulledData_noDiff_withFailure) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+// metric.set_use_diff(false);
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // condition becomes true
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// data->push_back(
+// ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
+// return true;
+// }))
+// .WillOnce(Return(false));
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+// valueProducer->mCondition = ConditionState::kFalse;
+//
+// valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
+// valueProducer->onConditionChanged(false, bucketStartTimeNs + 50);
+//
+// // Now the alarm is delivered. Condition is off though.
+// vector<shared_ptr<LogEvent>> allData;
+// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 30));
+// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//
+// // No buckets, we had a failure.
+// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {});
+//}
+//
+///*
+// * Test that DUMP_REPORT_REQUESTED dump reason is logged.
+// *
+// * For the bucket to be marked invalid during a dump report requested,
+// * three things must be true:
+// * - we want to include the current partial bucket
+// * - we need a pull (metric is pulled and condition is true)
+// * - the dump latency must be FAST
+// */
+//
+//TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenDumpReportRequested) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // Condition change to true.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
+// event->write("field1");
+// event->write(10);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+// // Condition change event.
+// valueProducer->onConditionChanged(true, bucketStartTimeNs + 20);
+//
+// // Check dump report.
+// ProtoOutputStream output;
+// std::set<string> strSet;
+// valueProducer->onDumpReport(bucketStartTimeNs + 40, true /* include recent buckets */, true,
+// FAST /* dumpLatency */, &strSet, &output);
+//
+// StatsLogReport report = outputStreamToProto(&output);
+// EXPECT_TRUE(report.has_value_metrics());
+// EXPECT_EQ(0, report.value_metrics().data_size());
+// EXPECT_EQ(1, report.value_metrics().skipped_size());
+//
+// EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+// report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+// EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 40),
+// report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+// EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+//
+// auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+// EXPECT_EQ(BucketDropReason::DUMP_REPORT_REQUESTED, dropEvent.drop_reason());
+// EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 40), dropEvent.drop_time_millis());
+//}
+//
+///*
+// * Test that EVENT_IN_WRONG_BUCKET dump reason is logged for a late condition
+// * change event (i.e. the condition change occurs in the wrong bucket).
+// */
+//TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenConditionEventWrongBucket) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // Condition change to true.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
+// event->write("field1");
+// event->write(10);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+// // Condition change event.
+// valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
+//
+// // Bucket boundary pull.
+// vector<shared_ptr<LogEvent>> allData;
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs);
+// event->write("field1");
+// event->write(15);
+// event->init();
+// allData.push_back(event);
+// valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
+//
+// // Late condition change event.
+// valueProducer->onConditionChanged(false, bucket2StartTimeNs - 100);
+//
+// // Check dump report.
+// ProtoOutputStream output;
+// std::set<string> strSet;
+// valueProducer->onDumpReport(bucket2StartTimeNs + 100, true /* include recent buckets */, true,
+// NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
+//
+// StatsLogReport report = outputStreamToProto(&output);
+// EXPECT_TRUE(report.has_value_metrics());
+// EXPECT_EQ(1, report.value_metrics().data_size());
+// EXPECT_EQ(1, report.value_metrics().skipped_size());
+//
+// EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
+// report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+// EXPECT_EQ(NanoToMillis(bucket2StartTimeNs + 100),
+// report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+// EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+//
+// auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+// EXPECT_EQ(BucketDropReason::EVENT_IN_WRONG_BUCKET, dropEvent.drop_reason());
+// EXPECT_EQ(NanoToMillis(bucket2StartTimeNs - 100), dropEvent.drop_time_millis());
+//}
+//
+///*
+// * Test that EVENT_IN_WRONG_BUCKET dump reason is logged for a late accumulate
+// * event (i.e. the accumulate events call occurs in the wrong bucket).
+// */
+//TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenAccumulateEventWrongBucket) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // Condition change to true.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
+// event->write("field1");
+// event->write(10);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// // Dump report requested.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 100);
+// event->write("field1");
+// event->write(15);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+// // Condition change event.
+// valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
+//
+// // Bucket boundary pull.
+// vector<shared_ptr<LogEvent>> allData;
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs);
+// event->write("field1");
+// event->write(15);
+// event->init();
+// allData.push_back(event);
+// valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
+//
+// allData.clear();
+// event = make_shared<LogEvent>(tagId, bucket2StartTimeNs - 100);
+// event->write("field1");
+// event->write(20);
+// event->init();
+// allData.push_back(event);
+//
+// // Late accumulateEvents event.
+// valueProducer->accumulateEvents(allData, bucket2StartTimeNs - 100, bucket2StartTimeNs - 100);
+//
+// // Check dump report.
+// ProtoOutputStream output;
+// std::set<string> strSet;
+// valueProducer->onDumpReport(bucket2StartTimeNs + 100, true /* include recent buckets */, true,
+// NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
+//
+// StatsLogReport report = outputStreamToProto(&output);
+// EXPECT_TRUE(report.has_value_metrics());
+// EXPECT_EQ(1, report.value_metrics().data_size());
+// EXPECT_EQ(1, report.value_metrics().skipped_size());
+//
+// EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
+// report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+// EXPECT_EQ(NanoToMillis(bucket2StartTimeNs + 100),
+// report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+// EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+//
+// auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+// EXPECT_EQ(BucketDropReason::EVENT_IN_WRONG_BUCKET, dropEvent.drop_reason());
+// EXPECT_EQ(NanoToMillis(bucket2StartTimeNs - 100), dropEvent.drop_time_millis());
+//}
+//
+///*
+// * Test that CONDITION_UNKNOWN dump reason is logged due to an unknown condition
+// * when a metric is initialized.
+// */
+//TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenConditionUnknown) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // Condition change to true.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
+// event->write("field1");
+// event->write(10);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// // Dump report requested.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 100);
+// event->write("field1");
+// event->write(15);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithNoInitialCondition(pullerManager,
+// metric);
+//
+// // Condition change event.
+// valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
+//
+// // Check dump report.
+// ProtoOutputStream output;
+// std::set<string> strSet;
+// int64_t dumpReportTimeNs = bucketStartTimeNs + 10000;
+// valueProducer->onDumpReport(dumpReportTimeNs, true /* include recent buckets */, true,
+// NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
+//
+// StatsLogReport report = outputStreamToProto(&output);
+// EXPECT_TRUE(report.has_value_metrics());
+// EXPECT_EQ(0, report.value_metrics().data_size());
+// EXPECT_EQ(1, report.value_metrics().skipped_size());
+//
+// EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+// report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+// EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
+// report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+// EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+//
+// auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+// EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
+// EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
+//}
+//
+///*
+// * Test that PULL_FAILED dump reason is logged due to a pull failure in
+// * #pullAndMatchEventsLocked.
+// */
+//TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenPullFailed) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // Condition change to true.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
+// event->write("field1");
+// event->write(10);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// // Dump report requested, pull fails.
+// .WillOnce(Return(false));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+// // Condition change event.
+// valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
+//
+// // Check dump report.
+// ProtoOutputStream output;
+// std::set<string> strSet;
+// int64_t dumpReportTimeNs = bucketStartTimeNs + 10000;
+// valueProducer->onDumpReport(dumpReportTimeNs, true /* include recent buckets */, true,
+// NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
+//
+// StatsLogReport report = outputStreamToProto(&output);
+// EXPECT_TRUE(report.has_value_metrics());
+// EXPECT_EQ(0, report.value_metrics().data_size());
+// EXPECT_EQ(1, report.value_metrics().skipped_size());
+//
+// EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+// report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+// EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
+// report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+// EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+//
+// auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+// EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+// EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
+//}
+//
+///*
+// * Test that MULTIPLE_BUCKETS_SKIPPED dump reason is logged when a log event
+// * skips over more than one bucket.
+// */
+//TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenMultipleBucketsSkipped) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // Condition change to true.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+// event->write("field1");
+// event->write(10);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// // Dump report requested.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event =
+// make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1000);
+// event->write("field1");
+// event->write(15);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+// // Condition change event.
+// valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
+//
+// // Condition change event that skips forward by three buckets.
+// valueProducer->onConditionChanged(false, bucket4StartTimeNs + 10);
+//
+// // Check dump report.
+// ProtoOutputStream output;
+// std::set<string> strSet;
+// valueProducer->onDumpReport(bucket4StartTimeNs + 1000, true /* include recent buckets */, true,
+// NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
+//
+// StatsLogReport report = outputStreamToProto(&output);
+// EXPECT_TRUE(report.has_value_metrics());
+// EXPECT_EQ(0, report.value_metrics().data_size());
+// EXPECT_EQ(1, report.value_metrics().skipped_size());
+//
+// EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+// report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+// EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
+// report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+// EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+//
+// auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+// EXPECT_EQ(BucketDropReason::MULTIPLE_BUCKETS_SKIPPED, dropEvent.drop_reason());
+// EXPECT_EQ(NanoToMillis(bucket4StartTimeNs + 10), dropEvent.drop_time_millis());
+//}
+//
+///*
+// * Test that BUCKET_TOO_SMALL dump reason is logged when a flushed bucket size
+// * is smaller than the "min_bucket_size_nanos" specified in the metric config.
+// */
+//TEST(ValueMetricProducerTest_BucketDrop, TestBucketDropWhenBucketTooSmall) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+// metric.set_min_bucket_size_nanos(10000000000); // 10 seconds
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // Condition change to true.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+// event->write("field1");
+// event->write(10);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// // Dump report requested.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event =
+// make_shared<LogEvent>(tagId, bucketStartTimeNs + 9000000);
+// event->write("field1");
+// event->write(15);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+// // Condition change event.
+// valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
+//
+// // Check dump report.
+// ProtoOutputStream output;
+// std::set<string> strSet;
+// int64_t dumpReportTimeNs = bucketStartTimeNs + 9000000;
+// valueProducer->onDumpReport(dumpReportTimeNs, true /* include recent buckets */, true,
+// NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
+//
+// StatsLogReport report = outputStreamToProto(&output);
+// EXPECT_TRUE(report.has_value_metrics());
+// EXPECT_EQ(0, report.value_metrics().data_size());
+// EXPECT_EQ(1, report.value_metrics().skipped_size());
+//
+// EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+// report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+// EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
+// report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+// EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+//
+// auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+// EXPECT_EQ(BucketDropReason::BUCKET_TOO_SMALL, dropEvent.drop_reason());
+// EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
+//}
+//
+///*
+// * Test multiple bucket drop events in the same bucket.
+// */
+//TEST(ValueMetricProducerTest_BucketDrop, TestMultipleBucketDropEvents) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // Condition change to true.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+// event->write("field1");
+// event->write(10);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithNoInitialCondition(pullerManager,
+// metric);
+//
+// // Condition change event.
+// valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
+//
+// // Check dump report.
+// ProtoOutputStream output;
+// std::set<string> strSet;
+// int64_t dumpReportTimeNs = bucketStartTimeNs + 1000;
+// valueProducer->onDumpReport(dumpReportTimeNs, true /* include recent buckets */, true,
+// FAST /* dumpLatency */, &strSet, &output);
+//
+// StatsLogReport report = outputStreamToProto(&output);
+// EXPECT_TRUE(report.has_value_metrics());
+// EXPECT_EQ(0, report.value_metrics().data_size());
+// EXPECT_EQ(1, report.value_metrics().skipped_size());
+//
+// EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+// report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+// EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
+// report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+// EXPECT_EQ(2, report.value_metrics().skipped(0).drop_event_size());
+//
+// auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+// EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
+// EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 10), dropEvent.drop_time_millis());
+//
+// dropEvent = report.value_metrics().skipped(0).drop_event(1);
+// EXPECT_EQ(BucketDropReason::DUMP_REPORT_REQUESTED, dropEvent.drop_reason());
+// EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
+//}
+//
+///*
+// * Test that the number of logged bucket drop events is capped at the maximum.
+// * The maximum is currently 10 and is set in MetricProducer::maxDropEventsReached().
+// */
+//TEST(ValueMetricProducerTest_BucketDrop, TestMaxBucketDropEvents) {
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // First condition change event.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// for (int i = 0; i < 2000; i++) {
+// shared_ptr<LogEvent> event =
+// make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
+// event->write(i);
+// event->write(i);
+// event->init();
+// data->push_back(event);
+// }
+// return true;
+// }))
+// .WillOnce(Return(false))
+// .WillOnce(Return(false))
+// .WillOnce(Return(false))
+// .WillOnce(Return(false))
+// .WillOnce(Return(false))
+// .WillOnce(Return(false))
+// .WillOnce(Return(false))
+// .WillOnce(Return(false))
+// .WillOnce(Return(false))
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 220);
+// event->write("field1");
+// event->write(10);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithNoInitialCondition(pullerManager,
+// metric);
+//
+// // First condition change event causes guardrail to be reached.
+// valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
+//
+// // 2-10 condition change events result in failed pulls.
+// valueProducer->onConditionChanged(false, bucketStartTimeNs + 30);
+// valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
+// valueProducer->onConditionChanged(false, bucketStartTimeNs + 70);
+// valueProducer->onConditionChanged(true, bucketStartTimeNs + 90);
+// valueProducer->onConditionChanged(false, bucketStartTimeNs + 100);
+// valueProducer->onConditionChanged(true, bucketStartTimeNs + 150);
+// valueProducer->onConditionChanged(false, bucketStartTimeNs + 170);
+// valueProducer->onConditionChanged(true, bucketStartTimeNs + 190);
+// valueProducer->onConditionChanged(false, bucketStartTimeNs + 200);
+//
+// // Condition change event 11
+// valueProducer->onConditionChanged(true, bucketStartTimeNs + 220);
+//
+// // Check dump report.
+// ProtoOutputStream output;
+// std::set<string> strSet;
+// int64_t dumpReportTimeNs = bucketStartTimeNs + 1000;
+// // Because we already have 10 dump events in the current bucket,
+// // this case should not be added to the list of dump events.
+// valueProducer->onDumpReport(bucketStartTimeNs + 1000, true /* include recent buckets */, true,
+// FAST /* dumpLatency */, &strSet, &output);
+//
+// StatsLogReport report = outputStreamToProto(&output);
+// EXPECT_TRUE(report.has_value_metrics());
+// EXPECT_EQ(0, report.value_metrics().data_size());
+// EXPECT_EQ(1, report.value_metrics().skipped_size());
+//
+// EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+// report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+// EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
+// report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+// EXPECT_EQ(10, report.value_metrics().skipped(0).drop_event_size());
+//
+// auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+// EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
+// EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 10), dropEvent.drop_time_millis());
+//
+// dropEvent = report.value_metrics().skipped(0).drop_event(1);
+// EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+// EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 30), dropEvent.drop_time_millis());
+//
+// dropEvent = report.value_metrics().skipped(0).drop_event(2);
+// EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+// EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 50), dropEvent.drop_time_millis());
+//
+// dropEvent = report.value_metrics().skipped(0).drop_event(3);
+// EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+// EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 70), dropEvent.drop_time_millis());
+//
+// dropEvent = report.value_metrics().skipped(0).drop_event(4);
+// EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+// EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 90), dropEvent.drop_time_millis());
+//
+// dropEvent = report.value_metrics().skipped(0).drop_event(5);
+// EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+// EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 100), dropEvent.drop_time_millis());
+//
+// dropEvent = report.value_metrics().skipped(0).drop_event(6);
+// EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+// EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 150), dropEvent.drop_time_millis());
+//
+// dropEvent = report.value_metrics().skipped(0).drop_event(7);
+// EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+// EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 170), dropEvent.drop_time_millis());
+//
+// dropEvent = report.value_metrics().skipped(0).drop_event(8);
+// EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+// EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 190), dropEvent.drop_time_millis());
+//
+// dropEvent = report.value_metrics().skipped(0).drop_event(9);
+// EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+// EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 200), dropEvent.drop_time_millis());
+//}
+//
+///*
+// * Test metric with a simple sliced state
+// * - Increasing values
+// * - Using diff
+// * - Second field is value field
+// */
+//TEST(ValueMetricProducerTest, TestSlicedState) {
+// // Set up ValueMetricProducer.
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("SCREEN_STATE");
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // ValueMetricProducer initialized.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+// event->write("field1");
+// event->write(3);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// // Screen state change to ON.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 5);
+// event->write("field1");
+// event->write(5);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// // Screen state change to OFF.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+// event->write("field1");
+// event->write(9);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// // Screen state change to ON.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 15);
+// event->write("field1");
+// event->write(21);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// // Dump report requested.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
+// event->write("field1");
+// event->write(30);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithState(
+// pullerManager, metric, {android::util::SCREEN_STATE_CHANGED}, {});
+//
+// // Set up StateManager and check that StateTrackers are initialized.
+// StateManager::getInstance().clear();
+// StateManager::getInstance().registerListener(SCREEN_STATE_ATOM_ID, valueProducer);
+// EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
+// EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
+//
+// // Bucket status after metric initialized.
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// // Base for dimension key {}
+// auto it = valueProducer->mCurrentSlicedBucket.begin();
+// auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+// EXPECT_EQ(true, itBase->second[0].hasBase);
+// EXPECT_EQ(3, itBase->second[0].base.long_value);
+// // Value for dimension, state key {{}, kStateUnknown}
+// EXPECT_EQ(false, it->second[0].hasValue);
+//
+// // Bucket status after screen state change kStateUnknown->ON.
+// auto screenEvent = CreateScreenStateChangedEvent(
+// android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 5);
+// StateManager::getInstance().onLogEvent(*screenEvent);
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// // Base for dimension key {}
+// it = valueProducer->mCurrentSlicedBucket.begin();
+// itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+// EXPECT_EQ(true, itBase->second[0].hasBase);
+// EXPECT_EQ(5, itBase->second[0].base.long_value);
+// // Value for dimension, state key {{}, kStateUnknown}
+// EXPECT_EQ(true, it->second[0].hasValue);
+// EXPECT_EQ(2, it->second[0].value.long_value);
+//
+// // Bucket status after screen state change ON->OFF.
+// screenEvent = CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+// bucketStartTimeNs + 10);
+// StateManager::getInstance().onLogEvent(*screenEvent);
+// EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+// // Base for dimension key {}
+// it = valueProducer->mCurrentSlicedBucket.begin();
+// itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+// EXPECT_EQ(true, itBase->second[0].hasBase);
+// EXPECT_EQ(9, itBase->second[0].base.long_value);
+// // Value for dimension, state key {{}, ON}
+// EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+// it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+// EXPECT_EQ(true, it->second[0].hasValue);
+// EXPECT_EQ(4, it->second[0].value.long_value);
+// // Value for dimension, state key {{}, kStateUnknown}
+// it++;
+// EXPECT_EQ(true, it->second[0].hasValue);
+// EXPECT_EQ(2, it->second[0].value.long_value);
+//
+// // Bucket status after screen state change OFF->ON.
+// screenEvent = CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+// bucketStartTimeNs + 15);
+// StateManager::getInstance().onLogEvent(*screenEvent);
+// EXPECT_EQ(3UL, valueProducer->mCurrentSlicedBucket.size());
+// // Base for dimension key {}
+// it = valueProducer->mCurrentSlicedBucket.begin();
+// itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+// EXPECT_EQ(true, itBase->second[0].hasBase);
+// EXPECT_EQ(21, itBase->second[0].base.long_value);
+// // Value for dimension, state key {{}, OFF}
+// EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+// it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+// EXPECT_EQ(true, it->second[0].hasValue);
+// EXPECT_EQ(12, it->second[0].value.long_value);
+// // Value for dimension, state key {{}, ON}
+// it++;
+// EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+// it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+// EXPECT_EQ(true, it->second[0].hasValue);
+// EXPECT_EQ(4, it->second[0].value.long_value);
+// // Value for dimension, state key {{}, kStateUnknown}
+// it++;
+// EXPECT_EQ(true, it->second[0].hasValue);
+// EXPECT_EQ(2, it->second[0].value.long_value);
+//
+// // Start dump report and check output.
+// ProtoOutputStream output;
+// std::set<string> strSet;
+// valueProducer->onDumpReport(bucketStartTimeNs + 50, true /* include recent buckets */, true,
+// NO_TIME_CONSTRAINTS, &strSet, &output);
+//
+// StatsLogReport report = outputStreamToProto(&output);
+// EXPECT_TRUE(report.has_value_metrics());
+// EXPECT_EQ(3, report.value_metrics().data_size());
+//
+// auto data = report.value_metrics().data(0);
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
+//
+// data = report.value_metrics().data(1);
+// EXPECT_EQ(1, report.value_metrics().data(1).bucket_info_size());
+// EXPECT_EQ(13, report.value_metrics().data(1).bucket_info(0).values(0).value_long());
+// EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+// EXPECT_TRUE(data.slice_by_state(0).has_value());
+// EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON, data.slice_by_state(0).value());
+//
+// data = report.value_metrics().data(2);
+// EXPECT_EQ(1, report.value_metrics().data(2).bucket_info_size());
+// EXPECT_EQ(12, report.value_metrics().data(2).bucket_info(0).values(0).value_long());
+// EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+// EXPECT_TRUE(data.slice_by_state(0).has_value());
+// EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF, data.slice_by_state(0).value());
+//}
+//
+///*
+// * Test metric with sliced state with map
+// * - Increasing values
+// * - Using diff
+// * - Second field is value field
+// */
+//TEST(ValueMetricProducerTest, TestSlicedStateWithMap) {
+// // Set up ValueMetricProducer.
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("SCREEN_STATE_ONOFF");
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // ValueMetricProducer initialized.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+// event->write("field1");
+// event->write(3);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// // Screen state change to ON.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 5);
+// event->write("field1");
+// event->write(5);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// // Screen state change to VR.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+// event->write("field1");
+// event->write(9);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// // Screen state change to OFF.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 15);
+// event->write("field1");
+// event->write(21);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// // Dump report requested.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
+// event->write("field1");
+// event->write(30);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// const StateMap& stateMap = CreateScreenStateOnOffMap();
+// const StateMap_StateGroup screenOnGroup = stateMap.group(0);
+// const StateMap_StateGroup screenOffGroup = stateMap.group(1);
+//
+// unordered_map<int, unordered_map<int, int64_t>> stateGroupMap;
+// for (auto group : stateMap.group()) {
+// for (auto value : group.value()) {
+// stateGroupMap[SCREEN_STATE_ATOM_ID][value] = group.group_id();
+// }
+// }
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithState(
+// pullerManager, metric, {android::util::SCREEN_STATE_CHANGED}, stateGroupMap);
+//
+// // Set up StateManager and check that StateTrackers are initialized.
+// StateManager::getInstance().clear();
+// StateManager::getInstance().registerListener(SCREEN_STATE_ATOM_ID, valueProducer);
+// EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
+// EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
+//
+// // Bucket status after metric initialized.
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// // Base for dimension key {}
+// auto it = valueProducer->mCurrentSlicedBucket.begin();
+// auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+// EXPECT_EQ(true, itBase->second[0].hasBase);
+// EXPECT_EQ(3, itBase->second[0].base.long_value);
+// // Value for dimension, state key {{}, {}}
+// EXPECT_EQ(false, it->second[0].hasValue);
+//
+// // Bucket status after screen state change kStateUnknown->ON.
+// auto screenEvent = CreateScreenStateChangedEvent(
+// android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 5);
+// StateManager::getInstance().onLogEvent(*screenEvent);
+// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+// // Base for dimension key {}
+// it = valueProducer->mCurrentSlicedBucket.begin();
+// itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+// EXPECT_EQ(true, itBase->second[0].hasBase);
+// EXPECT_EQ(5, itBase->second[0].base.long_value);
+// // Value for dimension, state key {{}, kStateUnknown}
+// EXPECT_EQ(true, it->second[0].hasValue);
+// EXPECT_EQ(2, it->second[0].value.long_value);
+//
+// // Bucket status after screen state change ON->VR (also ON).
+// screenEvent = CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_VR,
+// bucketStartTimeNs + 10);
+// StateManager::getInstance().onLogEvent(*screenEvent);
+// EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+// // Base for dimension key {}
+// it = valueProducer->mCurrentSlicedBucket.begin();
+// itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+// EXPECT_EQ(true, itBase->second[0].hasBase);
+// EXPECT_EQ(9, itBase->second[0].base.long_value);
+// // Value for dimension, state key {{}, ON GROUP}
+// EXPECT_EQ(screenOnGroup.group_id(),
+// it->first.getStateValuesKey().getValues()[0].mValue.long_value);
+// EXPECT_EQ(true, it->second[0].hasValue);
+// EXPECT_EQ(4, it->second[0].value.long_value);
+// // Value for dimension, state key {{}, kStateUnknown}
+// it++;
+// EXPECT_EQ(true, it->second[0].hasValue);
+// EXPECT_EQ(2, it->second[0].value.long_value);
+//
+// // Bucket status after screen state change VR->OFF.
+// screenEvent = CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+// bucketStartTimeNs + 15);
+// StateManager::getInstance().onLogEvent(*screenEvent);
+// EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+// // Base for dimension key {}
+// it = valueProducer->mCurrentSlicedBucket.begin();
+// itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+// EXPECT_EQ(true, itBase->second[0].hasBase);
+// EXPECT_EQ(21, itBase->second[0].base.long_value);
+// // Value for dimension, state key {{}, ON GROUP}
+// EXPECT_EQ(screenOnGroup.group_id(),
+// it->first.getStateValuesKey().getValues()[0].mValue.long_value);
+// EXPECT_EQ(true, it->second[0].hasValue);
+// EXPECT_EQ(16, it->second[0].value.long_value);
+// // Value for dimension, state key {{}, kStateUnknown}
+// it++;
+// EXPECT_EQ(true, it->second[0].hasValue);
+// EXPECT_EQ(2, it->second[0].value.long_value);
+//
+// // Start dump report and check output.
+// ProtoOutputStream output;
+// std::set<string> strSet;
+// valueProducer->onDumpReport(bucketStartTimeNs + 50, true /* include recent buckets */, true,
+// NO_TIME_CONSTRAINTS, &strSet, &output);
+//
+// StatsLogReport report = outputStreamToProto(&output);
+// EXPECT_TRUE(report.has_value_metrics());
+// EXPECT_EQ(3, report.value_metrics().data_size());
+//
+// auto data = report.value_metrics().data(0);
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
+//
+// data = report.value_metrics().data(1);
+// EXPECT_EQ(1, report.value_metrics().data(1).bucket_info_size());
+// EXPECT_EQ(16, report.value_metrics().data(1).bucket_info(0).values(0).value_long());
+// EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+// EXPECT_TRUE(data.slice_by_state(0).has_group_id());
+// EXPECT_EQ(screenOnGroup.group_id(), data.slice_by_state(0).group_id());
+//
+// data = report.value_metrics().data(2);
+// EXPECT_EQ(1, report.value_metrics().data(2).bucket_info_size());
+// EXPECT_EQ(9, report.value_metrics().data(2).bucket_info(0).values(0).value_long());
+// EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+// EXPECT_TRUE(data.slice_by_state(0).has_group_id());
+// EXPECT_EQ(screenOffGroup.group_id(), data.slice_by_state(0).group_id());
+//}
+//
+///*
+// * Test metric that slices by state with a primary field and has dimensions
+// * - Increasing values
+// * - Using diff
+// * - Second field is value field
+// */
+//TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
+// // Set up ValueMetricProducer.
+// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("UID_PROCESS_STATE");
+// metric.mutable_dimensions_in_what()->set_field(tagId);
+// metric.mutable_dimensions_in_what()->add_child()->set_field(1);
+//
+// MetricStateLink* stateLink = metric.add_state_link();
+// stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
+// auto fieldsInWhat = stateLink->mutable_fields_in_what();
+// *fieldsInWhat = CreateDimensions(tagId, {1 /* uid */});
+// auto fieldsInState = stateLink->mutable_fields_in_state();
+// *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(tagId, _))
+// // ValueMetricProducer initialized.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+// event->write(2 /* uid */);
+// event->write(7);
+// event->init();
+// data->push_back(event);
+//
+// event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+// event->write(1 /* uid */);
+// event->write(3);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// // Uid 1 process state change from kStateUnknown -> Foreground
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
+// event->write(1 /* uid */);
+// event->write(6);
+// event->init();
+// data->push_back(event);
+//
+// // This event should be skipped.
+// event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
+// event->write(2 /* uid */);
+// event->write(8);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// // Uid 2 process state change from kStateUnknown -> Background
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 40);
+// event->write(2 /* uid */);
+// event->write(9);
+// event->init();
+// data->push_back(event);
+//
+// // This event should be skipped.
+// event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 40);
+// event->write(1 /* uid */);
+// event->write(12);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// // Uid 1 process state change from Foreground -> Background
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 20);
+// event->write(1 /* uid */);
+// event->write(13);
+// event->init();
+// data->push_back(event);
+//
+// // This event should be skipped.
+// event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 20);
+// event->write(2 /* uid */);
+// event->write(11);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// // Uid 1 process state change from Background -> Foreground
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 40);
+// event->write(1 /* uid */);
+// event->write(17);
+// event->init();
+// data->push_back(event);
+//
+// // This event should be skipped.
+// event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 40);
+// event->write(2 /* uid */);
+// event->write(15);
+// event->init();
+// data->push_back(event);
+// return true;
+// }))
+// // Dump report pull.
+// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 50);
+// event->write(2 /* uid */);
+// event->write(20);
+// event->init();
+// data->push_back(event);
+//
+// event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 50);
+// event->write(1 /* uid */);
+// event->write(21);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// sp<ValueMetricProducer> valueProducer =
+// ValueMetricProducerTestHelper::createValueProducerWithState(
+// pullerManager, metric, {UID_PROCESS_STATE_ATOM_ID}, {});
+//
+// // Set up StateManager and check that StateTrackers are initialized.
+// StateManager::getInstance().clear();
+// StateManager::getInstance().registerListener(UID_PROCESS_STATE_ATOM_ID, valueProducer);
+// EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
+// EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
+//
+// // Bucket status after metric initialized.
+// EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+// // Base for dimension key {uid 1}.
+// auto it = valueProducer->mCurrentSlicedBucket.begin();
+// EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+// auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+// EXPECT_EQ(true, itBase->second[0].hasBase);
+// EXPECT_EQ(3, itBase->second[0].base.long_value);
+// // Value for dimension, state key {{uid 1}, kStateUnknown}
+// // TODO(tsaichristine): test equality of state values key
+// // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+// EXPECT_EQ(false, it->second[0].hasValue);
+// // Base for dimension key {uid 2}
+// it++;
+// EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+// itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+// EXPECT_EQ(true, itBase->second[0].hasBase);
+// EXPECT_EQ(7, itBase->second[0].base.long_value);
+// // Value for dimension, state key {{uid 2}, kStateUnknown}
+// // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+// EXPECT_EQ(false, it->second[0].hasValue);
+//
+// // Bucket status after uid 1 process state change kStateUnknown -> Foreground.
+// auto uidProcessEvent = CreateUidProcessStateChangedEvent(
+// 1 /* uid */, android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, bucketStartTimeNs + 20);
+// StateManager::getInstance().onLogEvent(*uidProcessEvent);
+// EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+// // Base for dimension key {uid 1}.
+// it = valueProducer->mCurrentSlicedBucket.begin();
+// EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+// itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+// EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+// EXPECT_EQ(true, itBase->second[0].hasBase);
+// EXPECT_EQ(6, itBase->second[0].base.long_value);
+// // Value for key {uid 1, kStateUnknown}.
+// // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+// EXPECT_EQ(true, it->second[0].hasValue);
+// EXPECT_EQ(3, it->second[0].value.long_value);
+//
+// // Base for dimension key {uid 2}
+// it++;
+// EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+// itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+// EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+// EXPECT_EQ(true, itBase->second[0].hasBase);
+// EXPECT_EQ(7, itBase->second[0].base.long_value);
+// // Value for key {uid 2, kStateUnknown}
+// EXPECT_EQ(false, it->second[0].hasValue);
+//
+// // Bucket status after uid 2 process state change kStateUnknown -> Background.
+// uidProcessEvent = CreateUidProcessStateChangedEvent(
+// 2 /* uid */, android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, bucketStartTimeNs + 40);
+// StateManager::getInstance().onLogEvent(*uidProcessEvent);
+// EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+// // Base for dimension key {uid 1}.
+// it = valueProducer->mCurrentSlicedBucket.begin();
+// EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+// itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+// EXPECT_EQ(true, itBase->second[0].hasBase);
+// EXPECT_EQ(6, itBase->second[0].base.long_value);
+// // Value for key {uid 1, kStateUnknown}.
+// EXPECT_EQ(true, it->second[0].hasValue);
+// EXPECT_EQ(3, it->second[0].value.long_value);
+//
+// // Base for dimension key {uid 2}
+// it++;
+// EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+// itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+// EXPECT_EQ(true, itBase->second[0].hasBase);
+// EXPECT_EQ(9, itBase->second[0].base.long_value);
+// // Value for key {uid 2, kStateUnknown}
+// // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+// EXPECT_EQ(true, it->second[0].hasValue);
+// EXPECT_EQ(2, it->second[0].value.long_value);
+//
+// // Pull at end of first bucket.
+// vector<shared_ptr<LogEvent>> allData;
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs);
+// event->write(1 /* uid */);
+// event->write(10);
+// event->init();
+// allData.push_back(event);
+//
+// event = make_shared<LogEvent>(tagId, bucket2StartTimeNs);
+// event->write(2 /* uid */);
+// event->write(15);
+// event->init();
+// allData.push_back(event);
+//
+// valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
+//
+// // Buckets flushed after end of first bucket.
+// // None of the buckets should have a value.
+// EXPECT_EQ(4UL, valueProducer->mCurrentSlicedBucket.size());
+// EXPECT_EQ(4UL, valueProducer->mPastBuckets.size());
+// EXPECT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
+// // Base for dimension key {uid 2}.
+// it = valueProducer->mCurrentSlicedBucket.begin();
+// EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+// itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+// EXPECT_EQ(true, itBase->second[0].hasBase);
+// EXPECT_EQ(15, itBase->second[0].base.long_value);
+// // Value for key {uid 2, BACKGROUND}.
+// EXPECT_EQ(1, it->first.getStateValuesKey().getValues().size());
+// EXPECT_EQ(1006, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+// EXPECT_EQ(false, it->second[0].hasValue);
+//
+// // Base for dimension key {uid 1}
+// it++;
+// EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+// itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+// EXPECT_EQ(true, itBase->second[0].hasBase);
+// EXPECT_EQ(10, itBase->second[0].base.long_value);
+// // Value for key {uid 1, kStateUnknown}
+// EXPECT_EQ(0, it->first.getStateValuesKey().getValues().size());
+// // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+// EXPECT_EQ(false, it->second[0].hasValue);
+//
+// // Value for key {uid 1, FOREGROUND}
+// it++;
+// EXPECT_EQ(1, it->first.getStateValuesKey().getValues().size());
+// EXPECT_EQ(1005, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+// EXPECT_EQ(false, it->second[0].hasValue);
+//
+// // Value for key {uid 2, kStateUnknown}
+// it++;
+// EXPECT_EQ(false, it->second[0].hasValue);
+//
+// // Bucket status after uid 1 process state change from Foreground -> Background.
+// uidProcessEvent = CreateUidProcessStateChangedEvent(
+// 1 /* uid */, android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, bucket2StartTimeNs + 20);
+// StateManager::getInstance().onLogEvent(*uidProcessEvent);
+//
+// EXPECT_EQ(4UL, valueProducer->mCurrentSlicedBucket.size());
+// EXPECT_EQ(4UL, valueProducer->mPastBuckets.size());
+// EXPECT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
+// // Base for dimension key {uid 2}.
+// it = valueProducer->mCurrentSlicedBucket.begin();
+// EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+// itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+// EXPECT_EQ(true, itBase->second[0].hasBase);
+// EXPECT_EQ(15, itBase->second[0].base.long_value);
+// // Value for key {uid 2, BACKGROUND}.
+// EXPECT_EQ(false, it->second[0].hasValue);
+// // Base for dimension key {uid 1}
+// it++;
+// EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+// itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+// EXPECT_EQ(true, itBase->second[0].hasBase);
+// EXPECT_EQ(13, itBase->second[0].base.long_value);
+// // Value for key {uid 1, kStateUnknown}
+// EXPECT_EQ(false, it->second[0].hasValue);
+// // Value for key {uid 1, FOREGROUND}
+// it++;
+// EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+// EXPECT_EQ(1005, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+// EXPECT_EQ(true, it->second[0].hasValue);
+// EXPECT_EQ(3, it->second[0].value.long_value);
+// // Value for key {uid 2, kStateUnknown}
+// it++;
+// EXPECT_EQ(false, it->second[0].hasValue);
+//
+// // Bucket status after uid 1 process state change Background->Foreground.
+// uidProcessEvent = CreateUidProcessStateChangedEvent(
+// 1 /* uid */, android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, bucket2StartTimeNs + 40);
+// StateManager::getInstance().onLogEvent(*uidProcessEvent);
+//
+// EXPECT_EQ(5UL, valueProducer->mCurrentSlicedBucket.size());
+// EXPECT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
+// // Base for dimension key {uid 2}
+// it = valueProducer->mCurrentSlicedBucket.begin();
+// EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+// itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+// EXPECT_EQ(true, itBase->second[0].hasBase);
+// EXPECT_EQ(15, itBase->second[0].base.long_value);
+// EXPECT_EQ(false, it->second[0].hasValue);
+//
+// it++;
+// EXPECT_EQ(false, it->second[0].hasValue);
+//
+// // Base for dimension key {uid 1}
+// it++;
+// EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+// itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+// EXPECT_EQ(17, itBase->second[0].base.long_value);
+// // Value for key {uid 1, BACKGROUND}
+// EXPECT_EQ(1006, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+// EXPECT_EQ(true, it->second[0].hasValue);
+// EXPECT_EQ(4, it->second[0].value.long_value);
+// // Value for key {uid 1, FOREGROUND}
+// it++;
+// EXPECT_EQ(1005, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+// EXPECT_EQ(true, it->second[0].hasValue);
+// EXPECT_EQ(3, it->second[0].value.long_value);
+//
+// // Start dump report and check output.
+// ProtoOutputStream output;
+// std::set<string> strSet;
+// valueProducer->onDumpReport(bucket2StartTimeNs + 50, true /* include recent buckets */, true,
+// NO_TIME_CONSTRAINTS, &strSet, &output);
+//
+// StatsLogReport report = outputStreamToProto(&output);
+// EXPECT_TRUE(report.has_value_metrics());
+// EXPECT_EQ(5, report.value_metrics().data_size());
+//
+// auto data = report.value_metrics().data(0);
+// EXPECT_EQ(1, data.bucket_info_size());
+// EXPECT_EQ(4, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
+// EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+// EXPECT_TRUE(data.slice_by_state(0).has_value());
+// EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
+// data.slice_by_state(0).value());
+//
+// data = report.value_metrics().data(1);
+// EXPECT_EQ(1, report.value_metrics().data(1).bucket_info_size());
+// EXPECT_EQ(2, report.value_metrics().data(1).bucket_info(0).values(0).value_long());
+//
+// data = report.value_metrics().data(2);
+// EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+// EXPECT_TRUE(data.slice_by_state(0).has_value());
+// EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
+// data.slice_by_state(0).value());
+// EXPECT_EQ(2, report.value_metrics().data(2).bucket_info_size());
+// EXPECT_EQ(4, report.value_metrics().data(2).bucket_info(0).values(0).value_long());
+// EXPECT_EQ(7, report.value_metrics().data(2).bucket_info(1).values(0).value_long());
+//
+// data = report.value_metrics().data(3);
+// EXPECT_EQ(1, report.value_metrics().data(3).bucket_info_size());
+// EXPECT_EQ(3, report.value_metrics().data(3).bucket_info(0).values(0).value_long());
+//
+// data = report.value_metrics().data(4);
+// EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+// EXPECT_TRUE(data.slice_by_state(0).has_value());
+// EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
+// data.slice_by_state(0).value());
+// EXPECT_EQ(2, report.value_metrics().data(4).bucket_info_size());
+// EXPECT_EQ(6, report.value_metrics().data(4).bucket_info(0).values(0).value_long());
+// EXPECT_EQ(5, report.value_metrics().data(4).bucket_info(1).values(0).value_long());
+//}
} // namespace statsd
} // namespace os
diff --git a/cmds/statsd/tests/shell/ShellSubscriber_test.cpp b/cmds/statsd/tests/shell/ShellSubscriber_test.cpp
index dac5f33..57e4265 100644
--- a/cmds/statsd/tests/shell/ShellSubscriber_test.cpp
+++ b/cmds/statsd/tests/shell/ShellSubscriber_test.cpp
@@ -105,29 +105,30 @@
close(fds_data[0]);
}
-TEST(ShellSubscriberTest, testPushedSubscription) {
- sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- vector<std::shared_ptr<LogEvent>> pushedList;
-
- std::shared_ptr<LogEvent> event1 =
- std::make_shared<LogEvent>(29 /*screen_state_atom_id*/, 1000 /*timestamp*/);
- event1->write(::android::view::DisplayStateEnum::DISPLAY_STATE_ON);
- event1->init();
- pushedList.push_back(event1);
-
- // create a simple config to get screen events
- ShellSubscription config;
- config.add_pushed()->set_atom_id(29);
-
- // this is the expected screen event atom.
- ShellData shellData;
- shellData.add_atom()->mutable_screen_state_changed()->set_state(
- ::android::view::DisplayStateEnum::DISPLAY_STATE_ON);
-
- runShellTest(config, uidMap, pullerManager, pushedList, shellData);
-}
+// TODO(b/149590301): Update this test to use new socket schema.
+//TEST(ShellSubscriberTest, testPushedSubscription) {
+// sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// vector<std::shared_ptr<LogEvent>> pushedList;
+//
+// std::shared_ptr<LogEvent> event1 =
+// std::make_shared<LogEvent>(29 /*screen_state_atom_id*/, 1000 /*timestamp*/);
+// event1->write(::android::view::DisplayStateEnum::DISPLAY_STATE_ON);
+// event1->init();
+// pushedList.push_back(event1);
+//
+// // create a simple config to get screen events
+// ShellSubscription config;
+// config.add_pushed()->set_atom_id(29);
+//
+// // this is the expected screen event atom.
+// ShellData shellData;
+// shellData.add_atom()->mutable_screen_state_changed()->set_state(
+// ::android::view::DisplayStateEnum::DISPLAY_STATE_ON);
+//
+// runShellTest(config, uidMap, pullerManager, pushedList, shellData);
+//}
namespace {
@@ -160,30 +161,31 @@
} // namespace
-TEST(ShellSubscriberTest, testPulledSubscription) {
- sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
-
- sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(10016, _))
- .WillRepeatedly(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, 1111L);
- event->write(kUid1);
- event->write(kCpuTime1);
- event->init();
- data->push_back(event);
- // another event
- event = make_shared<LogEvent>(tagId, 1111L);
- event->write(kUid2);
- event->write(kCpuTime2);
- event->init();
- data->push_back(event);
- return true;
- }));
-
- runShellTest(getPulledConfig(), uidMap, pullerManager, vector<std::shared_ptr<LogEvent>>(),
- getExpectedShellData());
-}
+// TODO(b/149590301): Update this test to use new socket schema.
+//TEST(ShellSubscriberTest, testPulledSubscription) {
+// sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
+//
+// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+// EXPECT_CALL(*pullerManager, Pull(10016, _))
+// .WillRepeatedly(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+// data->clear();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, 1111L);
+// event->write(kUid1);
+// event->write(kCpuTime1);
+// event->init();
+// data->push_back(event);
+// // another event
+// event = make_shared<LogEvent>(tagId, 1111L);
+// event->write(kUid2);
+// event->write(kCpuTime2);
+// event->init();
+// data->push_back(event);
+// return true;
+// }));
+//
+// runShellTest(getPulledConfig(), uidMap, pullerManager, vector<std::shared_ptr<LogEvent>>(),
+// getExpectedShellData());
+//}
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
diff --git a/cmds/statsd/tests/state/StateTracker_test.cpp b/cmds/statsd/tests/state/StateTracker_test.cpp
index b0acd5a..36c0f32 100644
--- a/cmds/statsd/tests/state/StateTracker_test.cpp
+++ b/cmds/statsd/tests/state/StateTracker_test.cpp
@@ -56,94 +56,95 @@
return output.mValue.int_value;
}
-// START: build event functions.
-// State with no primary fields - ScreenStateChanged
-std::shared_ptr<LogEvent> buildScreenEvent(int state) {
- std::shared_ptr<LogEvent> event =
- std::make_shared<LogEvent>(android::util::SCREEN_STATE_CHANGED, 1000 /*timestamp*/);
- event->write((int32_t)state);
- event->init();
- return event;
-}
-
-// State with one primary field - UidProcessStateChanged
-std::shared_ptr<LogEvent> buildUidProcessEvent(int uid, int state) {
- std::shared_ptr<LogEvent> event =
- std::make_shared<LogEvent>(android::util::UID_PROCESS_STATE_CHANGED, 1000 /*timestamp*/);
- event->write((int32_t)uid);
- event->write((int32_t)state);
- event->init();
- return event;
-}
-
-// State with first uid in attribution chain as primary field - WakelockStateChanged
-std::shared_ptr<LogEvent> buildPartialWakelockEvent(int uid, const std::string& tag, bool acquire) {
- std::vector<AttributionNodeInternal> chain;
- chain.push_back(AttributionNodeInternal());
- AttributionNodeInternal& attr = chain.back();
- attr.set_uid(uid);
-
- std::shared_ptr<LogEvent> event =
- std::make_shared<LogEvent>(android::util::WAKELOCK_STATE_CHANGED, 1000 /* timestamp */);
- event->write(chain);
- event->write((int32_t)1); // PARTIAL_WAKE_LOCK
- event->write(tag);
- event->write(acquire ? 1 : 0);
- event->init();
- return event;
-}
-
-// State with multiple primary fields - OverlayStateChanged
-std::shared_ptr<LogEvent> buildOverlayEvent(int uid, const std::string& packageName, int state) {
- std::shared_ptr<LogEvent> event =
- std::make_shared<LogEvent>(android::util::OVERLAY_STATE_CHANGED, 1000 /*timestamp*/);
- event->write((int32_t)uid);
- event->write(packageName);
- event->write(true); // using_alert_window
- event->write((int32_t)state);
- event->init();
- return event;
-}
-
-// Incorrect event - missing fields
-std::shared_ptr<LogEvent> buildIncorrectOverlayEvent(int uid, const std::string& packageName, int state) {
- std::shared_ptr<LogEvent> event =
- std::make_shared<LogEvent>(android::util::OVERLAY_STATE_CHANGED, 1000 /*timestamp*/);
- event->write((int32_t)uid);
- event->write(packageName);
- event->write((int32_t)state);
- event->init();
- return event;
-}
-
-// Incorrect event - exclusive state has wrong type
-std::shared_ptr<LogEvent> buildOverlayEventBadStateType(int uid, const std::string& packageName) {
- std::shared_ptr<LogEvent> event =
- std::make_shared<LogEvent>(android::util::OVERLAY_STATE_CHANGED, 1000 /*timestamp*/);
- event->write((int32_t)uid);
- event->write(packageName);
- event->write(true);
- event->write("string"); // exclusive state: string instead of int
- event->init();
- return event;
-}
-
-std::shared_ptr<LogEvent> buildBleScanEvent(int uid, bool acquire, bool reset) {
- std::vector<AttributionNodeInternal> chain;
- chain.push_back(AttributionNodeInternal());
- AttributionNodeInternal& attr = chain.back();
- attr.set_uid(uid);
-
- std::shared_ptr<LogEvent> event =
- std::make_shared<LogEvent>(android::util::BLE_SCAN_STATE_CHANGED, 1000);
- event->write(chain);
- event->write(reset ? 2 : acquire ? 1 : 0); // PARTIAL_WAKE_LOCK
- event->write(0); // filtered
- event->write(0); // first match
- event->write(0); // opportunistic
- event->init();
- return event;
-}
+// TODO(b/149590301): Update these helpers to use new socket schema.
+//// START: build event functions.
+//// State with no primary fields - ScreenStateChanged
+//std::shared_ptr<LogEvent> buildScreenEvent(int state) {
+// std::shared_ptr<LogEvent> event =
+// std::make_shared<LogEvent>(android::util::SCREEN_STATE_CHANGED, 1000 /*timestamp*/);
+// event->write((int32_t)state);
+// event->init();
+// return event;
+//}
+//
+//// State with one primary field - UidProcessStateChanged
+//std::shared_ptr<LogEvent> buildUidProcessEvent(int uid, int state) {
+// std::shared_ptr<LogEvent> event =
+// std::make_shared<LogEvent>(android::util::UID_PROCESS_STATE_CHANGED, 1000 /*timestamp*/);
+// event->write((int32_t)uid);
+// event->write((int32_t)state);
+// event->init();
+// return event;
+//}
+//
+//// State with first uid in attribution chain as primary field - WakelockStateChanged
+//std::shared_ptr<LogEvent> buildPartialWakelockEvent(int uid, const std::string& tag, bool acquire) {
+// std::vector<AttributionNodeInternal> chain;
+// chain.push_back(AttributionNodeInternal());
+// AttributionNodeInternal& attr = chain.back();
+// attr.set_uid(uid);
+//
+// std::shared_ptr<LogEvent> event =
+// std::make_shared<LogEvent>(android::util::WAKELOCK_STATE_CHANGED, 1000 /* timestamp */);
+// event->write(chain);
+// event->write((int32_t)1); // PARTIAL_WAKE_LOCK
+// event->write(tag);
+// event->write(acquire ? 1 : 0);
+// event->init();
+// return event;
+//}
+//
+//// State with multiple primary fields - OverlayStateChanged
+//std::shared_ptr<LogEvent> buildOverlayEvent(int uid, const std::string& packageName, int state) {
+// std::shared_ptr<LogEvent> event =
+// std::make_shared<LogEvent>(android::util::OVERLAY_STATE_CHANGED, 1000 /*timestamp*/);
+// event->write((int32_t)uid);
+// event->write(packageName);
+// event->write(true); // using_alert_window
+// event->write((int32_t)state);
+// event->init();
+// return event;
+//}
+//
+//// Incorrect event - missing fields
+//std::shared_ptr<LogEvent> buildIncorrectOverlayEvent(int uid, const std::string& packageName, int state) {
+// std::shared_ptr<LogEvent> event =
+// std::make_shared<LogEvent>(android::util::OVERLAY_STATE_CHANGED, 1000 /*timestamp*/);
+// event->write((int32_t)uid);
+// event->write(packageName);
+// event->write((int32_t)state);
+// event->init();
+// return event;
+//}
+//
+//// Incorrect event - exclusive state has wrong type
+//std::shared_ptr<LogEvent> buildOverlayEventBadStateType(int uid, const std::string& packageName) {
+// std::shared_ptr<LogEvent> event =
+// std::make_shared<LogEvent>(android::util::OVERLAY_STATE_CHANGED, 1000 /*timestamp*/);
+// event->write((int32_t)uid);
+// event->write(packageName);
+// event->write(true);
+// event->write("string"); // exclusive state: string instead of int
+// event->init();
+// return event;
+//}
+//
+//std::shared_ptr<LogEvent> buildBleScanEvent(int uid, bool acquire, bool reset) {
+// std::vector<AttributionNodeInternal> chain;
+// chain.push_back(AttributionNodeInternal());
+// AttributionNodeInternal& attr = chain.back();
+// attr.set_uid(uid);
+//
+// std::shared_ptr<LogEvent> event =
+// std::make_shared<LogEvent>(android::util::BLE_SCAN_STATE_CHANGED, 1000);
+// event->write(chain);
+// event->write(reset ? 2 : acquire ? 1 : 0); // PARTIAL_WAKE_LOCK
+// event->write(0); // filtered
+// event->write(0); // first match
+// event->write(0); // opportunistic
+// event->init();
+// return event;
+//}
// END: build event functions.
// START: get primary key functions
@@ -292,302 +293,302 @@
EXPECT_EQ(0, mgr.getStateTrackersCount());
EXPECT_EQ(-1, mgr.getListenersCount(android::util::SCREEN_STATE_CHANGED));
}
-
-/**
- * Test a binary state atom with nested counting.
- *
- * To go from an "ON" state to an "OFF" state with nested counting, we must see
- * an equal number of "OFF" events as "ON" events.
- * For example, ACQUIRE, ACQUIRE, RELEASE will still be in the ACQUIRE state.
- * ACQUIRE, ACQUIRE, RELEASE, RELEASE will be in the RELEASE state.
- */
-TEST(StateTrackerTest, TestStateChangeNested) {
- sp<TestStateListener> listener = new TestStateListener();
- StateManager mgr;
- mgr.registerListener(android::util::WAKELOCK_STATE_CHANGED, listener);
-
- std::shared_ptr<LogEvent> event1 =
- buildPartialWakelockEvent(1000 /* uid */, "tag", true /*acquire*/);
- mgr.onLogEvent(*event1);
- EXPECT_EQ(1, listener->updates.size());
- EXPECT_EQ(1000, listener->updates[0].mKey.getValues()[0].mValue.int_value);
- EXPECT_EQ(1, listener->updates[0].mState);
- listener->updates.clear();
-
- std::shared_ptr<LogEvent> event2 =
- buildPartialWakelockEvent(1000 /* uid */, "tag", true /*acquire*/);
- mgr.onLogEvent(*event2);
- EXPECT_EQ(0, listener->updates.size());
-
- std::shared_ptr<LogEvent> event3 =
- buildPartialWakelockEvent(1000 /* uid */, "tag", false /*release*/);
- mgr.onLogEvent(*event3);
- EXPECT_EQ(0, listener->updates.size());
-
- std::shared_ptr<LogEvent> event4 =
- buildPartialWakelockEvent(1000 /* uid */, "tag", false /*release*/);
- mgr.onLogEvent(*event4);
- EXPECT_EQ(1, listener->updates.size());
- EXPECT_EQ(1000, listener->updates[0].mKey.getValues()[0].mValue.int_value);
- EXPECT_EQ(0, listener->updates[0].mState);
-}
-
-/**
- * Test a state atom with a reset state.
- *
- * If the reset state value is seen, every state in the map is set to the default
- * state and every listener is notified.
- */
-TEST(StateTrackerTest, TestStateChangeReset) {
- sp<TestStateListener> listener = new TestStateListener();
- StateManager mgr;
- mgr.registerListener(android::util::BLE_SCAN_STATE_CHANGED, listener);
-
- std::shared_ptr<LogEvent> event1 =
- buildBleScanEvent(1000 /* uid */, true /*acquire*/, false /*reset*/);
- mgr.onLogEvent(*event1);
- EXPECT_EQ(1, listener->updates.size());
- EXPECT_EQ(1000, listener->updates[0].mKey.getValues()[0].mValue.int_value);
- EXPECT_EQ(BleScanStateChanged::ON, listener->updates[0].mState);
- listener->updates.clear();
-
- std::shared_ptr<LogEvent> event2 =
- buildBleScanEvent(2000 /* uid */, true /*acquire*/, false /*reset*/);
- mgr.onLogEvent(*event2);
- EXPECT_EQ(1, listener->updates.size());
- EXPECT_EQ(2000, listener->updates[0].mKey.getValues()[0].mValue.int_value);
- EXPECT_EQ(BleScanStateChanged::ON, listener->updates[0].mState);
- listener->updates.clear();
-
- std::shared_ptr<LogEvent> event3 =
- buildBleScanEvent(2000 /* uid */, false /*acquire*/, true /*reset*/);
- mgr.onLogEvent(*event3);
- EXPECT_EQ(2, listener->updates.size());
- EXPECT_EQ(BleScanStateChanged::OFF, listener->updates[0].mState);
- EXPECT_EQ(BleScanStateChanged::OFF, listener->updates[1].mState);
-}
-
-/**
- * Test StateManager's onLogEvent and StateListener's onStateChanged correctly
- * updates listener for states without primary keys.
- */
-TEST(StateTrackerTest, TestStateChangeNoPrimaryFields) {
- sp<TestStateListener> listener1 = new TestStateListener();
- StateManager mgr;
- mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener1);
-
- // log event
- std::shared_ptr<LogEvent> event =
- buildScreenEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON);
- mgr.onLogEvent(*event);
-
- // check listener was updated
- EXPECT_EQ(1, listener1->updates.size());
- EXPECT_EQ(DEFAULT_DIMENSION_KEY, listener1->updates[0].mKey);
- EXPECT_EQ(2, listener1->updates[0].mState);
-
- // check StateTracker was updated by querying for state
- HashableDimensionKey queryKey = DEFAULT_DIMENSION_KEY;
- EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
- getStateInt(mgr, android::util::SCREEN_STATE_CHANGED, queryKey));
-}
-
-/**
- * Test StateManager's onLogEvent and StateListener's onStateChanged correctly
- * updates listener for states with one primary key.
- */
-TEST(StateTrackerTest, TestStateChangeOnePrimaryField) {
- sp<TestStateListener> listener1 = new TestStateListener();
- StateManager mgr;
- mgr.registerListener(android::util::UID_PROCESS_STATE_CHANGED, listener1);
-
- // log event
- std::shared_ptr<LogEvent> event =
- buildUidProcessEvent(1000 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_TOP);
- mgr.onLogEvent(*event);
-
- // check listener was updated
- EXPECT_EQ(1, listener1->updates.size());
- EXPECT_EQ(1000, listener1->updates[0].mKey.getValues()[0].mValue.int_value);
- EXPECT_EQ(1002, listener1->updates[0].mState);
-
- // check StateTracker was updated by querying for state
- HashableDimensionKey queryKey;
- getUidProcessKey(1000 /* uid */, &queryKey);
- EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_TOP,
- getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED, queryKey));
-}
-
-TEST(StateTrackerTest, TestStateChangePrimaryFieldAttrChain) {
- sp<TestStateListener> listener1 = new TestStateListener();
- StateManager mgr;
- mgr.registerListener(android::util::WAKELOCK_STATE_CHANGED, listener1);
-
- // Log event.
- std::shared_ptr<LogEvent> event =
- buildPartialWakelockEvent(1001 /* uid */, "tag1", true /* acquire */);
- mgr.onLogEvent(*event);
-
- EXPECT_EQ(1, mgr.getStateTrackersCount());
- EXPECT_EQ(1, mgr.getListenersCount(android::util::WAKELOCK_STATE_CHANGED));
-
- // Check listener was updated.
- EXPECT_EQ(1, listener1->updates.size());
- EXPECT_EQ(3, listener1->updates[0].mKey.getValues().size());
- EXPECT_EQ(1001, listener1->updates[0].mKey.getValues()[0].mValue.int_value);
- EXPECT_EQ(1, listener1->updates[0].mKey.getValues()[1].mValue.int_value);
- EXPECT_EQ("tag1", listener1->updates[0].mKey.getValues()[2].mValue.str_value);
- EXPECT_EQ(WakelockStateChanged::ACQUIRE, listener1->updates[0].mState);
-
- // Check StateTracker was updated by querying for state.
- HashableDimensionKey queryKey;
- getPartialWakelockKey(1001 /* uid */, "tag1", &queryKey);
- EXPECT_EQ(WakelockStateChanged::ACQUIRE,
- getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey));
-
- // No state stored for this query key.
- HashableDimensionKey queryKey2;
- getPartialWakelockKey(1002 /* uid */, "tag1", &queryKey2);
- EXPECT_EQ(WakelockStateChanged::RELEASE,
- getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey2));
-
- // Partial query fails.
- HashableDimensionKey queryKey3;
- getPartialWakelockKey(1001 /* uid */, &queryKey3);
- EXPECT_EQ(WakelockStateChanged::RELEASE,
- getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey3));
-}
-
-/**
- * Test StateManager's onLogEvent and StateListener's onStateChanged correctly
- * updates listener for states with multiple primary keys.
- */
-TEST(StateTrackerTest, TestStateChangeMultiplePrimaryFields) {
- sp<TestStateListener> listener1 = new TestStateListener();
- StateManager mgr;
- mgr.registerListener(android::util::OVERLAY_STATE_CHANGED, listener1);
-
- // log event
- std::shared_ptr<LogEvent> event =
- buildOverlayEvent(1000 /* uid */, "package1", 1); // state: ENTERED
- mgr.onLogEvent(*event);
-
- // check listener was updated
- EXPECT_EQ(1, listener1->updates.size());
- EXPECT_EQ(1000, listener1->updates[0].mKey.getValues()[0].mValue.int_value);
- EXPECT_EQ(1, listener1->updates[0].mState);
-
- // check StateTracker was updated by querying for state
- HashableDimensionKey queryKey;
- getOverlayKey(1000 /* uid */, "package1", &queryKey);
- EXPECT_EQ(OverlayStateChanged::ENTERED,
- getStateInt(mgr, android::util::OVERLAY_STATE_CHANGED, queryKey));
-}
-
-/**
- * Test StateManager's onLogEvent and StateListener's onStateChanged
- * when there is an error extracting state from log event. Listener is not
- * updated of state change.
- */
-TEST(StateTrackerTest, TestStateChangeEventError) {
- sp<TestStateListener> listener1 = new TestStateListener();
- StateManager mgr;
- mgr.registerListener(android::util::OVERLAY_STATE_CHANGED, listener1);
-
- // log event
- std::shared_ptr<LogEvent> event1 =
- buildIncorrectOverlayEvent(1000 /* uid */, "package1", 1 /* state */);
- std::shared_ptr<LogEvent> event2 = buildOverlayEventBadStateType(1001 /* uid */, "package2");
-
- // check listener was updated
- mgr.onLogEvent(*event1);
- EXPECT_EQ(0, listener1->updates.size());
- mgr.onLogEvent(*event2);
- EXPECT_EQ(0, listener1->updates.size());
-}
-
-TEST(StateTrackerTest, TestStateQuery) {
- sp<TestStateListener> listener1 = new TestStateListener();
- sp<TestStateListener> listener2 = new TestStateListener();
- sp<TestStateListener> listener3 = new TestStateListener();
- sp<TestStateListener> listener4 = new TestStateListener();
- StateManager mgr;
- mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener1);
- mgr.registerListener(android::util::UID_PROCESS_STATE_CHANGED, listener2);
- mgr.registerListener(android::util::OVERLAY_STATE_CHANGED, listener3);
- mgr.registerListener(android::util::WAKELOCK_STATE_CHANGED, listener4);
-
- std::shared_ptr<LogEvent> event1 = buildUidProcessEvent(
- 1000,
- android::app::ProcessStateEnum::PROCESS_STATE_TOP); // state value: 1002
- std::shared_ptr<LogEvent> event2 = buildUidProcessEvent(
- 1001,
- android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE); // state value:
- // 1003
- std::shared_ptr<LogEvent> event3 = buildUidProcessEvent(
- 1002,
- android::app::ProcessStateEnum::PROCESS_STATE_PERSISTENT); // state value: 1000
- std::shared_ptr<LogEvent> event4 = buildUidProcessEvent(
- 1001,
- android::app::ProcessStateEnum::PROCESS_STATE_TOP); // state value: 1002
- std::shared_ptr<LogEvent> event5 =
- buildScreenEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON);
- std::shared_ptr<LogEvent> event6 =
- buildOverlayEvent(1000, "package1", OverlayStateChanged::ENTERED);
- std::shared_ptr<LogEvent> event7 =
- buildOverlayEvent(1000, "package2", OverlayStateChanged::EXITED);
- std::shared_ptr<LogEvent> event8 = buildPartialWakelockEvent(1005, "tag1", true);
- std::shared_ptr<LogEvent> event9 = buildPartialWakelockEvent(1005, "tag2", false);
-
- mgr.onLogEvent(*event1);
- mgr.onLogEvent(*event2);
- mgr.onLogEvent(*event3);
- mgr.onLogEvent(*event5);
- mgr.onLogEvent(*event5);
- mgr.onLogEvent(*event6);
- mgr.onLogEvent(*event7);
- mgr.onLogEvent(*event8);
- mgr.onLogEvent(*event9);
-
- // Query for UidProcessState of uid 1001
- HashableDimensionKey queryKey1;
- getUidProcessKey(1001, &queryKey1);
- EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE,
- getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED, queryKey1));
-
- // Query for UidProcessState of uid 1004 - not in state map
- HashableDimensionKey queryKey2;
- getUidProcessKey(1004, &queryKey2);
- EXPECT_EQ(-1, getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED,
- queryKey2)); // default state
-
- // Query for UidProcessState of uid 1001 - after change in state
- mgr.onLogEvent(*event4);
- EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_TOP,
- getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED, queryKey1));
-
- // Query for ScreenState
- EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
- getStateInt(mgr, android::util::SCREEN_STATE_CHANGED, DEFAULT_DIMENSION_KEY));
-
- // Query for OverlayState of uid 1000, package name "package2"
- HashableDimensionKey queryKey3;
- getOverlayKey(1000, "package2", &queryKey3);
- EXPECT_EQ(OverlayStateChanged::EXITED,
- getStateInt(mgr, android::util::OVERLAY_STATE_CHANGED, queryKey3));
-
- // Query for WakelockState of uid 1005, tag 2
- HashableDimensionKey queryKey4;
- getPartialWakelockKey(1005, "tag2", &queryKey4);
- EXPECT_EQ(WakelockStateChanged::RELEASE,
- getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey4));
-
- // Query for WakelockState of uid 1005, tag 1
- HashableDimensionKey queryKey5;
- getPartialWakelockKey(1005, "tag1", &queryKey5);
- EXPECT_EQ(WakelockStateChanged::ACQUIRE,
- getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey5));
-}
+// TODO(b/149590301): Update these tests to use new socket schema.
+///**
+// * Test a binary state atom with nested counting.
+// *
+// * To go from an "ON" state to an "OFF" state with nested counting, we must see
+// * an equal number of "OFF" events as "ON" events.
+// * For example, ACQUIRE, ACQUIRE, RELEASE will still be in the ACQUIRE state.
+// * ACQUIRE, ACQUIRE, RELEASE, RELEASE will be in the RELEASE state.
+// */
+//TEST(StateTrackerTest, TestStateChangeNested) {
+// sp<TestStateListener> listener = new TestStateListener();
+// StateManager mgr;
+// mgr.registerListener(android::util::WAKELOCK_STATE_CHANGED, listener);
+//
+// std::shared_ptr<LogEvent> event1 =
+// buildPartialWakelockEvent(1000 /* uid */, "tag", true /*acquire*/);
+// mgr.onLogEvent(*event1);
+// EXPECT_EQ(1, listener->updates.size());
+// EXPECT_EQ(1000, listener->updates[0].mKey.getValues()[0].mValue.int_value);
+// EXPECT_EQ(1, listener->updates[0].mState);
+// listener->updates.clear();
+//
+// std::shared_ptr<LogEvent> event2 =
+// buildPartialWakelockEvent(1000 /* uid */, "tag", true /*acquire*/);
+// mgr.onLogEvent(*event2);
+// EXPECT_EQ(0, listener->updates.size());
+//
+// std::shared_ptr<LogEvent> event3 =
+// buildPartialWakelockEvent(1000 /* uid */, "tag", false /*release*/);
+// mgr.onLogEvent(*event3);
+// EXPECT_EQ(0, listener->updates.size());
+//
+// std::shared_ptr<LogEvent> event4 =
+// buildPartialWakelockEvent(1000 /* uid */, "tag", false /*release*/);
+// mgr.onLogEvent(*event4);
+// EXPECT_EQ(1, listener->updates.size());
+// EXPECT_EQ(1000, listener->updates[0].mKey.getValues()[0].mValue.int_value);
+// EXPECT_EQ(0, listener->updates[0].mState);
+//}
+//
+///**
+// * Test a state atom with a reset state.
+// *
+// * If the reset state value is seen, every state in the map is set to the default
+// * state and every listener is notified.
+// */
+//TEST(StateTrackerTest, TestStateChangeReset) {
+// sp<TestStateListener> listener = new TestStateListener();
+// StateManager mgr;
+// mgr.registerListener(android::util::BLE_SCAN_STATE_CHANGED, listener);
+//
+// std::shared_ptr<LogEvent> event1 =
+// buildBleScanEvent(1000 /* uid */, true /*acquire*/, false /*reset*/);
+// mgr.onLogEvent(*event1);
+// EXPECT_EQ(1, listener->updates.size());
+// EXPECT_EQ(1000, listener->updates[0].mKey.getValues()[0].mValue.int_value);
+// EXPECT_EQ(BleScanStateChanged::ON, listener->updates[0].mState);
+// listener->updates.clear();
+//
+// std::shared_ptr<LogEvent> event2 =
+// buildBleScanEvent(2000 /* uid */, true /*acquire*/, false /*reset*/);
+// mgr.onLogEvent(*event2);
+// EXPECT_EQ(1, listener->updates.size());
+// EXPECT_EQ(2000, listener->updates[0].mKey.getValues()[0].mValue.int_value);
+// EXPECT_EQ(BleScanStateChanged::ON, listener->updates[0].mState);
+// listener->updates.clear();
+//
+// std::shared_ptr<LogEvent> event3 =
+// buildBleScanEvent(2000 /* uid */, false /*acquire*/, true /*reset*/);
+// mgr.onLogEvent(*event3);
+// EXPECT_EQ(2, listener->updates.size());
+// EXPECT_EQ(BleScanStateChanged::OFF, listener->updates[0].mState);
+// EXPECT_EQ(BleScanStateChanged::OFF, listener->updates[1].mState);
+//}
+//
+///**
+// * Test StateManager's onLogEvent and StateListener's onStateChanged correctly
+// * updates listener for states without primary keys.
+// */
+//TEST(StateTrackerTest, TestStateChangeNoPrimaryFields) {
+// sp<TestStateListener> listener1 = new TestStateListener();
+// StateManager mgr;
+// mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener1);
+//
+// // log event
+// std::shared_ptr<LogEvent> event =
+// buildScreenEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON);
+// mgr.onLogEvent(*event);
+//
+// // check listener was updated
+// EXPECT_EQ(1, listener1->updates.size());
+// EXPECT_EQ(DEFAULT_DIMENSION_KEY, listener1->updates[0].mKey);
+// EXPECT_EQ(2, listener1->updates[0].mState);
+//
+// // check StateTracker was updated by querying for state
+// HashableDimensionKey queryKey = DEFAULT_DIMENSION_KEY;
+// EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+// getStateInt(mgr, android::util::SCREEN_STATE_CHANGED, queryKey));
+//}
+//
+///**
+// * Test StateManager's onLogEvent and StateListener's onStateChanged correctly
+// * updates listener for states with one primary key.
+// */
+//TEST(StateTrackerTest, TestStateChangeOnePrimaryField) {
+// sp<TestStateListener> listener1 = new TestStateListener();
+// StateManager mgr;
+// mgr.registerListener(android::util::UID_PROCESS_STATE_CHANGED, listener1);
+//
+// // log event
+// std::shared_ptr<LogEvent> event =
+// buildUidProcessEvent(1000 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_TOP);
+// mgr.onLogEvent(*event);
+//
+// // check listener was updated
+// EXPECT_EQ(1, listener1->updates.size());
+// EXPECT_EQ(1000, listener1->updates[0].mKey.getValues()[0].mValue.int_value);
+// EXPECT_EQ(1002, listener1->updates[0].mState);
+//
+// // check StateTracker was updated by querying for state
+// HashableDimensionKey queryKey;
+// getUidProcessKey(1000 /* uid */, &queryKey);
+// EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_TOP,
+// getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED, queryKey));
+//}
+//
+//TEST(StateTrackerTest, TestStateChangePrimaryFieldAttrChain) {
+// sp<TestStateListener> listener1 = new TestStateListener();
+// StateManager mgr;
+// mgr.registerListener(android::util::WAKELOCK_STATE_CHANGED, listener1);
+//
+// // Log event.
+// std::shared_ptr<LogEvent> event =
+// buildPartialWakelockEvent(1001 /* uid */, "tag1", true /* acquire */);
+// mgr.onLogEvent(*event);
+//
+// EXPECT_EQ(1, mgr.getStateTrackersCount());
+// EXPECT_EQ(1, mgr.getListenersCount(android::util::WAKELOCK_STATE_CHANGED));
+//
+// // Check listener was updated.
+// EXPECT_EQ(1, listener1->updates.size());
+// EXPECT_EQ(3, listener1->updates[0].mKey.getValues().size());
+// EXPECT_EQ(1001, listener1->updates[0].mKey.getValues()[0].mValue.int_value);
+// EXPECT_EQ(1, listener1->updates[0].mKey.getValues()[1].mValue.int_value);
+// EXPECT_EQ("tag1", listener1->updates[0].mKey.getValues()[2].mValue.str_value);
+// EXPECT_EQ(WakelockStateChanged::ACQUIRE, listener1->updates[0].mState);
+//
+// // Check StateTracker was updated by querying for state.
+// HashableDimensionKey queryKey;
+// getPartialWakelockKey(1001 /* uid */, "tag1", &queryKey);
+// EXPECT_EQ(WakelockStateChanged::ACQUIRE,
+// getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey));
+//
+// // No state stored for this query key.
+// HashableDimensionKey queryKey2;
+// getPartialWakelockKey(1002 /* uid */, "tag1", &queryKey2);
+// EXPECT_EQ(WakelockStateChanged::RELEASE,
+// getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey2));
+//
+// // Partial query fails.
+// HashableDimensionKey queryKey3;
+// getPartialWakelockKey(1001 /* uid */, &queryKey3);
+// EXPECT_EQ(WakelockStateChanged::RELEASE,
+// getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey3));
+//}
+//
+///**
+// * Test StateManager's onLogEvent and StateListener's onStateChanged correctly
+// * updates listener for states with multiple primary keys.
+// */
+//TEST(StateTrackerTest, TestStateChangeMultiplePrimaryFields) {
+// sp<TestStateListener> listener1 = new TestStateListener();
+// StateManager mgr;
+// mgr.registerListener(android::util::OVERLAY_STATE_CHANGED, listener1);
+//
+// // log event
+// std::shared_ptr<LogEvent> event =
+// buildOverlayEvent(1000 /* uid */, "package1", 1); // state: ENTERED
+// mgr.onLogEvent(*event);
+//
+// // check listener was updated
+// EXPECT_EQ(1, listener1->updates.size());
+// EXPECT_EQ(1000, listener1->updates[0].mKey.getValues()[0].mValue.int_value);
+// EXPECT_EQ(1, listener1->updates[0].mState);
+//
+// // check StateTracker was updated by querying for state
+// HashableDimensionKey queryKey;
+// getOverlayKey(1000 /* uid */, "package1", &queryKey);
+// EXPECT_EQ(OverlayStateChanged::ENTERED,
+// getStateInt(mgr, android::util::OVERLAY_STATE_CHANGED, queryKey));
+//}
+//
+///**
+// * Test StateManager's onLogEvent and StateListener's onStateChanged
+// * when there is an error extracting state from log event. Listener is not
+// * updated of state change.
+// */
+//TEST(StateTrackerTest, TestStateChangeEventError) {
+// sp<TestStateListener> listener1 = new TestStateListener();
+// StateManager mgr;
+// mgr.registerListener(android::util::OVERLAY_STATE_CHANGED, listener1);
+//
+// // log event
+// std::shared_ptr<LogEvent> event1 =
+// buildIncorrectOverlayEvent(1000 /* uid */, "package1", 1 /* state */);
+// std::shared_ptr<LogEvent> event2 = buildOverlayEventBadStateType(1001 /* uid */, "package2");
+//
+// // check listener was updated
+// mgr.onLogEvent(*event1);
+// EXPECT_EQ(0, listener1->updates.size());
+// mgr.onLogEvent(*event2);
+// EXPECT_EQ(0, listener1->updates.size());
+//}
+//
+//TEST(StateTrackerTest, TestStateQuery) {
+// sp<TestStateListener> listener1 = new TestStateListener();
+// sp<TestStateListener> listener2 = new TestStateListener();
+// sp<TestStateListener> listener3 = new TestStateListener();
+// sp<TestStateListener> listener4 = new TestStateListener();
+// StateManager mgr;
+// mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener1);
+// mgr.registerListener(android::util::UID_PROCESS_STATE_CHANGED, listener2);
+// mgr.registerListener(android::util::OVERLAY_STATE_CHANGED, listener3);
+// mgr.registerListener(android::util::WAKELOCK_STATE_CHANGED, listener4);
+//
+// std::shared_ptr<LogEvent> event1 = buildUidProcessEvent(
+// 1000,
+// android::app::ProcessStateEnum::PROCESS_STATE_TOP); // state value: 1002
+// std::shared_ptr<LogEvent> event2 = buildUidProcessEvent(
+// 1001,
+// android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE); // state value:
+// // 1003
+// std::shared_ptr<LogEvent> event3 = buildUidProcessEvent(
+// 1002,
+// android::app::ProcessStateEnum::PROCESS_STATE_PERSISTENT); // state value: 1000
+// std::shared_ptr<LogEvent> event4 = buildUidProcessEvent(
+// 1001,
+// android::app::ProcessStateEnum::PROCESS_STATE_TOP); // state value: 1002
+// std::shared_ptr<LogEvent> event5 =
+// buildScreenEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON);
+// std::shared_ptr<LogEvent> event6 =
+// buildOverlayEvent(1000, "package1", OverlayStateChanged::ENTERED);
+// std::shared_ptr<LogEvent> event7 =
+// buildOverlayEvent(1000, "package2", OverlayStateChanged::EXITED);
+// std::shared_ptr<LogEvent> event8 = buildPartialWakelockEvent(1005, "tag1", true);
+// std::shared_ptr<LogEvent> event9 = buildPartialWakelockEvent(1005, "tag2", false);
+//
+// mgr.onLogEvent(*event1);
+// mgr.onLogEvent(*event2);
+// mgr.onLogEvent(*event3);
+// mgr.onLogEvent(*event5);
+// mgr.onLogEvent(*event5);
+// mgr.onLogEvent(*event6);
+// mgr.onLogEvent(*event7);
+// mgr.onLogEvent(*event8);
+// mgr.onLogEvent(*event9);
+//
+// // Query for UidProcessState of uid 1001
+// HashableDimensionKey queryKey1;
+// getUidProcessKey(1001, &queryKey1);
+// EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE,
+// getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED, queryKey1));
+//
+// // Query for UidProcessState of uid 1004 - not in state map
+// HashableDimensionKey queryKey2;
+// getUidProcessKey(1004, &queryKey2);
+// EXPECT_EQ(-1, getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED,
+// queryKey2)); // default state
+//
+// // Query for UidProcessState of uid 1001 - after change in state
+// mgr.onLogEvent(*event4);
+// EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_TOP,
+// getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED, queryKey1));
+//
+// // Query for ScreenState
+// EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+// getStateInt(mgr, android::util::SCREEN_STATE_CHANGED, DEFAULT_DIMENSION_KEY));
+//
+// // Query for OverlayState of uid 1000, package name "package2"
+// HashableDimensionKey queryKey3;
+// getOverlayKey(1000, "package2", &queryKey3);
+// EXPECT_EQ(OverlayStateChanged::EXITED,
+// getStateInt(mgr, android::util::OVERLAY_STATE_CHANGED, queryKey3));
+//
+// // Query for WakelockState of uid 1005, tag 2
+// HashableDimensionKey queryKey4;
+// getPartialWakelockKey(1005, "tag2", &queryKey4);
+// EXPECT_EQ(WakelockStateChanged::RELEASE,
+// getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey4));
+//
+// // Query for WakelockState of uid 1005, tag 1
+// HashableDimensionKey queryKey5;
+// getPartialWakelockKey(1005, "tag1", &queryKey5);
+// EXPECT_EQ(WakelockStateChanged::ACQUIRE,
+// getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey5));
+//}
} // namespace statsd
} // namespace os
diff --git a/cmds/statsd/tests/statsd_test_util.cpp b/cmds/statsd/tests/statsd_test_util.cpp
index 6958218..2bfce9b 100644
--- a/cmds/statsd/tests/statsd_test_util.cpp
+++ b/cmds/statsd/tests/statsd_test_util.cpp
@@ -409,180 +409,181 @@
return dimensions;
}
-std::unique_ptr<LogEvent> CreateScreenStateChangedEvent(
- const android::view::DisplayStateEnum state, uint64_t timestampNs) {
- auto event = std::make_unique<LogEvent>(android::util::SCREEN_STATE_CHANGED, timestampNs);
- EXPECT_TRUE(event->write(state));
- event->init();
- return event;
-}
-
-std::unique_ptr<LogEvent> CreateBatterySaverOnEvent(uint64_t timestampNs) {
- auto event = std::make_unique<LogEvent>(
- android::util::BATTERY_SAVER_MODE_STATE_CHANGED, timestampNs);
- EXPECT_TRUE(event->write(BatterySaverModeStateChanged::ON));
- event->init();
- return event;
-}
-
-std::unique_ptr<LogEvent> CreateBatterySaverOffEvent(uint64_t timestampNs) {
- auto event = std::make_unique<LogEvent>(
- android::util::BATTERY_SAVER_MODE_STATE_CHANGED, timestampNs);
- EXPECT_TRUE(event->write(BatterySaverModeStateChanged::OFF));
- event->init();
- return event;
-}
-
-std::unique_ptr<LogEvent> CreateScreenBrightnessChangedEvent(
- int level, uint64_t timestampNs) {
- auto event = std::make_unique<LogEvent>(android::util::SCREEN_BRIGHTNESS_CHANGED, timestampNs);
- EXPECT_TRUE(event->write(level));
- event->init();
- return event;
-
-}
-
-std::unique_ptr<LogEvent> CreateScheduledJobStateChangedEvent(
- const std::vector<AttributionNodeInternal>& attributions, const string& jobName,
- const ScheduledJobStateChanged::State state, uint64_t timestampNs) {
- auto event = std::make_unique<LogEvent>(android::util::SCHEDULED_JOB_STATE_CHANGED, timestampNs);
- event->write(attributions);
- event->write(jobName);
- event->write(state);
- event->init();
- return event;
-}
-
-std::unique_ptr<LogEvent> CreateStartScheduledJobEvent(
- const std::vector<AttributionNodeInternal>& attributions,
- const string& name, uint64_t timestampNs) {
- return CreateScheduledJobStateChangedEvent(
- attributions, name, ScheduledJobStateChanged::STARTED, timestampNs);
-}
-
-// Create log event when scheduled job finishes.
-std::unique_ptr<LogEvent> CreateFinishScheduledJobEvent(
- const std::vector<AttributionNodeInternal>& attributions,
- const string& name, uint64_t timestampNs) {
- return CreateScheduledJobStateChangedEvent(
- attributions, name, ScheduledJobStateChanged::FINISHED, timestampNs);
-}
-
-std::unique_ptr<LogEvent> CreateWakelockStateChangedEvent(
- const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
- const WakelockStateChanged::State state, uint64_t timestampNs) {
- auto event = std::make_unique<LogEvent>(android::util::WAKELOCK_STATE_CHANGED, timestampNs);
- event->write(attributions);
- event->write(android::os::WakeLockLevelEnum::PARTIAL_WAKE_LOCK);
- event->write(wakelockName);
- event->write(state);
- event->init();
- return event;
-}
-
-std::unique_ptr<LogEvent> CreateAcquireWakelockEvent(
- const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
- uint64_t timestampNs) {
- return CreateWakelockStateChangedEvent(
- attributions, wakelockName, WakelockStateChanged::ACQUIRE, timestampNs);
-}
-
-std::unique_ptr<LogEvent> CreateReleaseWakelockEvent(
- const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
- uint64_t timestampNs) {
- return CreateWakelockStateChangedEvent(
- attributions, wakelockName, WakelockStateChanged::RELEASE, timestampNs);
-}
-
-std::unique_ptr<LogEvent> CreateActivityForegroundStateChangedEvent(
- const int uid, const ActivityForegroundStateChanged::State state, uint64_t timestampNs) {
- auto event = std::make_unique<LogEvent>(
- android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, timestampNs);
- event->write(uid);
- event->write("pkg_name");
- event->write("class_name");
- event->write(state);
- event->init();
- return event;
-}
-
-std::unique_ptr<LogEvent> CreateMoveToBackgroundEvent(const int uid, uint64_t timestampNs) {
- return CreateActivityForegroundStateChangedEvent(
- uid, ActivityForegroundStateChanged::BACKGROUND, timestampNs);
-}
-
-std::unique_ptr<LogEvent> CreateMoveToForegroundEvent(const int uid, uint64_t timestampNs) {
- return CreateActivityForegroundStateChangedEvent(
- uid, ActivityForegroundStateChanged::FOREGROUND, timestampNs);
-}
-
-std::unique_ptr<LogEvent> CreateSyncStateChangedEvent(
- const std::vector<AttributionNodeInternal>& attributions, const string& name,
- const SyncStateChanged::State state, uint64_t timestampNs) {
- auto event = std::make_unique<LogEvent>(android::util::SYNC_STATE_CHANGED, timestampNs);
- event->write(attributions);
- event->write(name);
- event->write(state);
- event->init();
- return event;
-}
-
-std::unique_ptr<LogEvent> CreateSyncStartEvent(
- const std::vector<AttributionNodeInternal>& attributions, const string& name,
- uint64_t timestampNs) {
- return CreateSyncStateChangedEvent(attributions, name, SyncStateChanged::ON, timestampNs);
-}
-
-std::unique_ptr<LogEvent> CreateSyncEndEvent(
- const std::vector<AttributionNodeInternal>& attributions, const string& name,
- uint64_t timestampNs) {
- return CreateSyncStateChangedEvent(attributions, name, SyncStateChanged::OFF, timestampNs);
-}
-
-std::unique_ptr<LogEvent> CreateProcessLifeCycleStateChangedEvent(
- const int uid, const ProcessLifeCycleStateChanged::State state, uint64_t timestampNs) {
- auto logEvent = std::make_unique<LogEvent>(
- android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, timestampNs);
- logEvent->write(uid);
- logEvent->write("");
- logEvent->write(state);
- logEvent->init();
- return logEvent;
-}
-
-std::unique_ptr<LogEvent> CreateAppCrashEvent(const int uid, uint64_t timestampNs) {
- return CreateProcessLifeCycleStateChangedEvent(
- uid, ProcessLifeCycleStateChanged::CRASHED, timestampNs);
-}
-
-std::unique_ptr<LogEvent> CreateAppCrashOccurredEvent(const int uid, uint64_t timestampNs) {
- auto event = std::make_unique<LogEvent>(android::util::APP_CRASH_OCCURRED, timestampNs);
- event->write(uid);
- event->write("eventType");
- event->write("processName");
- event->init();
- return event;
-}
-
-std::unique_ptr<LogEvent> CreateIsolatedUidChangedEvent(
- int isolatedUid, int hostUid, bool is_create, uint64_t timestampNs) {
- auto logEvent = std::make_unique<LogEvent>(
- android::util::ISOLATED_UID_CHANGED, timestampNs);
- logEvent->write(hostUid);
- logEvent->write(isolatedUid);
- logEvent->write(is_create);
- logEvent->init();
- return logEvent;
-}
-
-std::unique_ptr<LogEvent> CreateUidProcessStateChangedEvent(
- int uid, const android::app::ProcessStateEnum state, uint64_t timestampNs) {
- auto event = std::make_unique<LogEvent>(android::util::UID_PROCESS_STATE_CHANGED, timestampNs);
- event->write(uid);
- event->write(state);
- event->init();
- return event;
-}
+// TODO(b/149590301): Update these helpers to use new socket schema.
+//std::unique_ptr<LogEvent> CreateScreenStateChangedEvent(
+// const android::view::DisplayStateEnum state, uint64_t timestampNs) {
+// auto event = std::make_unique<LogEvent>(android::util::SCREEN_STATE_CHANGED, timestampNs);
+// EXPECT_TRUE(event->write(state));
+// event->init();
+// return event;
+//}
+//
+//std::unique_ptr<LogEvent> CreateBatterySaverOnEvent(uint64_t timestampNs) {
+// auto event = std::make_unique<LogEvent>(
+// android::util::BATTERY_SAVER_MODE_STATE_CHANGED, timestampNs);
+// EXPECT_TRUE(event->write(BatterySaverModeStateChanged::ON));
+// event->init();
+// return event;
+//}
+//
+//std::unique_ptr<LogEvent> CreateBatterySaverOffEvent(uint64_t timestampNs) {
+// auto event = std::make_unique<LogEvent>(
+// android::util::BATTERY_SAVER_MODE_STATE_CHANGED, timestampNs);
+// EXPECT_TRUE(event->write(BatterySaverModeStateChanged::OFF));
+// event->init();
+// return event;
+//}
+//
+//std::unique_ptr<LogEvent> CreateScreenBrightnessChangedEvent(
+// int level, uint64_t timestampNs) {
+// auto event = std::make_unique<LogEvent>(android::util::SCREEN_BRIGHTNESS_CHANGED, timestampNs);
+// EXPECT_TRUE(event->write(level));
+// event->init();
+// return event;
+//
+//}
+//
+//std::unique_ptr<LogEvent> CreateScheduledJobStateChangedEvent(
+// const std::vector<AttributionNodeInternal>& attributions, const string& jobName,
+// const ScheduledJobStateChanged::State state, uint64_t timestampNs) {
+// auto event = std::make_unique<LogEvent>(android::util::SCHEDULED_JOB_STATE_CHANGED, timestampNs);
+// event->write(attributions);
+// event->write(jobName);
+// event->write(state);
+// event->init();
+// return event;
+//}
+//
+//std::unique_ptr<LogEvent> CreateStartScheduledJobEvent(
+// const std::vector<AttributionNodeInternal>& attributions,
+// const string& name, uint64_t timestampNs) {
+// return CreateScheduledJobStateChangedEvent(
+// attributions, name, ScheduledJobStateChanged::STARTED, timestampNs);
+//}
+//
+//// Create log event when scheduled job finishes.
+//std::unique_ptr<LogEvent> CreateFinishScheduledJobEvent(
+// const std::vector<AttributionNodeInternal>& attributions,
+// const string& name, uint64_t timestampNs) {
+// return CreateScheduledJobStateChangedEvent(
+// attributions, name, ScheduledJobStateChanged::FINISHED, timestampNs);
+//}
+//
+//std::unique_ptr<LogEvent> CreateWakelockStateChangedEvent(
+// const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
+// const WakelockStateChanged::State state, uint64_t timestampNs) {
+// auto event = std::make_unique<LogEvent>(android::util::WAKELOCK_STATE_CHANGED, timestampNs);
+// event->write(attributions);
+// event->write(android::os::WakeLockLevelEnum::PARTIAL_WAKE_LOCK);
+// event->write(wakelockName);
+// event->write(state);
+// event->init();
+// return event;
+//}
+//
+//std::unique_ptr<LogEvent> CreateAcquireWakelockEvent(
+// const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
+// uint64_t timestampNs) {
+// return CreateWakelockStateChangedEvent(
+// attributions, wakelockName, WakelockStateChanged::ACQUIRE, timestampNs);
+//}
+//
+//std::unique_ptr<LogEvent> CreateReleaseWakelockEvent(
+// const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
+// uint64_t timestampNs) {
+// return CreateWakelockStateChangedEvent(
+// attributions, wakelockName, WakelockStateChanged::RELEASE, timestampNs);
+//}
+//
+//std::unique_ptr<LogEvent> CreateActivityForegroundStateChangedEvent(
+// const int uid, const ActivityForegroundStateChanged::State state, uint64_t timestampNs) {
+// auto event = std::make_unique<LogEvent>(
+// android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, timestampNs);
+// event->write(uid);
+// event->write("pkg_name");
+// event->write("class_name");
+// event->write(state);
+// event->init();
+// return event;
+//}
+//
+//std::unique_ptr<LogEvent> CreateMoveToBackgroundEvent(const int uid, uint64_t timestampNs) {
+// return CreateActivityForegroundStateChangedEvent(
+// uid, ActivityForegroundStateChanged::BACKGROUND, timestampNs);
+//}
+//
+//std::unique_ptr<LogEvent> CreateMoveToForegroundEvent(const int uid, uint64_t timestampNs) {
+// return CreateActivityForegroundStateChangedEvent(
+// uid, ActivityForegroundStateChanged::FOREGROUND, timestampNs);
+//}
+//
+//std::unique_ptr<LogEvent> CreateSyncStateChangedEvent(
+// const std::vector<AttributionNodeInternal>& attributions, const string& name,
+// const SyncStateChanged::State state, uint64_t timestampNs) {
+// auto event = std::make_unique<LogEvent>(android::util::SYNC_STATE_CHANGED, timestampNs);
+// event->write(attributions);
+// event->write(name);
+// event->write(state);
+// event->init();
+// return event;
+//}
+//
+//std::unique_ptr<LogEvent> CreateSyncStartEvent(
+// const std::vector<AttributionNodeInternal>& attributions, const string& name,
+// uint64_t timestampNs) {
+// return CreateSyncStateChangedEvent(attributions, name, SyncStateChanged::ON, timestampNs);
+//}
+//
+//std::unique_ptr<LogEvent> CreateSyncEndEvent(
+// const std::vector<AttributionNodeInternal>& attributions, const string& name,
+// uint64_t timestampNs) {
+// return CreateSyncStateChangedEvent(attributions, name, SyncStateChanged::OFF, timestampNs);
+//}
+//
+//std::unique_ptr<LogEvent> CreateProcessLifeCycleStateChangedEvent(
+// const int uid, const ProcessLifeCycleStateChanged::State state, uint64_t timestampNs) {
+// auto logEvent = std::make_unique<LogEvent>(
+// android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, timestampNs);
+// logEvent->write(uid);
+// logEvent->write("");
+// logEvent->write(state);
+// logEvent->init();
+// return logEvent;
+//}
+//
+//std::unique_ptr<LogEvent> CreateAppCrashEvent(const int uid, uint64_t timestampNs) {
+// return CreateProcessLifeCycleStateChangedEvent(
+// uid, ProcessLifeCycleStateChanged::CRASHED, timestampNs);
+//}
+//
+//std::unique_ptr<LogEvent> CreateAppCrashOccurredEvent(const int uid, uint64_t timestampNs) {
+// auto event = std::make_unique<LogEvent>(android::util::APP_CRASH_OCCURRED, timestampNs);
+// event->write(uid);
+// event->write("eventType");
+// event->write("processName");
+// event->init();
+// return event;
+//}
+//
+//std::unique_ptr<LogEvent> CreateIsolatedUidChangedEvent(
+// int isolatedUid, int hostUid, bool is_create, uint64_t timestampNs) {
+// auto logEvent = std::make_unique<LogEvent>(
+// android::util::ISOLATED_UID_CHANGED, timestampNs);
+// logEvent->write(hostUid);
+// logEvent->write(isolatedUid);
+// logEvent->write(is_create);
+// logEvent->init();
+// return logEvent;
+//}
+//
+//std::unique_ptr<LogEvent> CreateUidProcessStateChangedEvent(
+// int uid, const android::app::ProcessStateEnum state, uint64_t timestampNs) {
+// auto event = std::make_unique<LogEvent>(android::util::UID_PROCESS_STATE_CHANGED, timestampNs);
+// event->write(uid);
+// event->write(state);
+// event->init();
+// return event;
+//}
sp<StatsLogProcessor> CreateStatsLogProcessor(const int64_t timeBaseNs, const int64_t currentTimeNs,
const StatsdConfig& config, const ConfigKey& key,
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index b7a35f7..83d609c 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -2414,4 +2414,55 @@
return mTimestamp;
};
}
+
+ /**
+ * When {@link AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is enabled, this
+ * function requests that touch interactions starting in the specified region of the screen
+ * bypass the gesture detector. There can only be one gesture detection passthrough region per
+ * display. Requesting a new gesture detection passthrough region clears the existing one. To
+ * disable this passthrough and return to the original behavior, pass in an empty region. When
+ * {@link AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is disabled this
+ * function has no effect.
+ *
+ * @param displayId The display on which to set this region.
+ * @param region the region of the screen.
+ */
+ public void setGestureDetectionPassthroughRegion(int displayId, @NonNull Region region) {
+ Preconditions.checkNotNull(region, "region cannot be null");
+ final IAccessibilityServiceConnection connection =
+ AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
+ if (connection != null) {
+ try {
+ connection.setGestureDetectionPassthroughRegion(displayId, region);
+ } catch (RemoteException re) {
+ throw new RuntimeException(re);
+ }
+ }
+ }
+
+ /**
+ * When {@link AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is enabled, this
+ * function requests that touch interactions starting in the specified region of the screen
+ * bypass the touch explorer and go straight to the view hierarchy. There can only be one touch
+ * exploration passthrough region per display. Requesting a new touch explorationpassthrough
+ * region clears the existing one. To disable this passthrough and return to the original
+ * behavior, pass in an empty region. When {@link
+ * AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is disabled this function has
+ * no effect.
+ *
+ * @param displayId The display on which to set this region.
+ * @param region the region of the screen .
+ */
+ public void setTouchExplorationPassthroughRegion(int displayId, @NonNull Region region) {
+ Preconditions.checkNotNull(region, "region cannot be null");
+ final IAccessibilityServiceConnection connection =
+ AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
+ if (connection != null) {
+ try {
+ connection.setTouchExplorationPassthroughRegion(displayId, region);
+ } catch (RemoteException re) {
+ throw new RuntimeException(re);
+ }
+ }
+ }
}
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
index 9177d4d..0b3b9b2 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
@@ -111,4 +111,8 @@
int getWindowIdForLeashToken(IBinder token);
void takeScreenshot(int displayId, in RemoteCallback callback);
+
+ void setGestureDetectionPassthroughRegion(int displayId, in Region region);
+
+ void setTouchExplorationPassthroughRegion(int displayId, in Region region);
}
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 576b56f..32e7d84 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -6046,21 +6046,18 @@
/**
* Removes RemoteViews that were created for compatibility from {@param n}, if they did not
- * change. Also removes extenders on low ram devices, as
- * {@link android.service.notification.NotificationListenerService} services are disabled.
+ * change.
*
* @return {@param n}, if no stripping is needed, otherwise a stripped clone of {@param n}.
*
* @hide
*/
- public static Notification maybeCloneStrippedForDelivery(Notification n, boolean isLowRam,
- Context context) {
+ public static Notification maybeCloneStrippedForDelivery(Notification n) {
String templateClass = n.extras.getString(EXTRA_TEMPLATE);
// Only strip views for known Styles because we won't know how to
// re-create them otherwise.
- if (!isLowRam
- && !TextUtils.isEmpty(templateClass)
+ if (!TextUtils.isEmpty(templateClass)
&& getNotificationStyleClass(templateClass) == null) {
return n;
}
@@ -6077,8 +6074,7 @@
n.headsUpContentView.getSequenceNumber();
// Nothing to do here, no need to clone.
- if (!isLowRam
- && !stripContentView && !stripBigContentView && !stripHeadsUpContentView) {
+ if (!stripContentView && !stripBigContentView && !stripHeadsUpContentView) {
return n;
}
@@ -6095,15 +6091,6 @@
clone.headsUpContentView = null;
clone.extras.remove(EXTRA_REBUILD_HEADS_UP_CONTENT_VIEW_ACTION_COUNT);
}
- if (isLowRam) {
- String[] allowedServices = context.getResources().getStringArray(
- R.array.config_allowedManagedServicesOnLowRamDevices);
- if (allowedServices.length == 0) {
- clone.extras.remove(Notification.TvExtender.EXTRA_TV_EXTENDER);
- clone.extras.remove(WearableExtender.EXTRA_WEARABLE_EXTENSIONS);
- clone.extras.remove(CarExtender.EXTRA_CAR_EXTENDER);
- }
- }
return clone;
}
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 528b508..88edb05 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -592,10 +592,7 @@
}
notification.reduceImageSizes(mContext);
-
- ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
- boolean isLowRam = am.isLowRamDevice();
- return Builder.maybeCloneStrippedForDelivery(notification, isLowRam, mContext);
+ return Builder.maybeCloneStrippedForDelivery(notification);
}
private void fixLegacySmallIcon(Notification n, String pkg) {
diff --git a/core/java/android/app/compat/ChangeIdStateCache.java b/core/java/android/app/compat/ChangeIdStateCache.java
new file mode 100644
index 0000000..9ef63f6
--- /dev/null
+++ b/core/java/android/app/compat/ChangeIdStateCache.java
@@ -0,0 +1,86 @@
+/*
+ * 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 android.app.compat;
+
+import android.app.PropertyInvalidatedCache;
+import android.content.Context;
+import android.os.Binder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+
+import com.android.internal.compat.IPlatformCompat;
+
+/**
+ * Handles caching of calls to {@link com.android.internal.compat.IPlatformCompat}
+ * @hide
+ */
+public final class ChangeIdStateCache
+ extends PropertyInvalidatedCache<ChangeIdStateQuery, Boolean> {
+ private static final String CACHE_KEY = "cache_key.is_compat_change_enabled";
+ private static final int MAX_ENTRIES = 20;
+ private static boolean sDisabled = false;
+
+ /** @hide */
+ public ChangeIdStateCache() {
+ super(MAX_ENTRIES, CACHE_KEY);
+ }
+
+ /**
+ * Disable cache.
+ *
+ * <p>Should only be used in unit tests.
+ * @hide
+ */
+ public static void disable() {
+ sDisabled = true;
+ }
+
+ /**
+ * Invalidate the cache.
+ *
+ * <p>Can only be called by the system server process.
+ * @hide
+ */
+ public static void invalidate() {
+ if (!sDisabled) {
+ PropertyInvalidatedCache.invalidateCache(CACHE_KEY);
+ }
+ }
+
+ @Override
+ protected Boolean recompute(ChangeIdStateQuery query) {
+ IPlatformCompat platformCompat = IPlatformCompat.Stub.asInterface(
+ ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
+ final long token = Binder.clearCallingIdentity();
+ try {
+ if (query.type == ChangeIdStateQuery.QUERY_BY_PACKAGE_NAME) {
+ return platformCompat.isChangeEnabledByPackageName(query.changeId,
+ query.packageName,
+ query.userId);
+ } else if (query.type == ChangeIdStateQuery.QUERY_BY_UID) {
+ return platformCompat.isChangeEnabledByUid(query.changeId, query.uid);
+ } else {
+ throw new IllegalArgumentException("Invalid query type: " + query.type);
+ }
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ throw new IllegalStateException("Could not recompute value!");
+ }
+}
diff --git a/core/java/android/app/compat/ChangeIdStateQuery.java b/core/java/android/app/compat/ChangeIdStateQuery.java
new file mode 100644
index 0000000..2c4c120
--- /dev/null
+++ b/core/java/android/app/compat/ChangeIdStateQuery.java
@@ -0,0 +1,87 @@
+/*
+ * 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 android.app.compat;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+
+/**
+ * A key type for caching calls to {@link com.android.internal.compat.IPlatformCompat}
+ *
+ * <p>For {@link com.android.internal.compat.IPlatformCompat#isChangeEnabledByPackageName}
+ * and {@link com.android.internal.compat.IPlatformCompat#isChangeEnabledByUid}
+ *
+ * @hide
+ */
+final class ChangeIdStateQuery {
+
+ static final int QUERY_BY_PACKAGE_NAME = 0;
+ static final int QUERY_BY_UID = 1;
+ @IntDef({QUERY_BY_PACKAGE_NAME, QUERY_BY_UID})
+ @Retention(RetentionPolicy.SOURCE)
+ @interface QueryType {}
+
+ public @QueryType int type;
+ public long changeId;
+ public String packageName;
+ public int uid;
+ public int userId;
+
+ private ChangeIdStateQuery(@QueryType int type, long changeId, String packageName,
+ int uid, int userId) {
+ this.type = type;
+ this.changeId = changeId;
+ this.packageName = packageName;
+ this.uid = uid;
+ this.userId = userId;
+ }
+
+ static ChangeIdStateQuery byPackageName(long changeId, @NonNull String packageName,
+ int userId) {
+ return new ChangeIdStateQuery(QUERY_BY_PACKAGE_NAME, changeId, packageName, 0, userId);
+ }
+
+ static ChangeIdStateQuery byUid(long changeId, int uid) {
+ return new ChangeIdStateQuery(QUERY_BY_UID, changeId, null, uid, 0);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+ if ((other == null) || !(other instanceof ChangeIdStateQuery)) {
+ return false;
+ }
+ final ChangeIdStateQuery that = (ChangeIdStateQuery) other;
+ return this.type == that.type
+ && this.changeId == that.changeId
+ && Objects.equals(this.packageName, that.packageName)
+ && this.uid == that.uid
+ && this.userId == that.userId;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type, changeId, packageName, uid, userId);
+ }
+}
diff --git a/core/java/android/app/compat/CompatChanges.java b/core/java/android/app/compat/CompatChanges.java
index e289a27..0d5e45f 100644
--- a/core/java/android/app/compat/CompatChanges.java
+++ b/core/java/android/app/compat/CompatChanges.java
@@ -19,14 +19,8 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.compat.Compatibility;
-import android.content.Context;
-import android.os.Binder;
-import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.UserHandle;
-import com.android.internal.compat.IPlatformCompat;
-
/**
* CompatChanges APIs - to be used by platform code only (including mainline
* modules).
@@ -35,6 +29,7 @@
*/
@SystemApi
public final class CompatChanges {
+ private static final ChangeIdStateCache QUERY_CACHE = new ChangeIdStateCache();
private CompatChanges() {}
/**
@@ -69,17 +64,8 @@
*/
public static boolean isChangeEnabled(long changeId, @NonNull String packageName,
@NonNull UserHandle user) {
- IPlatformCompat platformCompat = IPlatformCompat.Stub.asInterface(
- ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
- final long token = Binder.clearCallingIdentity();
- try {
- return platformCompat.isChangeEnabledByPackageName(changeId, packageName,
- user.getIdentifier());
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- } finally {
- Binder.restoreCallingIdentity(token);
- }
+ return QUERY_CACHE.query(ChangeIdStateQuery.byPackageName(changeId, packageName,
+ user.getIdentifier()));
}
/**
@@ -101,15 +87,7 @@
* @return {@code true} if the change is enabled for the current app.
*/
public static boolean isChangeEnabled(long changeId, int uid) {
- IPlatformCompat platformCompat = IPlatformCompat.Stub.asInterface(
- ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
- final long token = Binder.clearCallingIdentity();
- try {
- return platformCompat.isChangeEnabledByUid(changeId, uid);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- } finally {
- Binder.restoreCallingIdentity(token);
- }
+ return QUERY_CACHE.query(ChangeIdStateQuery.byUid(changeId, uid));
}
+
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 2e591ca..acc4cb0 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -6478,6 +6478,21 @@
public static final int FLAG_ACTIVITY_MATCH_EXTERNAL = 0x00000800;
/**
+ * If set in an intent passed to {@link Context#startActivity Context.startActivity()}, this
+ * flag will only launch the intent if it resolves to a result that is not a browser. If no such
+ * result exists, an {@link ActivityNotFoundException} will be thrown.
+ */
+ public static final int FLAG_ACTIVITY_REQUIRE_NON_BROWSER = 0x00000400;
+
+ /**
+ * If set in an intent passed to {@link Context#startActivity Context.startActivity()}, this
+ * flag will only launch the intent if it resolves to a single result. If no such result exists
+ * or if the system chooser would otherwise be displayed, an {@link ActivityNotFoundException}
+ * will be thrown.
+ */
+ public static final int FLAG_ACTIVITY_REQUIRE_DEFAULT = 0x00000200;
+
+ /**
* If set, when sending a broadcast only registered receivers will be
* called -- no BroadcastReceiver components will be launched.
*/
diff --git a/core/java/android/content/om/OverlayInfo.java b/core/java/android/content/om/OverlayInfo.java
index a3487be..55a6cab 100644
--- a/core/java/android/content/om/OverlayInfo.java
+++ b/core/java/android/content/om/OverlayInfo.java
@@ -45,7 +45,7 @@
STATE_NO_IDMAP,
STATE_DISABLED,
STATE_ENABLED,
- STATE_ENABLED_STATIC,
+ STATE_ENABLED_IMMUTABLE,
// @Deprecated STATE_TARGET_IS_BEING_REPLACED,
STATE_OVERLAY_IS_BEING_REPLACED,
})
@@ -117,11 +117,12 @@
/**
* The overlay package is currently enabled because it is marked as
- * 'static'. It cannot be disabled but will change state if for instance
+ * 'immutable'. It cannot be disabled but will change state if for instance
* its target is uninstalled.
* @hide
*/
- public static final int STATE_ENABLED_STATIC = 6;
+ @Deprecated
+ public static final int STATE_ENABLED_IMMUTABLE = 6;
/**
* Overlay category: theme.
@@ -180,21 +181,21 @@
public final int userId;
/**
- * Priority as read from the manifest. Used if isStatic is true. Not
- * intended to be exposed to 3rd party.
+ * Priority as configured by {@link com.android.internal.content.om.OverlayConfig}.
+ * Not intended to be exposed to 3rd party.
*
* @hide
*/
public final int priority;
/**
- * isStatic as read from the manifest. If true, the overlay is
- * unconditionally loaded and cannot be unloaded. Not intended to be
+ * isMutable as configured by {@link com.android.internal.content.om.OverlayConfig}.
+ * If false, the overlay is unconditionally loaded and cannot be unloaded. Not intended to be
* exposed to 3rd party.
*
* @hide
*/
- public final boolean isStatic;
+ public final boolean isMutable;
/**
* Create a new OverlayInfo based on source with an updated state.
@@ -207,14 +208,14 @@
public OverlayInfo(@NonNull OverlayInfo source, @State int state) {
this(source.packageName, source.targetPackageName, source.targetOverlayableName,
source.category, source.baseCodePath, state, source.userId, source.priority,
- source.isStatic);
+ source.isMutable);
}
/** @hide */
public OverlayInfo(@NonNull String packageName, @NonNull String targetPackageName,
@Nullable String targetOverlayableName, @Nullable String category,
@NonNull String baseCodePath, int state, int userId,
- int priority, boolean isStatic) {
+ int priority, boolean isMutable) {
this.packageName = packageName;
this.targetPackageName = targetPackageName;
this.targetOverlayableName = targetOverlayableName;
@@ -223,7 +224,7 @@
this.state = state;
this.userId = userId;
this.priority = priority;
- this.isStatic = isStatic;
+ this.isMutable = isMutable;
ensureValidState();
}
@@ -237,7 +238,7 @@
state = source.readInt();
userId = source.readInt();
priority = source.readInt();
- isStatic = source.readBoolean();
+ isMutable = source.readBoolean();
ensureValidState();
}
@@ -307,7 +308,7 @@
case STATE_NO_IDMAP:
case STATE_DISABLED:
case STATE_ENABLED:
- case STATE_ENABLED_STATIC:
+ case STATE_ENABLED_IMMUTABLE:
case STATE_TARGET_IS_BEING_REPLACED:
case STATE_OVERLAY_IS_BEING_REPLACED:
break;
@@ -331,7 +332,7 @@
dest.writeInt(state);
dest.writeInt(userId);
dest.writeInt(priority);
- dest.writeBoolean(isStatic);
+ dest.writeBoolean(isMutable);
}
public static final @android.annotation.NonNull Parcelable.Creator<OverlayInfo> CREATOR =
@@ -360,7 +361,7 @@
public boolean isEnabled() {
switch (state) {
case STATE_ENABLED:
- case STATE_ENABLED_STATIC:
+ case STATE_ENABLED_IMMUTABLE:
return true;
default:
return false;
@@ -386,8 +387,8 @@
return "STATE_DISABLED";
case STATE_ENABLED:
return "STATE_ENABLED";
- case STATE_ENABLED_STATIC:
- return "STATE_ENABLED_STATIC";
+ case STATE_ENABLED_IMMUTABLE:
+ return "STATE_ENABLED_IMMUTABLE";
case STATE_TARGET_IS_BEING_REPLACED:
return "STATE_TARGET_IS_BEING_REPLACED";
case STATE_OVERLAY_IS_BEING_REPLACED:
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index da44f70..168679e 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -483,6 +483,9 @@
public final boolean isolatedSplits;
public final boolean isSplitRequired;
public final boolean useEmbeddedDex;
+ public final String targetPackageName;
+ public final boolean overlayIsStatic;
+ public final int overlayPriority;
public ApkLite(String codePath, String packageName, String splitName,
boolean isFeatureSplit,
@@ -492,6 +495,7 @@
SigningDetails signingDetails, boolean coreApp,
boolean debuggable, boolean multiArch, boolean use32bitAbi,
boolean useEmbeddedDex, boolean extractNativeLibs, boolean isolatedSplits,
+ String targetPackageName, boolean overlayIsStatic, int overlayPriority,
int minSdkVersion, int targetSdkVersion) {
this.codePath = codePath;
this.packageName = packageName;
@@ -513,6 +517,9 @@
this.extractNativeLibs = extractNativeLibs;
this.isolatedSplits = isolatedSplits;
this.isSplitRequired = isSplitRequired;
+ this.targetPackageName = targetPackageName;
+ this.overlayIsStatic = overlayIsStatic;
+ this.overlayPriority = overlayPriority;
this.minSdkVersion = minSdkVersion;
this.targetSdkVersion = targetSdkVersion;
}
@@ -1784,6 +1791,12 @@
boolean useEmbeddedDex = false;
String configForSplit = null;
String usesSplitName = null;
+ String targetPackage = null;
+ boolean overlayIsStatic = false;
+ int overlayPriority = 0;
+
+ String requiredSystemPropertyName = null;
+ String requiredSystemPropertyValue = null;
for (int i = 0; i < attrs.getAttributeCount(); i++) {
final String attr = attrs.getAttributeName(i);
@@ -1848,6 +1861,21 @@
useEmbeddedDex = attrs.getAttributeBooleanValue(i, false);
}
}
+ } else if (PackageParser.TAG_OVERLAY.equals(parser.getName())) {
+ for (int i = 0; i < attrs.getAttributeCount(); ++i) {
+ final String attr = attrs.getAttributeName(i);
+ if ("requiredSystemPropertyName".equals(attr)) {
+ requiredSystemPropertyName = attrs.getAttributeValue(i);
+ } else if ("requiredSystemPropertyValue".equals(attr)) {
+ requiredSystemPropertyValue = attrs.getAttributeValue(i);
+ } else if ("targetPackage".equals(attr)) {
+ targetPackage = attrs.getAttributeValue(i);;
+ } else if ("isStatic".equals(attr)) {
+ overlayIsStatic = attrs.getAttributeBooleanValue(i, false);
+ } else if ("priority".equals(attr)) {
+ overlayPriority = attrs.getAttributeIntValue(i, 0);
+ }
+ }
} else if (TAG_USES_SPLIT.equals(parser.getName())) {
if (usesSplitName != null) {
Slog.w(TAG, "Only one <uses-split> permitted. Ignoring others.");
@@ -1874,11 +1902,22 @@
}
}
+ // Check to see if overlay should be excluded based on system property condition
+ if (!checkRequiredSystemProperty(requiredSystemPropertyName,
+ requiredSystemPropertyValue)) {
+ Slog.i(TAG, "Skipping target and overlay pair " + targetPackage + " and "
+ + codePath + ": overlay ignored due to required system property: "
+ + requiredSystemPropertyName + " with value: " + requiredSystemPropertyValue);
+ targetPackage = null;
+ overlayIsStatic = false;
+ overlayPriority = 0;
+ }
+
return new ApkLite(codePath, packageSplit.first, packageSplit.second, isFeatureSplit,
configForSplit, usesSplitName, isSplitRequired, versionCode, versionCodeMajor,
revisionCode, installLocation, verifiers, signingDetails, coreApp, debuggable,
multiArch, use32bitAbi, useEmbeddedDex, extractNativeLibs, isolatedSplits,
- minSdkVersion, targetSdkVersion);
+ targetPackage, overlayIsStatic, overlayPriority, minSdkVersion, targetSdkVersion);
}
/**
@@ -2162,7 +2201,7 @@
}
// check to see if overlay should be excluded based on system property condition
- if (!checkOverlayRequiredSystemProperty(propName, propValue)) {
+ if (!checkRequiredSystemProperty(propName, propValue)) {
Slog.i(TAG, "Skipping target and overlay pair " + pkg.mOverlayTarget + " and "
+ pkg.baseCodePath+ ": overlay ignored due to required system property: "
+ propName + " with value: " + propValue);
@@ -2590,8 +2629,11 @@
return pkg;
}
- private boolean checkOverlayRequiredSystemProperty(String propName, String propValue) {
-
+ /**
+ * Returns {@code true} if both the property name and value are empty or if the given system
+ * property is set to the specified value. In all other cases, returns {@code false}
+ */
+ public static boolean checkRequiredSystemProperty(String propName, String propValue) {
if (TextUtils.isEmpty(propName) || TextUtils.isEmpty(propValue)) {
if (!TextUtils.isEmpty(propName) || !TextUtils.isEmpty(propValue)) {
// malformed condition - incomplete
diff --git a/core/java/android/content/pm/PackagePartitions.java b/core/java/android/content/pm/PackagePartitions.java
new file mode 100644
index 0000000..9b8396e
--- /dev/null
+++ b/core/java/android/content/pm/PackagePartitions.java
@@ -0,0 +1,213 @@
+/*
+ * 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 android.content.pm;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Environment;
+import android.os.FileUtils;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.function.Function;
+
+/**
+ * Exposes {@link #SYSTEM_PARTITIONS} which represents the partitions in which application packages
+ * can be installed. The partitions are ordered from most generic (lowest priority) to most specific
+ * (greatest priority).
+ *
+ * @hide
+ **/
+public class PackagePartitions {
+ public static final int PARTITION_SYSTEM = 0;
+ public static final int PARTITION_VENDOR = 1;
+ public static final int PARTITION_ODM = 2;
+ public static final int PARTITION_OEM = 3;
+ public static final int PARTITION_PRODUCT = 4;
+ public static final int PARTITION_SYSTEM_EXT = 5;
+
+ @IntDef(flag = true, prefix = { "PARTITION_" }, value = {
+ PARTITION_SYSTEM,
+ PARTITION_VENDOR,
+ PARTITION_ODM,
+ PARTITION_OEM,
+ PARTITION_PRODUCT,
+ PARTITION_SYSTEM_EXT
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PartitionType {}
+
+ /**
+ * The list of all system partitions that may contain packages in ascending order of
+ * specificity (the more generic, the earlier in the list a partition appears).
+ */
+ private static final ArrayList<SystemPartition> SYSTEM_PARTITIONS =
+ new ArrayList<>(Arrays.asList(
+ new SystemPartition(Environment.getRootDirectory(), PARTITION_SYSTEM,
+ true /* containsPrivApp */, false /* containsOverlay */),
+ new SystemPartition(Environment.getVendorDirectory(), PARTITION_VENDOR,
+ true /* containsPrivApp */, true /* containsOverlay */),
+ new SystemPartition(Environment.getOdmDirectory(), PARTITION_ODM,
+ true /* containsPrivApp */, true /* containsOverlay */),
+ new SystemPartition(Environment.getOemDirectory(), PARTITION_OEM,
+ false /* containsPrivApp */, true /* containsOverlay */),
+ new SystemPartition(Environment.getProductDirectory(), PARTITION_PRODUCT,
+ true /* containsPrivApp */, true /* containsOverlay */),
+ new SystemPartition(Environment.getSystemExtDirectory(), PARTITION_SYSTEM_EXT,
+ true /* containsPrivApp */, true /* containsOverlay */)));
+
+ /**
+ * Returns a list in which the elements are products of the specified function applied to the
+ * list of {@link #SYSTEM_PARTITIONS} in increasing specificity order.
+ */
+ public static <T> ArrayList<T> getOrderedPartitions(
+ @NonNull Function<SystemPartition, T> producer) {
+ final ArrayList<T> out = new ArrayList<>();
+ for (int i = 0, n = SYSTEM_PARTITIONS.size(); i < n; i++) {
+ final T v = producer.apply(SYSTEM_PARTITIONS.get(i));
+ if (v != null) {
+ out.add(v);
+ }
+ }
+ return out;
+ }
+
+ /** Represents a partition that contains application packages. */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public static class SystemPartition {
+ @NonNull
+ public final File folder;
+
+ @PartitionType
+ public final int type;
+
+ @Nullable
+ private final DeferredCanonicalFile mAppFolder;
+
+ @Nullable
+ private final DeferredCanonicalFile mPrivAppFolder;
+
+ @Nullable
+ private final DeferredCanonicalFile mOverlayFolder;
+
+ private SystemPartition(@NonNull File folder, @PartitionType int type,
+ boolean containsPrivApp, boolean containsOverlay) {
+ this.folder = folder;
+ this.type = type;
+ this.mAppFolder = new DeferredCanonicalFile(folder, "app");
+ this.mPrivAppFolder = containsPrivApp ?
+ new DeferredCanonicalFile(folder, "priv-app") : null;
+ this.mOverlayFolder = containsOverlay ?
+ new DeferredCanonicalFile(folder, "overlay") : null;
+ }
+
+ public SystemPartition(@NonNull SystemPartition original) {
+ this.folder = original.folder;
+ this.type = original.type;
+ this.mAppFolder = original.mAppFolder;
+ this.mPrivAppFolder = original.mPrivAppFolder;
+ this.mOverlayFolder = original.mOverlayFolder;
+ }
+
+ /**
+ * Creates a partition containing the same folders as the original partition but with a
+ * different root folder.
+ */
+ public SystemPartition(@NonNull File rootFolder, @NonNull SystemPartition partition) {
+ this(rootFolder, partition.type, partition.mPrivAppFolder != null,
+ partition.mOverlayFolder != null);
+ }
+
+ /** Returns the canonical app folder of the partition. */
+ @Nullable
+ public File getAppFolder() {
+ return mAppFolder == null ? null : mAppFolder.getFile();
+ }
+
+ /** Returns the canonical priv-app folder of the partition, if one exists. */
+ @Nullable
+ public File getPrivAppFolder() {
+ return mPrivAppFolder == null ? null : mPrivAppFolder.getFile();
+ }
+
+ /** Returns the canonical overlay folder of the partition, if one exists. */
+ @Nullable
+ public File getOverlayFolder() {
+ return mOverlayFolder == null ? null : mOverlayFolder.getFile();
+ }
+
+ /** Returns whether the partition contains the specified file in its priv-app folder. */
+ public boolean containsPrivApp(@NonNull File scanFile) {
+ return FileUtils.contains(mPrivAppFolder.getFile(), scanFile);
+ }
+
+ /** Returns whether the partition contains the specified file in its app folder. */
+ public boolean containsApp(@NonNull File scanFile) {
+ return FileUtils.contains(mAppFolder.getFile(), scanFile);
+ }
+
+ /** Returns whether the partition contains the specified file in its overlay folder. */
+ public boolean containsOverlay(@NonNull File scanFile) {
+ return FileUtils.contains(mOverlayFolder.getFile(), scanFile);
+ }
+
+ /** Returns whether the partition contains the specified file. */
+ public boolean containsPath(@NonNull String path) {
+ return path.startsWith(folder.getPath() + "/");
+ }
+
+ /** Returns whether the partition contains the specified file in its priv-app folder. */
+ public boolean containsPrivPath(@NonNull String path) {
+ return mPrivAppFolder != null
+ && path.startsWith(mPrivAppFolder.getFile().getPath() + "/");
+ }
+ }
+
+ /**
+ * A class that defers the canonicalization of its underlying file. This must be done so
+ * processes do not attempt to canonicalize files in directories for which the process does not
+ * have the correct selinux policies.
+ */
+ private static class DeferredCanonicalFile {
+ private boolean mIsCanonical;
+ private File mFile;
+ private DeferredCanonicalFile(File dir, String fileName) {
+ mFile = new File(dir, fileName);
+ mIsCanonical = false;
+ }
+
+ private File getFile() {
+ if (mIsCanonical) {
+ return mFile;
+ }
+ mIsCanonical = true;
+ try {
+ mFile = mFile.getCanonicalFile();
+ } catch (IOException ignore) {
+ // failed to look up canonical path, continue with original one
+ }
+ return mFile;
+ }
+ }
+}
diff --git a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
index 5be9c91..9087f42 100644
--- a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
+++ b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
@@ -289,6 +289,12 @@
boolean useEmbeddedDex = false;
String configForSplit = null;
String usesSplitName = null;
+ String targetPackage = null;
+ boolean overlayIsStatic = false;
+ int overlayPriority = 0;
+
+ String requiredSystemPropertyName = null;
+ String requiredSystemPropertyValue = null;
for (int i = 0; i < attrs.getAttributeCount(); i++) {
final String attr = attrs.getAttributeName(i);
@@ -365,6 +371,21 @@
break;
}
}
+ } else if (PackageParser.TAG_OVERLAY.equals(parser.getName())) {
+ for (int i = 0; i < attrs.getAttributeCount(); ++i) {
+ final String attr = attrs.getAttributeName(i);
+ if ("requiredSystemPropertyName".equals(attr)) {
+ requiredSystemPropertyName = attrs.getAttributeValue(i);
+ } else if ("requiredSystemPropertyValue".equals(attr)) {
+ requiredSystemPropertyValue = attrs.getAttributeValue(i);
+ } else if ("targetPackage".equals(attr)) {
+ targetPackage = attrs.getAttributeValue(i);;
+ } else if ("isStatic".equals(attr)) {
+ overlayIsStatic = attrs.getAttributeBooleanValue(i, false);
+ } else if ("priority".equals(attr)) {
+ overlayPriority = attrs.getAttributeIntValue(i, 0);
+ }
+ }
} else if (PackageParser.TAG_USES_SPLIT.equals(parser.getName())) {
if (usesSplitName != null) {
Slog.w(TAG, "Only one <uses-split> permitted. Ignoring others.");
@@ -391,11 +412,23 @@
}
}
+ // Check to see if overlay should be excluded based on system property condition
+ if (!PackageParser.checkRequiredSystemProperty(requiredSystemPropertyName,
+ requiredSystemPropertyValue)) {
+ Slog.i(TAG, "Skipping target and overlay pair " + targetPackage + " and "
+ + codePath + ": overlay ignored due to required system property: "
+ + requiredSystemPropertyName + " with value: " + requiredSystemPropertyValue);
+ targetPackage = null;
+ overlayIsStatic = false;
+ overlayPriority = 0;
+ }
+
return new PackageParser.ApkLite(codePath, packageSplit.first, packageSplit.second,
isFeatureSplit, configForSplit, usesSplitName, isSplitRequired, versionCode,
versionCodeMajor, revisionCode, installLocation, verifiers, signingDetails,
coreApp, debuggable, multiArch, use32bitAbi, useEmbeddedDex, extractNativeLibs,
- isolatedSplits, minSdkVersion, targetSdkVersion);
+ isolatedSplits, targetPackage, overlayIsStatic, overlayPriority, minSdkVersion,
+ targetSdkVersion);
}
public static VerifierInfo parseVerifier(AttributeSet attrs) {
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 1b01758..f295f8c 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -38,6 +38,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.content.om.OverlayConfig;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
@@ -242,14 +243,11 @@
try {
final ArrayList<ApkAssets> apkAssets = new ArrayList<>();
apkAssets.add(ApkAssets.loadFromPath(frameworkPath, true /*system*/));
- final String[] systemIdmapPaths = nativeCreateIdmapsForStaticOverlaysTargetingAndroid();
- if (systemIdmapPaths != null) {
- for (String idmapPath : systemIdmapPaths) {
- apkAssets.add(ApkAssets.loadOverlayFromPath(idmapPath, true /*system*/));
- }
- } else {
- Log.w(TAG, "'idmap2 --scan' failed: no static=\"true\" overlays targeting "
- + "\"android\" will be loaded");
+
+ final String[] systemIdmapPaths =
+ OverlayConfig.getZygoteInstance().createImmutableFrameworkIdmapsInZygote();
+ for (String idmapPath : systemIdmapPaths) {
+ apkAssets.add(ApkAssets.loadOverlayFromPath(idmapPath, true /*system*/));
}
sSystemApkAssetsSet = new ArraySet<>(apkAssets);
diff --git a/core/java/android/service/notification/ConditionProviderService.java b/core/java/android/service/notification/ConditionProviderService.java
index 7d3b13b..f37e01d 100644
--- a/core/java/android/service/notification/ConditionProviderService.java
+++ b/core/java/android/service/notification/ConditionProviderService.java
@@ -58,7 +58,7 @@
* </service></pre>
*
* <p> Condition providers cannot be bound by the system on
- * {@link ActivityManager#isLowRamDevice() low ram} devices</p>
+ * {@link ActivityManager#isLowRamDevice() low ram} devices running Android Q (and below)</p>
*
* @deprecated Instead of using an automatically bound service, use
* {@link android.app.NotificationManager#setAutomaticZenRuleState(String, Condition)} to tell the
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 0ff2e03..6562572 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -86,8 +86,8 @@
* or after {@link #onListenerDisconnected()}.
* </p>
* <p> Notification listeners cannot get notification access or be bound by the system on
- * {@linkplain ActivityManager#isLowRamDevice() low-RAM} devices. The system also ignores
- * notification listeners running in a work profile. A
+ * {@linkplain ActivityManager#isLowRamDevice() low-RAM} devices running Android Q (and below).
+ * The system also ignores notification listeners running in a work profile. A
* {@link android.app.admin.DevicePolicyManager} might block notifications originating from a work
* profile.</p>
* <p>
diff --git a/core/java/android/view/AccessibilityEmbeddedConnection.java b/core/java/android/view/AccessibilityEmbeddedConnection.java
index cc1e501..5d34669 100644
--- a/core/java/android/view/AccessibilityEmbeddedConnection.java
+++ b/core/java/android/view/AccessibilityEmbeddedConnection.java
@@ -33,6 +33,7 @@
*/
final class AccessibilityEmbeddedConnection extends IAccessibilityEmbeddedConnection.Stub {
private final WeakReference<ViewRootImpl> mViewRootImpl;
+ private final Matrix mTmpScreenMatrix = new Matrix();
AccessibilityEmbeddedConnection(ViewRootImpl viewRootImpl) {
mViewRootImpl = new WeakReference<>(viewRootImpl);
@@ -73,9 +74,11 @@
public void setScreenMatrix(float[] matrixValues) {
final ViewRootImpl viewRootImpl = mViewRootImpl.get();
if (viewRootImpl != null) {
- // TODO(b/148821260): Implement the rest of matrix values.
- viewRootImpl.mAttachInfo.mLocationInParentDisplay.set(
- (int) matrixValues[Matrix.MTRANS_X], (int) matrixValues[Matrix.MTRANS_Y]);
+ mTmpScreenMatrix.setValues(matrixValues);
+ if (viewRootImpl.mAttachInfo.mScreenMatrixInEmbeddedHierarchy == null) {
+ viewRootImpl.mAttachInfo.mScreenMatrixInEmbeddedHierarchy = new Matrix();
+ }
+ viewRootImpl.mAttachInfo.mScreenMatrixInEmbeddedHierarchy.set(mTmpScreenMatrix);
}
}
}
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index 3ca84c1..6d4ac0e 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -21,6 +21,7 @@
import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_REQUESTED_KEY;
import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY;
+import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
@@ -109,6 +110,7 @@
private final Rect mTempRect = new Rect();
private final Rect mTempRect1 = new Rect();
private final Rect mTempRect2 = new Rect();
+ private final RectF mTempRectF = new RectF();
private AddNodeInfosForViewId mAddNodeInfosForViewId;
@@ -855,6 +857,38 @@
return mViewRootImpl.mAttachInfo.mLocationInParentDisplay.equals(0, 0);
}
+ private void applyScreenMatrixIfNeeded(List<AccessibilityNodeInfo> infos) {
+ if (infos == null || shouldBypassApplyScreenMatrix()) {
+ return;
+ }
+ final int infoCount = infos.size();
+ for (int i = 0; i < infoCount; i++) {
+ final AccessibilityNodeInfo info = infos.get(i);
+ applyScreenMatrixIfNeeded(info);
+ }
+ }
+
+ private void applyScreenMatrixIfNeeded(AccessibilityNodeInfo info) {
+ if (info == null || shouldBypassApplyScreenMatrix()) {
+ return;
+ }
+ final Rect boundsInScreen = mTempRect;
+ final RectF transformedBounds = mTempRectF;
+ final Matrix screenMatrix = mViewRootImpl.mAttachInfo.mScreenMatrixInEmbeddedHierarchy;
+
+ info.getBoundsInScreen(boundsInScreen);
+ transformedBounds.set(boundsInScreen);
+ screenMatrix.mapRect(transformedBounds);
+ boundsInScreen.set((int) transformedBounds.left, (int) transformedBounds.top,
+ (int) transformedBounds.right, (int) transformedBounds.bottom);
+ info.setBoundsInScreen(boundsInScreen);
+ }
+
+ private boolean shouldBypassApplyScreenMatrix() {
+ final Matrix screenMatrix = mViewRootImpl.mAttachInfo.mScreenMatrixInEmbeddedHierarchy;
+ return screenMatrix == null || screenMatrix.isIdentity();
+ }
+
private void associateLeashedParentIfNeeded(List<AccessibilityNodeInfo> infos) {
if (infos == null || shouldBypassAssociateLeashedParent()) {
return;
@@ -945,6 +979,7 @@
try {
mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
associateLeashedParentIfNeeded(infos);
+ applyScreenMatrixIfNeeded(infos);
adjustBoundsInScreenIfNeeded(infos);
// To avoid applyAppScaleAndMagnificationSpecIfNeeded changing the bounds of node,
// then impact the visibility result, we need to adjust visibility before apply scale.
@@ -967,6 +1002,7 @@
try {
mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
associateLeashedParentIfNeeded(info);
+ applyScreenMatrixIfNeeded(info);
adjustBoundsInScreenIfNeeded(info);
// To avoid applyAppScaleAndMagnificationSpecIfNeeded changing the bounds of node,
// then impact the visibility result, we need to adjust visibility before apply scale.
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index c7f850a..b9be33c 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -28820,6 +28820,12 @@
final Point mLocationInParentDisplay = new Point();
/**
+ * The screen matrix of this view when it's on a {@link SurfaceControlViewHost} that is
+ * embedded within a SurfaceView.
+ */
+ Matrix mScreenMatrixInEmbeddedHierarchy;
+
+ /**
* Global to the view hierarchy used as a temporary for dealing with
* x/y points in the transparent region computations.
*/
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 54bdb88..ce7cfa7 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -1794,6 +1794,9 @@
client.autofillClientResetableStateAvailable();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
+ } catch (SyncResultReceiver.TimeoutException e) {
+ // no-op, just log the error message.
+ Log.w(TAG, "Exception getting result from SyncResultReceiver: " + e);
}
}
diff --git a/core/java/com/android/internal/content/om/OverlayConfig.java b/core/java/com/android/internal/content/om/OverlayConfig.java
new file mode 100644
index 0000000..f699eb8
--- /dev/null
+++ b/core/java/com/android/internal/content/om/OverlayConfig.java
@@ -0,0 +1,413 @@
+/*
+ * 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.internal.content.om;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.pm.PackagePartitions;
+import android.content.pm.parsing.AndroidPackage;
+import android.os.Build;
+import android.os.Process;
+import android.os.Trace;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.content.om.OverlayConfigParser.OverlayPartition;
+import com.android.internal.content.om.OverlayConfigParser.ParsedConfiguration;
+import com.android.internal.content.om.OverlayScanner.ParsedOverlayInfo;
+import com.android.internal.util.Preconditions;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+/**
+ * Responsible for reading overlay configuration files and handling queries of overlay mutability,
+ * default-enabled state, and priority.
+ *
+ * @see OverlayConfigParser
+ */
+@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+public class OverlayConfig {
+ static final String TAG = "OverlayConfig";
+
+ // The default priority of an overlay that has not been configured. Overlays with default
+ // priority have a higher precedence than configured overlays.
+ @VisibleForTesting
+ public static final int DEFAULT_PRIORITY = Integer.MAX_VALUE;
+
+ @VisibleForTesting
+ public static final class Configuration {
+ @Nullable
+ public final ParsedConfiguration parsedConfig;
+
+ public final int configIndex;
+
+ public Configuration(@Nullable ParsedConfiguration parsedConfig, int configIndex) {
+ this.parsedConfig = parsedConfig;
+ this.configIndex = configIndex;
+ }
+ }
+
+ /**
+ * Interface for providing information on scanned packages.
+ * TODO(147840005): Remove this when android:isStatic and android:priority are fully deprecated
+ */
+ public interface AndroidPackageProvider {
+
+ /** Performs the given action for each package. */
+ void forEachPackage(Consumer<AndroidPackage> p);
+ }
+
+ private static final Comparator<ParsedConfiguration> sStaticOverlayComparator = (c1, c2) -> {
+ final ParsedOverlayInfo o1 = c1.parsedInfo;
+ final ParsedOverlayInfo o2 = c2.parsedInfo;
+ Preconditions.checkArgument(o1.isStatic && o2.isStatic,
+ "attempted to sort non-static overlay");
+
+ if (!o1.targetPackageName.equals(o2.targetPackageName)) {
+ return o1.targetPackageName.compareTo(o2.targetPackageName);
+ }
+
+ final int comparedPriority = o1.priority - o2.priority;
+ return comparedPriority == 0 ? o1.path.compareTo(o2.path) : comparedPriority;
+ };
+
+ // Map of overlay package name to configured overlay settings
+ private final ArrayMap<String, Configuration> mConfigurations = new ArrayMap<>();
+
+ // Singleton instance only assigned in system server
+ private static OverlayConfig sInstance;
+
+ @VisibleForTesting
+ public OverlayConfig(@Nullable File rootDirectory,
+ @Nullable Supplier<OverlayScanner> scannerFactory,
+ @Nullable AndroidPackageProvider packageProvider) {
+ Preconditions.checkArgument((scannerFactory == null) != (packageProvider == null),
+ "scannerFactory and packageProvider cannot be both null or both non-null");
+
+ final ArrayList<OverlayPartition> partitions;
+ if (rootDirectory == null) {
+ partitions = new ArrayList<>(
+ PackagePartitions.getOrderedPartitions(OverlayPartition::new));
+ } else {
+ // Rebase the system partitions and settings file on the specified root directory.
+ partitions = new ArrayList<>(PackagePartitions.getOrderedPartitions(
+ p -> new OverlayPartition(new File(rootDirectory, p.folder.getPath()), p)));
+ }
+
+ boolean foundConfigFile = false;
+ ArrayList<ParsedOverlayInfo> packageManagerOverlayInfos = null;
+
+ final ArrayList<ParsedConfiguration> overlays = new ArrayList<>();
+ for (int i = 0, n = partitions.size(); i < n; i++) {
+ final OverlayPartition partition = partitions.get(i);
+ final OverlayScanner scanner = (scannerFactory == null) ? null : scannerFactory.get();
+ final ArrayList<ParsedConfiguration> partitionOverlays =
+ OverlayConfigParser.getConfigurations(partition, scanner);
+ if (partitionOverlays != null) {
+ foundConfigFile = true;
+ overlays.addAll(partitionOverlays);
+ continue;
+ }
+
+ // If the configuration file is not present, then use android:isStatic and
+ // android:priority to configure the overlays in the partition.
+ // TODO(147840005): Remove converting static overlays to immutable, default-enabled
+ // overlays when android:siStatic and android:priority are fully deprecated.
+ final ArrayList<ParsedOverlayInfo> partitionOverlayInfos;
+ if (scannerFactory != null) {
+ partitionOverlayInfos = new ArrayList<>(scanner.getAllParsedInfos());
+ } else {
+ if (packageManagerOverlayInfos == null) {
+ packageManagerOverlayInfos = getOverlayPackageInfos(packageProvider);
+ }
+
+ // Filter out overlays not present in the partition.
+ partitionOverlayInfos = new ArrayList<>(packageManagerOverlayInfos);
+ for (int j = partitionOverlayInfos.size() - 1; j >= 0; j--) {
+ if (!partition.containsPath(partitionOverlayInfos.get(j).path.getPath())) {
+ partitionOverlayInfos.remove(j);
+ }
+ }
+ }
+
+ // Static overlays are configured as immutable, default-enabled overlays.
+ final ArrayList<ParsedConfiguration> partitionConfigs = new ArrayList<>();
+ for (int j = 0, m = partitionOverlayInfos.size(); j < m; j++) {
+ final ParsedOverlayInfo p = partitionOverlayInfos.get(j);
+ if (p.isStatic) {
+ partitionConfigs.add(new ParsedConfiguration(p.packageName,
+ true /* enabled */, false /* mutable */, partition.policy, p));
+ }
+ }
+
+ partitionConfigs.sort(sStaticOverlayComparator);
+ overlays.addAll(partitionConfigs);
+ }
+
+ if (!foundConfigFile) {
+ // If no overlay configuration files exist, disregard partition precedence and allow
+ // android:priority to reorder overlays across partition boundaries.
+ overlays.sort(sStaticOverlayComparator);
+ }
+
+ for (int i = 0, n = overlays.size(); i < n; i++) {
+ // Add the configurations to a map so definitions of an overlay in an earlier
+ // partition can be replaced by an overlay with the same package name in a later
+ // partition.
+ final ParsedConfiguration config = overlays.get(i);
+ mConfigurations.put(config.packageName, new Configuration(config, i));
+ }
+ }
+
+ /**
+ * Creates an instance of OverlayConfig for use in the zygote process.
+ * This instance will not include information of static overlays existing outside of a partition
+ * overlay directory.
+ */
+ @NonNull
+ public static OverlayConfig getZygoteInstance() {
+ if (Process.myUid() != Process.ROOT_UID) {
+ // Scan the overlays in the zygote process to generate configuration settings for
+ // overlays on the system image. Do not cache this instance so OverlayConfig will not
+ // be present in applications by default.
+ throw new IllegalStateException("Can only be invoked in the root process");
+ }
+
+ Trace.traceBegin(Trace.TRACE_TAG_RRO, "OverlayConfig#getZygoteInstance");
+ try {
+ return new OverlayConfig(null /* rootDirectory */, OverlayScanner::new,
+ null /* packageProvider */);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_RRO);
+ }
+ }
+
+ /**
+ * Initializes a singleton instance for use in the system process.
+ * Can only be called once. This instance is cached so future invocations of
+ * {@link #getSystemInstance()} will return the initialized instance.
+ */
+ @NonNull
+ public static OverlayConfig initializeSystemInstance(AndroidPackageProvider packageProvider) {
+ if (Process.myUid() != Process.SYSTEM_UID) {
+ throw new IllegalStateException("Can only be invoked in the system process");
+ }
+
+ Trace.traceBegin(Trace.TRACE_TAG_RRO, "OverlayConfig#initializeSystemInstance");
+ sInstance = new OverlayConfig(null, null, packageProvider);
+ Trace.traceEnd(Trace.TRACE_TAG_RRO);
+ return sInstance;
+ }
+
+ /**
+ * Retrieves the singleton instance initialized by
+ * {@link #initializeSystemInstance(AndroidPackageProvider)}.
+ */
+ @NonNull
+ public static OverlayConfig getSystemInstance() {
+ if (sInstance == null) {
+ throw new IllegalStateException("System instance not initialized");
+ }
+
+ return sInstance;
+ }
+
+ @VisibleForTesting
+ @Nullable
+ public Configuration getConfiguration(@NonNull String packageName) {
+ return mConfigurations.get(packageName);
+ }
+
+ /**
+ * Returns whether the overlay is enabled by default.
+ * Overlays that are not configured are disabled by default mutable.
+ */
+ public boolean isEnabled(String packageName) {
+ final Configuration config = mConfigurations.get(packageName);
+
+ // STOPSHIP(149499802): Enabling a mutable overlay currently has no effect. Either implement
+ // some behavior for default-enabled, mutable overlays or prevent parsing of the enabled
+ // attribute on overlays that are mutable.
+ if (config != null && config.parsedConfig.mutable) {
+ Log.w(TAG, "Default-enabled configuration for mutable overlay "
+ + config.parsedConfig.packageName + " has no effect");
+ return OverlayConfigParser.DEFAULT_ENABLED_STATE;
+ }
+
+ return config == null? OverlayConfigParser.DEFAULT_ENABLED_STATE
+ : config.parsedConfig.enabled;
+ }
+
+ /**
+ * Returns whether the overlay is mutable and can have its enabled state changed dynamically.
+ * Overlays that are not configured are mutable.
+ */
+ public boolean isMutable(String packageName) {
+ final Configuration config = mConfigurations.get(packageName);
+ return config == null ? OverlayConfigParser.DEFAULT_MUTABILITY
+ : config.parsedConfig.mutable;
+ }
+
+ /**
+ * Returns an integer corresponding to the priority of the overlay.
+ * When multiple overlays override the same resource, the overlay with the highest priority will
+ * will have its value chosen. Overlays that are not configured have a priority of
+ * {@link Integer#MAX_VALUE}.
+ */
+ public int getPriority(String packageName) {
+ final Configuration config = mConfigurations.get(packageName);
+ return config == null ? DEFAULT_PRIORITY : config.configIndex;
+ }
+
+ @NonNull
+ private ArrayList<Configuration> getSortedOverlays() {
+ final ArrayList<Configuration> sortedOverlays = new ArrayList<>();
+ for (int i = 0, n = mConfigurations.size(); i < n; i++) {
+ sortedOverlays.add(mConfigurations.valueAt(i));
+ }
+ sortedOverlays.sort(Comparator.comparingInt(o -> o.configIndex));
+ return sortedOverlays;
+ }
+
+ @NonNull
+ private static ArrayList<ParsedOverlayInfo> getOverlayPackageInfos(
+ @NonNull AndroidPackageProvider packageManager) {
+ final ArrayList<ParsedOverlayInfo> overlays = new ArrayList<>();
+ packageManager.forEachPackage((AndroidPackage p) -> {
+ if (p.getOverlayTarget() != null && p.isSystem()) {
+ overlays.add(new ParsedOverlayInfo(p.getPackageName(), p.getOverlayTarget(),
+ p.getTargetSdkVersion(), p.isOverlayIsStatic(), p.getOverlayPriority(),
+ new File(p.getBaseCodePath())));
+ }
+ });
+ return overlays;
+ }
+
+ /** Represents a single call to idmap create-multiple. */
+ @VisibleForTesting
+ public static class IdmapInvocation {
+ public final boolean enforceOverlayable;
+ public final String policy;
+ public final ArrayList<String> overlayPaths = new ArrayList<>();
+
+ IdmapInvocation(boolean enforceOverlayable, @NonNull String policy) {
+ this.enforceOverlayable = enforceOverlayable;
+ this.policy = policy;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + String.format("{enforceOverlayable=%s, policy=%s"
+ + ", overlayPaths=[%s]}", enforceOverlayable, policy,
+ String.join(", ", overlayPaths));
+ }
+ }
+
+ /**
+ * Retrieves a list of immutable framework overlays in order of least precedence to greatest
+ * precedence.
+ */
+ @VisibleForTesting
+ public ArrayList<IdmapInvocation> getImmutableFrameworkOverlayIdmapInvocations() {
+ final ArrayList<IdmapInvocation> idmapInvocations = new ArrayList<>();
+ final ArrayList<Configuration> sortedConfigs = getSortedOverlays();
+ for (int i = 0, n = sortedConfigs.size(); i < n; i++) {
+ final Configuration overlay = sortedConfigs.get(i);
+ if (overlay.parsedConfig.mutable || !overlay.parsedConfig.enabled
+ || !"android".equals(overlay.parsedConfig.parsedInfo.targetPackageName)) {
+ continue;
+ }
+
+ // Only enforce that overlays targeting packages with overlayable declarations abide by
+ // those declarations if the target sdk of the overlay is at least Q (when overlayable
+ // was introduced).
+ final boolean enforceOverlayable = overlay.parsedConfig.parsedInfo.targetSdkVersion
+ >= Build.VERSION_CODES.Q;
+
+ // Determine if the idmap for the current overlay can be generated in the last idmap
+ // create-multiple invocation.
+ IdmapInvocation invocation = null;
+ if (!idmapInvocations.isEmpty()) {
+ final IdmapInvocation last = idmapInvocations.get(idmapInvocations.size() - 1);
+ if (last.enforceOverlayable == enforceOverlayable
+ && last.policy.equals(overlay.parsedConfig.policy)) {
+ invocation = last;
+ }
+ }
+
+ if (invocation == null) {
+ invocation = new IdmapInvocation(enforceOverlayable, overlay.parsedConfig.policy);
+ idmapInvocations.add(invocation);
+ }
+
+ invocation.overlayPaths.add(overlay.parsedConfig.parsedInfo.path.getAbsolutePath());
+ }
+ return idmapInvocations;
+ }
+
+ /**
+ * Creates idmap files for immutable overlays targeting the framework packages. Currently the
+ * android package is the only preloaded system package. Only the zygote can invoke this method.
+ *
+ * @return the paths of the created idmap files
+ */
+ @NonNull
+ public String[] createImmutableFrameworkIdmapsInZygote() {
+ if (Process.myUid() != Process.ROOT_UID) {
+ throw new IllegalStateException("This method can only be called from the root process");
+ }
+
+ final String targetPath = "/system/framework/framework-res.apk";
+ final ArrayList<String> idmapPaths = new ArrayList<>();
+ final ArrayList<IdmapInvocation> idmapInvocations =
+ getImmutableFrameworkOverlayIdmapInvocations();
+
+ for (int i = 0, n = idmapInvocations.size(); i < n; i++) {
+ final IdmapInvocation invocation = idmapInvocations.get(i);
+ final String[] idmaps = createIdmap(targetPath,
+ invocation.overlayPaths.toArray(new String[0]),
+ new String[]{OverlayConfigParser.OverlayPartition.POLICY_PUBLIC,
+ invocation.policy},
+ invocation.enforceOverlayable);
+
+ if (idmaps == null) {
+ Log.w(TAG, "'idmap2 create-multiple' failed: no mutable=\"false\" overlays"
+ + " targeting \"android\" will be loaded");
+ return new String[0];
+ }
+
+ idmapPaths.addAll(Arrays.asList(idmaps));
+ }
+
+ return idmapPaths.toArray(new String[0]);
+ }
+
+ /**
+ * For each overlay APK, this creates the idmap file that allows the overlay to override the
+ * target package.
+ *
+ * @return the paths of the created idmap
+ */
+ private static native String[] createIdmap(@NonNull String targetPath,
+ @NonNull String[] overlayPath, @NonNull String[] policies, boolean enforceOverlayable);
+}
diff --git a/core/java/com/android/internal/content/om/OverlayConfigParser.java b/core/java/com/android/internal/content/om/OverlayConfigParser.java
new file mode 100644
index 0000000..139607f
--- /dev/null
+++ b/core/java/com/android/internal/content/om/OverlayConfigParser.java
@@ -0,0 +1,391 @@
+/*
+ * 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.internal.content.om;
+
+import static com.android.internal.content.om.OverlayConfig.TAG;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.pm.PackagePartitions;
+import android.content.pm.PackagePartitions.SystemPartition;
+import android.os.FileUtils;
+import android.util.ArraySet;
+import android.util.Log;
+import android.util.Xml;
+
+import com.android.internal.util.XmlUtils;
+import com.android.internal.content.om.OverlayScanner.ParsedOverlayInfo;
+
+import libcore.io.IoUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+
+/**
+ * Responsible for parsing configurations of Runtime Resource Overlays that control mutability,
+ * default enable state, and priority. To configure an overlay, create or modify the file located
+ * at {@code partition}/overlay/config/config.xml where {@code partition} is the partition of the
+ * overlay to be configured. In order to be configured, an overlay must reside in the overlay
+ * directory of the partition in which the overlay is configured.
+ *
+ * @see #parseOverlay(File, XmlPullParser, OverlayScanner, ParsingContext)
+ * @see #parseMerge(File, XmlPullParser, OverlayScanner, ParsingContext)
+ **/
+final class OverlayConfigParser {
+
+ // Default values for overlay configurations.
+ static final boolean DEFAULT_ENABLED_STATE = false;
+ static final boolean DEFAULT_MUTABILITY = true;
+
+ // Maximum recursive depth of processing merge tags.
+ private static final int MAXIMUM_MERGE_DEPTH = 5;
+
+ // The subdirectory within a partition's overlay directory that contains the configuration files
+ // for the partition.
+ private static final String CONFIG_DIRECTORY = "config";
+
+ /**
+ * The name of the configuration file to parse for overlay configurations. This class does not
+ * scan for overlay configuration files within the {@link #CONFIG_DIRECTORY}; rather, other
+ * files can be included at a particular position within this file using the <merge> tag.
+ *
+ * @see #parseMerge(File, XmlPullParser, OverlayScanner, ParsingContext)
+ */
+ private static final String CONFIG_DEFAULT_FILENAME = CONFIG_DIRECTORY + "/config.xml";
+
+ /** Represents the configurations of a particular overlay. */
+ public static class ParsedConfiguration {
+ @NonNull
+ public final String packageName;
+
+ /** Whether or not the overlay is enabled by default. */
+ public final boolean enabled;
+
+ /**
+ * Whether or not the overlay is mutable and can have its enabled state changed dynamically
+ * using the {@code OverlayManagerService}.
+ **/
+ public final boolean mutable;
+
+ /** The policy granted to overlays on the partition in which the overlay is located. */
+ @NonNull
+ public final String policy;
+
+ /** Information extracted from the manifest of the overlay. */
+ @NonNull
+ public final ParsedOverlayInfo parsedInfo;
+
+ ParsedConfiguration(@NonNull String packageName, boolean enabled, boolean mutable,
+ @NonNull String policy, @NonNull ParsedOverlayInfo parsedInfo) {
+ this.packageName = packageName;
+ this.enabled = enabled;
+ this.mutable = mutable;
+ this.policy = policy;
+ this.parsedInfo = parsedInfo;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + String.format("{packageName=%s, enabled=%s"
+ + ", mutable=%s, policy=%s, parsedInfo=%s}", packageName, enabled,
+ mutable, policy, parsedInfo);
+ }
+ }
+
+ static class OverlayPartition extends SystemPartition {
+ // Policies passed to idmap2 during idmap creation.
+ // Keep partition policy constants in sync with f/b/cmds/idmap2/include/idmap2/Policies.h.
+ static final String POLICY_ODM = "odm";
+ static final String POLICY_OEM = "oem";
+ static final String POLICY_PRODUCT = "product";
+ static final String POLICY_PUBLIC = "public";
+ static final String POLICY_SYSTEM = "system";
+ static final String POLICY_VENDOR = "vendor";
+
+ @NonNull
+ public final String policy;
+
+ OverlayPartition(@NonNull SystemPartition partition) {
+ super(partition);
+ this.policy = policyForPartition(partition);
+ }
+
+ /**
+ * Creates a partition containing the same folders as the original partition but with a
+ * different root folder.
+ */
+ OverlayPartition(@NonNull File folder, @NonNull SystemPartition original) {
+ super(folder, original);
+ this.policy = policyForPartition(original);
+ }
+
+ private static String policyForPartition(SystemPartition partition) {
+ switch (partition.type) {
+ case PackagePartitions.PARTITION_SYSTEM:
+ case PackagePartitions.PARTITION_SYSTEM_EXT:
+ return POLICY_SYSTEM;
+ case PackagePartitions.PARTITION_VENDOR:
+ return POLICY_VENDOR;
+ case PackagePartitions.PARTITION_ODM:
+ return POLICY_ODM;
+ case PackagePartitions.PARTITION_OEM:
+ return POLICY_OEM;
+ case PackagePartitions.PARTITION_PRODUCT:
+ return POLICY_PRODUCT;
+ default:
+ throw new IllegalStateException("Unable to determine policy for "
+ + partition.folder);
+ }
+ }
+ }
+
+ /** This class holds state related to parsing the configurations of a partition. */
+ private static class ParsingContext {
+ // The overlay directory of the partition
+ private final OverlayPartition mPartition;
+
+ // The ordered list of configured overlays
+ private final ArrayList<ParsedConfiguration> mOrderedConfigurations = new ArrayList<>();
+
+ // The packages configured in the partition
+ private final ArraySet<String> mConfiguredOverlays = new ArraySet<>();
+
+ // Whether an mutable overlay has been configured in the partition
+ private boolean mFoundMutableOverlay;
+
+ // The current recursive depth of merging configuration files
+ private int mMergeDepth;
+
+ private ParsingContext(OverlayPartition partition) {
+ mPartition = partition;
+ }
+ }
+
+ /**
+ * Retrieves overlays configured within the partition in increasing priority order.
+ *
+ * If {@code scanner} is null, then the {@link ParsedConfiguration#parsedInfo} fields of the
+ * added configured overlays will be null and the parsing logic will not assert that the
+ * configured overlays exist within the partition.
+ *
+ * @return list of configured overlays if configuration file exists; otherwise, null
+ */
+ @Nullable
+ static ArrayList<ParsedConfiguration> getConfigurations(
+ @NonNull OverlayPartition partition, @Nullable OverlayScanner scanner) {
+ if (partition.getOverlayFolder() == null) {
+ return null;
+ }
+
+ if (scanner != null) {
+ scanner.scanDir(partition.getOverlayFolder());
+ }
+
+ final File configFile = new File(partition.getOverlayFolder(), CONFIG_DEFAULT_FILENAME);
+ if (!configFile.exists()) {
+ return null;
+ }
+
+ final ParsingContext parsingContext = new ParsingContext(partition);
+ readConfigFile(configFile, scanner, parsingContext);
+ return parsingContext.mOrderedConfigurations;
+ }
+
+ private static void readConfigFile(@NonNull File configFile, @Nullable OverlayScanner scanner,
+ @NonNull ParsingContext parsingContext) {
+ FileReader configReader;
+ try {
+ configReader = new FileReader(configFile);
+ } catch (FileNotFoundException e) {
+ Log.w(TAG, "Couldn't find or open overlay configuration file " + configFile);
+ return;
+ }
+
+ try {
+ final XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(configReader);
+ XmlUtils.beginDocument(parser, "config");
+
+ int depth = parser.getDepth();
+ while (XmlUtils.nextElementWithin(parser, depth)) {
+ final String name = parser.getName();
+ switch (name) {
+ case "merge":
+ parseMerge(configFile, parser, scanner, parsingContext);
+ break;
+ case "overlay":
+ parseOverlay(configFile, parser, scanner, parsingContext);
+ break;
+ default:
+ Log.w(TAG, String.format("Tag %s is unknown in %s at %s",
+ name, configFile, parser.getPositionDescription()));
+ break;
+ }
+ }
+ } catch (XmlPullParserException | IOException e) {
+ Log.w(TAG, "Got exception parsing overlay configuration.", e);
+ } finally {
+ IoUtils.closeQuietly(configReader);
+ }
+ }
+
+ /**
+ * Parses a <merge> tag within an overlay configuration file.
+ *
+ * Merge tags allow for other configuration files to be "merged" at the current parsing
+ * position into the current configuration file being parsed. The {@code path} attribute of the
+ * tag represents the path of the file to merge relative to the directory containing overlay
+ * configuration files.
+ */
+ private static void parseMerge(@NonNull File configFile, @NonNull XmlPullParser parser,
+ @Nullable OverlayScanner scanner, @NonNull ParsingContext parsingContext) {
+ final String path = parser.getAttributeValue(null, "path");
+ if (path == null) {
+ throw new IllegalStateException(String.format("<merge> without path in %s at %s"
+ + configFile, parser.getPositionDescription()));
+ }
+
+ if (path.startsWith("/")) {
+ throw new IllegalStateException(String.format(
+ "Path %s must be relative to the directory containing overlay configurations "
+ + " files in %s at %s ", path, configFile,
+ parser.getPositionDescription()));
+ }
+
+ if (parsingContext.mMergeDepth++ == MAXIMUM_MERGE_DEPTH) {
+ throw new IllegalStateException(String.format(
+ "Maximum <merge> depth exceeded in %s at %s", configFile,
+ parser.getPositionDescription()));
+ }
+
+ final File configDirectory;
+ final File includedConfigFile;
+ try {
+ configDirectory = new File(parsingContext.mPartition.getOverlayFolder(),
+ CONFIG_DIRECTORY).getCanonicalFile();
+ includedConfigFile = new File(configDirectory, path).getCanonicalFile();
+ } catch (IOException e) {
+ throw new IllegalStateException(
+ String.format("Couldn't find or open merged configuration file %s in %s at %s",
+ path, configFile, parser.getPositionDescription()), e);
+ }
+
+ if (!includedConfigFile.exists()) {
+ throw new IllegalStateException(
+ String.format("Merged configuration file %s does not exist in %s at %s",
+ path, configFile, parser.getPositionDescription()));
+ }
+
+ if (!FileUtils.contains(configDirectory, includedConfigFile)) {
+ throw new IllegalStateException(
+ String.format(
+ "Merged file %s outside of configuration directory in %s at %s",
+ includedConfigFile.getAbsolutePath(), includedConfigFile,
+ parser.getPositionDescription()));
+ }
+
+ readConfigFile(includedConfigFile, scanner, parsingContext);
+ parsingContext.mMergeDepth--;
+ }
+
+ /**
+ * Parses an <overlay> tag within an overlay configuration file.
+ *
+ * Requires a {@code package} attribute that indicates which package is being configured.
+ * The optional {@code enabled} attribute controls whether or not the overlay is enabled by
+ * default (default is false). The optional {@code mutable} attribute controls whether or
+ * not the overlay is mutable and can have its enabled state changed at runtime (default is
+ * true).
+ *
+ * The order in which overlays that override the same resources are configured matters. An
+ * overlay will have a greater priority than overlays with configurations preceding its own
+ * configuration.
+ *
+ * Configurations of immutable overlays must precede configurations of mutable overlays.
+ * An overlay cannot be configured in multiple locations. All configured overlay must exist
+ * within the partition of the configuration file. An overlay cannot be configured multiple
+ * times in a single partition.
+ *
+ * Overlays not listed within a configuration file will be mutable and disabled by default. The
+ * order of non-configured overlays when enabled by the OverlayManagerService is undefined.
+ */
+ private static void parseOverlay(@NonNull File configFile, @NonNull XmlPullParser parser,
+ @Nullable OverlayScanner scanner, @NonNull ParsingContext parsingContext) {
+ final String packageName = parser.getAttributeValue(null, "package");
+ if (packageName == null) {
+ throw new IllegalStateException(String.format("\"<overlay> without package in %s at %s",
+ configFile, parser.getPositionDescription()));
+ }
+
+ // Ensure the overlay being configured is present in the partition during zygote
+ // initialization.
+ ParsedOverlayInfo info = null;
+ if (scanner != null) {
+ info = scanner.getParsedInfo(packageName);
+ if (info == null|| !parsingContext.mPartition.containsOverlay(info.path)) {
+ throw new IllegalStateException(
+ String.format("overlay %s not present in partition %s in %s at %s",
+ packageName, parsingContext.mPartition.getOverlayFolder(),
+ configFile, parser.getPositionDescription()));
+ }
+ }
+
+ if (parsingContext.mConfiguredOverlays.contains(packageName)) {
+ throw new IllegalStateException(
+ String.format("overlay %s configured multiple times in a single partition"
+ + " in %s at %s", packageName, configFile,
+ parser.getPositionDescription()));
+ }
+
+ boolean isEnabled = DEFAULT_ENABLED_STATE;
+ final String enabled = parser.getAttributeValue(null, "enabled");
+ if (enabled != null) {
+ isEnabled = !"false".equals(enabled);
+ }
+
+ boolean isMutable = DEFAULT_MUTABILITY;
+ final String mutable = parser.getAttributeValue(null, "mutable");
+ if (mutable != null) {
+ isMutable = !"false".equals(mutable);
+ if (!isMutable && parsingContext.mFoundMutableOverlay) {
+ throw new IllegalStateException(String.format(
+ "immutable overlays must precede mutable overlays:"
+ + " found in %s at %s",
+ configFile, parser.getPositionDescription()));
+ }
+ }
+
+ if (isMutable) {
+ parsingContext.mFoundMutableOverlay = true;
+ } else if (!isEnabled) {
+ // Default disabled, immutable overlays may be a misconfiguration of the system so warn
+ // developers.
+ Log.w(TAG, "found default-disabled immutable overlay " + packageName);
+ }
+
+ final ParsedConfiguration Config = new ParsedConfiguration(packageName, isEnabled,
+ isMutable, parsingContext.mPartition.policy, info);
+ parsingContext.mConfiguredOverlays.add(packageName);
+ parsingContext.mOrderedConfigurations.add(Config);
+ }
+}
diff --git a/core/java/com/android/internal/content/om/OverlayScanner.java b/core/java/com/android/internal/content/om/OverlayScanner.java
new file mode 100644
index 0000000..a85cf56
--- /dev/null
+++ b/core/java/com/android/internal/content/om/OverlayScanner.java
@@ -0,0 +1,138 @@
+/*
+ * 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.internal.content.om;
+
+import static com.android.internal.content.om.OverlayConfig.TAG;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.pm.PackageParser;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.File;
+import java.util.Collection;
+
+/**
+ * This class scans a directory containing overlay APKs and extracts information from the overlay
+ * manifests by parsing the overlay manifests.
+ */
+@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+public class OverlayScanner {
+
+ /** Represents information parsed from the manifest of an overlay. */
+ public static class ParsedOverlayInfo {
+ public final String packageName;
+ public final String targetPackageName;
+ public final int targetSdkVersion;
+ public final boolean isStatic;
+ public final int priority;
+ public final File path;
+
+ public ParsedOverlayInfo(String packageName, String targetPackageName,
+ int targetSdkVersion, boolean isStatic, int priority, File path) {
+ this.packageName = packageName;
+ this.targetPackageName = targetPackageName;
+ this.targetSdkVersion = targetSdkVersion;
+ this.isStatic = isStatic;
+ this.priority = priority;
+ this.path = path;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + String.format("{packageName=%s"
+ + ", targetPackageName=%s, targetSdkVersion=%s, isStatic=%s"
+ + ", priority=%s, path=%s}",
+ packageName, targetPackageName, targetSdkVersion, isStatic, priority, path);
+ }
+ }
+
+ /**
+ * A map of overlay package name to the parsed manifest information of the latest version of
+ * the overlay.
+ */
+ private final ArrayMap<String, ParsedOverlayInfo> mParsedOverlayInfos = new ArrayMap<>();
+
+ /** Retrieves information parsed from the overlay with the package name. */
+ @Nullable
+ public final ParsedOverlayInfo getParsedInfo(String packageName) {
+ return mParsedOverlayInfos.get(packageName);
+ }
+
+ /** Retrieves all of the scanned overlays. */
+ @NonNull
+ final Collection<ParsedOverlayInfo> getAllParsedInfos() {
+ return mParsedOverlayInfos.values();
+ }
+
+ /**
+ * Recursively searches the directory for overlay APKs. If an overlay is found with the same
+ * package name as a previously scanned overlay, the info of the new overlay will replace the
+ * info of the previously scanned overlay.
+ */
+ public void scanDir(File partitionOverlayDir) {
+ if (!partitionOverlayDir.exists() || !partitionOverlayDir.isDirectory()) {
+ return;
+ }
+
+ if (!partitionOverlayDir.canRead()) {
+ Log.w(TAG, "Directory " + partitionOverlayDir + " cannot be read");
+ return;
+ }
+
+ final File[] files = partitionOverlayDir.listFiles();
+ if (files == null) {
+ return;
+ }
+
+ for (int i = 0; i < files.length; i++) {
+ final File f = files[i];
+ if (f.isDirectory()) {
+ scanDir(f);
+ }
+
+ if (!f.isFile() || !f.getPath().endsWith(".apk")) {
+ continue;
+ }
+
+ final ParsedOverlayInfo info = parseOverlayManifest(f);
+ if (info == null) {
+ continue;
+ }
+
+ mParsedOverlayInfos.put(info.packageName, info);
+ }
+ }
+
+ /** Extracts information about the overlay from its manifest. */
+ @VisibleForTesting
+ public ParsedOverlayInfo parseOverlayManifest(File overlayApk) {
+ try {
+ final PackageParser.ApkLite apkLite = PackageParser.parseApkLite(overlayApk, 0);
+ return apkLite.targetPackageName == null ? null :
+ new ParsedOverlayInfo(apkLite.packageName, apkLite.targetPackageName,
+ apkLite.targetSdkVersion, apkLite.overlayIsStatic,
+ apkLite.overlayPriority, new File(apkLite.codePath));
+ } catch (PackageParser.PackageParserException e) {
+ Log.w(TAG, "Got exception loading overlay.", e);
+ return null;
+ }
+ }
+}
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 07ea876..5912f40 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -153,7 +153,7 @@
"android_util_Binder.cpp",
"android_util_MemoryIntArray.cpp",
"android_util_Process.cpp",
- "android_media_AudioDevice.cpp",
+ "android_media_AudioDeviceAttributes.cpp",
"android_media_AudioEffectDescriptor.cpp",
"android_media_AudioRecord.cpp",
"android_media_AudioSystem.cpp",
@@ -197,6 +197,7 @@
"android_content_res_ObbScanner.cpp",
"android_content_res_Configuration.cpp",
"android_security_Scrypt.cpp",
+ "com_android_internal_content_om_OverlayConfig.cpp",
"com_android_internal_os_ClassLoaderFactory.cpp",
"com_android_internal_os_FuseAppLoop.cpp",
"com_android_internal_os_KernelCpuUidBpfMapReader.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index c6eb8f2..4879478 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -86,7 +86,7 @@
extern int register_android_hardware_UsbRequest(JNIEnv *env);
extern int register_android_hardware_location_ActivityRecognitionHardware(JNIEnv* env);
-extern int register_android_media_AudioDevice(JNIEnv* env);
+extern int register_android_media_AudioDeviceAttributes(JNIEnv* env);
extern int register_android_media_AudioEffectDescriptor(JNIEnv *env);
extern int register_android_media_AudioRecord(JNIEnv *env);
extern int register_android_media_AudioSystem(JNIEnv *env);
@@ -186,6 +186,7 @@
extern int register_android_animation_PropertyValuesHolder(JNIEnv *env);
extern int register_android_security_Scrypt(JNIEnv *env);
extern int register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env);
+extern int register_com_android_internal_content_om_OverlayConfig(JNIEnv *env);
extern int register_com_android_internal_os_ClassLoaderFactory(JNIEnv* env);
extern int register_com_android_internal_os_FuseAppLoop(JNIEnv* env);
extern int register_com_android_internal_os_KernelCpuUidBpfMapReader(JNIEnv *env);
@@ -1499,6 +1500,7 @@
REG_JNI(register_android_os_MemoryFile),
REG_JNI(register_android_os_SharedMemory),
REG_JNI(register_android_os_incremental_IncrementalManager),
+ REG_JNI(register_com_android_internal_content_om_OverlayConfig),
REG_JNI(register_com_android_internal_os_ClassLoaderFactory),
REG_JNI(register_com_android_internal_os_Zygote),
REG_JNI(register_com_android_internal_os_ZygoteInit),
@@ -1515,7 +1517,7 @@
REG_JNI(register_android_hardware_UsbDeviceConnection),
REG_JNI(register_android_hardware_UsbRequest),
REG_JNI(register_android_hardware_location_ActivityRecognitionHardware),
- REG_JNI(register_android_media_AudioDevice),
+ REG_JNI(register_android_media_AudioDeviceAttributes),
REG_JNI(register_android_media_AudioEffectDescriptor),
REG_JNI(register_android_media_AudioSystem),
REG_JNI(register_android_media_AudioRecord),
diff --git a/core/jni/android_media_AudioDevice.cpp b/core/jni/android_media_AudioDeviceAttributes.cpp
similarity index 64%
rename from core/jni/android_media_AudioDevice.cpp
rename to core/jni/android_media_AudioDeviceAttributes.cpp
index f6a0e4b..e79c95e 100644
--- a/core/jni/android_media_AudioDevice.cpp
+++ b/core/jni/android_media_AudioDeviceAttributes.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "android_media_AudioDevice.h"
+#include "android_media_AudioDeviceAttributes.h"
#include "android_media_AudioErrors.h"
#include "core_jni_helpers.h"
@@ -22,29 +22,30 @@
using namespace android;
-static jclass gAudioDeviceClass;
-static jmethodID gAudioDeviceCstor;
+static jclass gAudioDeviceAttributesClass;
+static jmethodID gAudioDeviceAttributesCstor;
namespace android {
-jint createAudioDeviceFromNative(JNIEnv *env, jobject *jAudioDevice,
+jint createAudioDeviceAttributesFromNative(JNIEnv *env, jobject *jAudioDeviceAttributes,
const AudioDeviceTypeAddr *devTypeAddr) {
jint jStatus = (jint)AUDIO_JAVA_SUCCESS;
jint jNativeType = (jint)devTypeAddr->mType;
ScopedLocalRef<jstring> jAddress(env, env->NewStringUTF(devTypeAddr->mAddress.data()));
- *jAudioDevice =
- env->NewObject(gAudioDeviceClass, gAudioDeviceCstor, jNativeType, jAddress.get());
+ *jAudioDeviceAttributes = env->NewObject(gAudioDeviceAttributesClass, gAudioDeviceAttributesCstor,
+ jNativeType, jAddress.get());
return jStatus;
}
} // namespace android
-int register_android_media_AudioDevice(JNIEnv *env) {
- jclass audioDeviceTypeAddressClass = FindClassOrDie(env, "android/media/AudioDevice");
- gAudioDeviceClass = MakeGlobalRefOrDie(env, audioDeviceTypeAddressClass);
- gAudioDeviceCstor =
+int register_android_media_AudioDeviceAttributes(JNIEnv *env) {
+ jclass audioDeviceTypeAddressClass =
+ FindClassOrDie(env, "android/media/AudioDeviceAttributes");
+ gAudioDeviceAttributesClass = MakeGlobalRefOrDie(env, audioDeviceTypeAddressClass);
+ gAudioDeviceAttributesCstor =
GetMethodIDOrDie(env, audioDeviceTypeAddressClass, "<init>", "(ILjava/lang/String;)V");
return 0;
diff --git a/core/jni/android_media_AudioDevice.h b/core/jni/android_media_AudioDeviceAttributes.h
similarity index 75%
rename from core/jni/android_media_AudioDevice.h
rename to core/jni/android_media_AudioDeviceAttributes.h
index fc92334..b49d9ba 100644
--- a/core/jni/android_media_AudioDevice.h
+++ b/core/jni/android_media_AudioDeviceAttributes.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_MEDIA_AUDIODEVICE_H
-#define ANDROID_MEDIA_AUDIODEVICE_H
+#ifndef ANDROID_MEDIA_AUDIODEVICEATTRIBUTES_H
+#define ANDROID_MEDIA_AUDIODEVICEATTRIBUTES_H
#include <media/AudioDeviceTypeAddr.h>
#include <system/audio.h>
@@ -24,9 +24,9 @@
namespace android {
-// Create a Java AudioDevice instance from a C++ AudioDeviceTypeAddress
+// Create a Java AudioDeviceAttributes instance from a C++ AudioDeviceTypeAddress
-extern jint createAudioDeviceFromNative(JNIEnv *env, jobject *jAudioDevice,
+extern jint createAudioDeviceAttributesFromNative(JNIEnv *env, jobject *jAudioDeviceAttributes,
const AudioDeviceTypeAddr *devTypeAddr);
} // namespace android
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index d8f30e9..ab3cf30 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -34,7 +34,7 @@
#include <system/audio.h>
#include <system/audio_policy.h>
#include "android_media_AudioAttributes.h"
-#include "android_media_AudioDevice.h"
+#include "android_media_AudioDeviceAttributes.h"
#include "android_media_AudioEffectDescriptor.h"
#include "android_media_AudioErrors.h"
#include "android_media_AudioFormat.h"
@@ -2352,7 +2352,7 @@
jint strategy, jobjectArray jDeviceArray)
{
if (jDeviceArray == nullptr || env->GetArrayLength(jDeviceArray) != 1) {
- ALOGE("%s invalid array to store AudioDevice", __FUNCTION__);
+ ALOGE("%s invalid array to store AudioDeviceAttributes", __FUNCTION__);
return (jint)AUDIO_JAVA_BAD_VALUE;
}
@@ -2362,10 +2362,10 @@
if (status != NO_ERROR) {
return (jint) status;
}
- jobject jAudioDevice = NULL;
- jint jStatus = createAudioDeviceFromNative(env, &jAudioDevice, &elDevice);
+ jobject jAudioDeviceAttributes = NULL;
+ jint jStatus = createAudioDeviceAttributesFromNative(env, &jAudioDeviceAttributes, &elDevice);
if (jStatus == AUDIO_JAVA_SUCCESS) {
- env->SetObjectArrayElement(jDeviceArray, 0, jAudioDevice);
+ env->SetObjectArrayElement(jDeviceArray, 0, jAudioDeviceAttributes);
}
return jStatus;
}
@@ -2380,7 +2380,7 @@
// with reverse JNI to make the array grow as need as this would be less efficient, and some
// components call this method often
if (jDeviceArray == nullptr || maxResultSize == 0) {
- ALOGE("%s invalid array to store AudioDevice", __FUNCTION__);
+ ALOGE("%s invalid array to store AudioDeviceAttributes", __FUNCTION__);
return (jint)AUDIO_JAVA_BAD_VALUE;
}
@@ -2401,13 +2401,13 @@
return AUDIO_JAVA_INVALID_OPERATION;
}
size_t index = 0;
- jobject jAudioDevice = NULL;
+ jobject jAudioDeviceAttributes = NULL;
for (const auto& device : devices) {
- jStatus = createAudioDeviceFromNative(env, &jAudioDevice, &device);
+ jStatus = createAudioDeviceAttributesFromNative(env, &jAudioDeviceAttributes, &device);
if (jStatus != AUDIO_JAVA_SUCCESS) {
return jStatus;
}
- env->SetObjectArrayElement(jDeviceArray, index++, jAudioDevice);
+ env->SetObjectArrayElement(jDeviceArray, index++, jAudioDeviceAttributes);
}
return jStatus;
}
@@ -2519,10 +2519,10 @@
(void *)android_media_AudioSystem_setPreferredDeviceForStrategy},
{"removePreferredDeviceForStrategy", "(I)I",
(void *)android_media_AudioSystem_removePreferredDeviceForStrategy},
- {"getPreferredDeviceForStrategy", "(I[Landroid/media/AudioDevice;)I",
+ {"getPreferredDeviceForStrategy", "(I[Landroid/media/AudioDeviceAttributes;)I",
(void *)android_media_AudioSystem_getPreferredDeviceForStrategy},
{"getDevicesForAttributes",
- "(Landroid/media/AudioAttributes;[Landroid/media/AudioDevice;)I",
+ "(Landroid/media/AudioAttributes;[Landroid/media/AudioDeviceAttributes;)I",
(void *)android_media_AudioSystem_getDevicesForAttributes},
{"setUserIdDeviceAffinities", "(I[I[Ljava/lang/String;)I",
(void *)android_media_AudioSystem_setUserIdDeviceAffinities},
diff --git a/core/jni/com_android_internal_content_om_OverlayConfig.cpp b/core/jni/com_android_internal_content_om_OverlayConfig.cpp
new file mode 100644
index 0000000..6aa7c10
--- /dev/null
+++ b/core/jni/com_android_internal_content_om_OverlayConfig.cpp
@@ -0,0 +1,122 @@
+/*
+ * 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 <sstream>
+#include <string>
+#include <vector>
+
+#include <nativehelper/JNIHelp.h>
+#include "jni.h"
+#include "core_jni_helpers.h"
+
+#include "android-base/logging.h"
+#include "androidfw/PosixUtils.h"
+
+using ::android::util::ExecuteBinary;
+
+static jclass g_stringClass = nullptr;
+
+static jobjectArray createIdmap(JNIEnv* env, jclass /*clazz*/, jstring targetPath,
+ jobjectArray overlayPath, jobjectArray policies,
+ jboolean enforceOverlayable) {
+ if (access("/system/bin/idmap2", X_OK) == -1) {
+ PLOG(WARNING) << "unable to execute idmap2";
+ return nullptr;
+ }
+
+ const char* targetApkPath = env->GetStringUTFChars(targetPath, NULL /* isCopy */);
+ std::vector<std::string> argv{"/system/bin/idmap2",
+ "create-multiple",
+ "--target-apk-path", targetApkPath,
+ };
+ env->ReleaseStringUTFChars(targetPath, targetApkPath);
+
+ // Add the overlays for which to generate idmap files to the idmap arguments.
+ for (size_t i = 0, count = env->GetArrayLength(overlayPath); i < count; ++i) {
+ jstring element = (jstring) env->GetObjectArrayElement(overlayPath, i);
+ const char* overlayApkPath = env->GetStringUTFChars(element, NULL /* isCopy */);
+ argv.emplace_back("--overlay-apk-path");
+ argv.emplace_back(overlayApkPath);
+ env->ReleaseStringUTFChars(element, overlayApkPath);
+ }
+
+ // Add the policies the overlays fulfill to the idmap arguments.
+ for (size_t i = 0, count = env->GetArrayLength(policies); i < count; ++i) {
+ jstring element = (jstring)env->GetObjectArrayElement(policies, i);
+ const char* policy = env->GetStringUTFChars(element, NULL /* isCopy */);
+ argv.emplace_back("--policy");
+ argv.emplace_back(policy);
+ env->ReleaseStringUTFChars(element, policy);
+ }
+
+ if (!enforceOverlayable) {
+ argv.emplace_back("--ignore-overlayable");
+ }
+
+ const auto result = ExecuteBinary(argv);
+ if (!result) {
+ LOG(ERROR) << "failed to execute idmap2";
+ return nullptr;
+ }
+
+ if (result->status != 0) {
+ LOG(ERROR) << "idmap2: " << result->stderr;
+ return nullptr;
+ }
+
+ // Return the paths of the idmaps created or updated during the idmap invocation.
+ std::vector<std::string> idmap_paths;
+ std::istringstream input(result->stdout);
+ std::string path;
+ while (std::getline(input, path)) {
+ idmap_paths.push_back(path);
+ }
+
+ jobjectArray array = env->NewObjectArray(idmap_paths.size(), g_stringClass, nullptr);
+ if (array == nullptr) {
+ return nullptr;
+ }
+ for (size_t i = 0; i < idmap_paths.size(); i++) {
+ const std::string path = idmap_paths[i];
+ jstring java_string = env->NewStringUTF(path.c_str());
+ if (env->ExceptionCheck()) {
+ return nullptr;
+ }
+ env->SetObjectArrayElement(array, i, java_string);
+ env->DeleteLocalRef(java_string);
+ }
+
+ return array;
+}
+
+static const JNINativeMethod g_methods[] = {
+ { "createIdmap",
+ "(Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;Z)[Ljava/lang/String;",
+ (void *)createIdmap },
+};
+
+static const char* const kOverlayConfigPathName = "com/android/internal/content/om/OverlayConfig";
+
+namespace android {
+
+int register_com_android_internal_content_om_OverlayConfig(JNIEnv* env) {
+ jclass stringClass = FindClassOrDie(env, "java/lang/String");
+ g_stringClass = MakeGlobalRefOrDie(env, stringClass);
+
+ return RegisterMethodsOrDie(env, kOverlayConfigPathName, g_methods, NELEM(g_methods));
+}
+
+} // namespace android
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index b82591f..c15b794 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3534,9 +3534,6 @@
<item>com.android.dialer</item>
</string-array>
- <!-- An array of packages which can listen for notifications on low ram devices. -->
- <string-array translatable="false" name="config_allowedManagedServicesOnLowRamDevices" />
-
<!-- The default value for transition animation scale found in developer settings.
1.0 corresponds to 1x animator scale, 0 means that there will be no transition
animations. Note that this is only a default and will be overridden by a
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 89cc770..b8dd418 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3167,8 +3167,6 @@
<java-symbol type="array" name="config_nonBlockableNotificationPackages" />
<java-symbol type="array" name="config_priorityOnlyDndExemptPackages" />
- <java-symbol type="array" name="config_allowedManagedServicesOnLowRamDevices" />
-
<!-- Screen-size-dependent modes for picker dialogs. -->
<java-symbol type="integer" name="time_picker_mode" />
<java-symbol type="integer" name="date_picker_mode" />
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index 18778b9..0785e42 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -114,6 +114,7 @@
":FrameworksCoreTests_keyset_splata_api",
":FrameworksCoreTests_keyset_splat_api",
":FrameworksCoreTests_locales",
+ ":FrameworksCoreTests_overlay_config",
":FrameworksCoreTests_version_1",
":FrameworksCoreTests_version_1_diff",
":FrameworksCoreTests_version_1_nosys",
diff --git a/core/tests/coretests/apks/overlay_config/Android.bp b/core/tests/coretests/apks/overlay_config/Android.bp
new file mode 100644
index 0000000..9573557
--- /dev/null
+++ b/core/tests/coretests/apks/overlay_config/Android.bp
@@ -0,0 +1,4 @@
+android_test_helper_app {
+ name: "FrameworksCoreTests_overlay_config",
+ defaults: ["FrameworksCoreTests_apks_defaults"],
+}
diff --git a/core/tests/coretests/apks/overlay_config/AndroidManifest.xml b/core/tests/coretests/apks/overlay_config/AndroidManifest.xml
new file mode 100644
index 0000000..b15338e
--- /dev/null
+++ b/core/tests/coretests/apks/overlay_config/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 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.
+ -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.frameworks.coretests.overlay_config">
+
+ <application android:hasCode="false" />
+
+ <uses-sdk android:targetSdkVersion="21"/>
+
+ <overlay android:targetPackage="android"
+ android:targetName="TestResources" />
+</manifest>
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java
index b71c580..75a7504 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java
@@ -157,4 +157,8 @@
}
public void takeScreenshot(int displayId, RemoteCallback callback) {}
+
+ public void setTouchExplorationPassthroughRegion(int displayId, Region region) {}
+
+ public void setGestureDetectionPassthroughRegion(int displayId, Region region) {}
}
diff --git a/core/tests/coretests/src/com/android/internal/content/OverlayConfigIterationRule.java b/core/tests/coretests/src/com/android/internal/content/OverlayConfigIterationRule.java
new file mode 100644
index 0000000..23655a0
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/content/OverlayConfigIterationRule.java
@@ -0,0 +1,162 @@
+/*
+ * 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.internal.content;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.when;
+
+import android.content.pm.parsing.AndroidPackage;
+import android.os.Build;
+import android.util.ArrayMap;
+
+import com.android.internal.content.om.OverlayConfig.AndroidPackageProvider;
+import com.android.internal.content.om.OverlayScanner;
+import com.android.internal.content.om.OverlayScanner.ParsedOverlayInfo;
+
+import org.junit.Assert;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Map;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+/**
+ * A {@link TestRule} that runs a test case twice. First, the test case runs with a non-null
+ * {@link OverlayScanner} as if the zygote process is scanning the overlay packages
+ * and parsing configuration files. The test case then runs with a non-null
+ * {@link AndroidPackageProvider} as if the system server is parsing configuration files.
+ *
+ * This simulates what will happen on device. If an exception would be thrown in the zygote, then
+ * the exception should be thrown in the first run of the test case.
+ */
+public class OverlayConfigIterationRule implements TestRule {
+
+ enum Iteration {
+ ZYGOTE,
+ SYSTEM_SERVER,
+ }
+
+ private final ArrayMap<File, ParsedOverlayInfo> mOverlayStubResults = new ArrayMap<>();
+ private Supplier<OverlayScanner> mOverlayScanner;
+ private AndroidPackageProvider mAndroidPackageProvider;
+ private Iteration mIteration;
+
+ /**
+ * Mocks the parsing of the file to make it appear to the scanner that the file is a valid
+ * overlay APK.
+ **/
+ void addOverlay(File path, String packageName, String targetPackage, int targetSdkVersion,
+ boolean isStatic, int priority) {
+ try {
+ final File canonicalPath = new File(path.getCanonicalPath());
+ mOverlayStubResults.put(canonicalPath, new ParsedOverlayInfo(
+ packageName, targetPackage, targetSdkVersion, isStatic, priority,
+ canonicalPath));
+ } catch (IOException e) {
+ Assert.fail("Failed to add overlay " + e);
+ }
+ }
+
+ void addOverlay(File path, String packageName) {
+ addOverlay(path, packageName, "target");
+ }
+
+ void addOverlay(File path, String packageName, String targetPackage) {
+ addOverlay(path, packageName, targetPackage, Build.VERSION_CODES.CUR_DEVELOPMENT);
+ }
+
+ void addOverlay(File path, String packageName, String targetPackage, int targetSdkVersion) {
+ addOverlay(path, packageName, targetPackage, targetSdkVersion, false, 0);
+ }
+
+ /** Retrieves the {@link OverlayScanner} for the current run of the test. */
+ Supplier<OverlayScanner> getScannerFactory() {
+ return mOverlayScanner;
+ }
+
+ /** Retrieves the {@link AndroidPackageProvider} for the current run of the test. */
+ AndroidPackageProvider getPackageProvider() {
+ return mAndroidPackageProvider;
+ }
+
+ /** Retrieves the current iteration of the test. */
+ Iteration getIteration() {
+ return mIteration;
+ }
+
+
+ @Override
+ public Statement apply(Statement base, Description description) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ // Run the test once as if the zygote process is scanning the overlay packages
+ // and parsing configuration files.
+ mOverlayScanner = () -> {
+ OverlayScanner scanner = Mockito.spy(new OverlayScanner());
+ for (Map.Entry<File, ParsedOverlayInfo> overlay :
+ mOverlayStubResults.entrySet()) {
+ doReturn(overlay.getValue()).when(scanner)
+ .parseOverlayManifest(overlay.getKey());
+ }
+ return scanner;
+ };
+ mAndroidPackageProvider = null;
+ mIteration = Iteration.ZYGOTE;
+ base.evaluate();
+
+ // Run the test once more (if the first test did not throw an exception) as if
+ // the system server is parsing the configuration files and using PackageManager to
+ // retrieving information of overlays.
+ mOverlayScanner = null;
+ mAndroidPackageProvider = Mockito.mock(AndroidPackageProvider.class);
+ mIteration = Iteration.SYSTEM_SERVER;
+ doAnswer((InvocationOnMock invocation) -> {
+ final Object[] args = invocation.getArguments();
+ final Consumer<AndroidPackage> f = (Consumer<AndroidPackage>) args[0];
+ for (Map.Entry<File, ParsedOverlayInfo> overlay :
+ mOverlayStubResults.entrySet()) {
+ final AndroidPackage a = Mockito.mock(AndroidPackage.class);
+ final ParsedOverlayInfo info = overlay.getValue();
+ when(a.getPackageName()).thenReturn(info.packageName);
+ when(a.getOverlayTarget()).thenReturn(info.targetPackageName);
+ when(a.getTargetSdkVersion()).thenReturn(info.targetSdkVersion);
+ when(a.isOverlayIsStatic()).thenReturn(info.isStatic);
+ when(a.getOverlayPriority()).thenReturn(info.priority);
+ when(a.getBaseCodePath()).thenReturn(info.path.getPath());
+ when(a.isSystem()).thenReturn(
+ !info.path.getPath().contains("data/overlay"));
+ f.accept(a);
+ }
+ return null;
+ }).when(mAndroidPackageProvider).forEachPackage(any());
+
+ base.evaluate();
+ }
+ };
+ }
+}
+
+
diff --git a/core/tests/coretests/src/com/android/internal/content/OverlayConfigTest.java b/core/tests/coretests/src/com/android/internal/content/OverlayConfigTest.java
new file mode 100644
index 0000000..dee118f
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/content/OverlayConfigTest.java
@@ -0,0 +1,603 @@
+/*
+ * 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.internal.content;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.os.FileUtils;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.frameworks.coretests.R;
+import com.android.internal.content.om.OverlayConfig;
+import com.android.internal.content.om.OverlayConfig.IdmapInvocation;
+import com.android.internal.content.om.OverlayScanner;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.RuleChain;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+
+@RunWith(AndroidJUnit4.class)
+public class OverlayConfigTest {
+ private static final String TEST_APK_PACKAGE_NAME =
+ "com.android.frameworks.coretests.overlay_config";
+
+ private ExpectedException mExpectedException = ExpectedException.none();
+ private OverlayConfigIterationRule mScannerRule = new OverlayConfigIterationRule();
+ private TemporaryFolder mTestFolder = new TemporaryFolder();
+
+ @Rule
+ public RuleChain chain = RuleChain.outerRule(mExpectedException)
+ .around(mTestFolder).around(mScannerRule);
+
+ private OverlayConfig createConfigImpl() throws IOException {
+ return new OverlayConfig(mTestFolder.getRoot().getCanonicalFile(),
+ mScannerRule.getScannerFactory(), mScannerRule.getPackageProvider());
+ }
+
+ private File createFile(String fileName) throws IOException {
+ return createFile(fileName, "");
+ }
+
+ private File createFile(String fileName, String content) throws IOException {
+ final File f = new File(String.format("%s/%s", mTestFolder.getRoot(), fileName));
+ if (!f.getParentFile().equals(mTestFolder.getRoot())) {
+ f.getParentFile().mkdirs();
+ }
+ FileUtils.stringToFile(f.getPath(), content);
+ return f;
+ }
+
+ private static void assertConfig(OverlayConfig overlayConfig, String packageName,
+ boolean mutable, boolean enabled, int configIndex) {
+ final OverlayConfig.Configuration config = overlayConfig.getConfiguration(packageName);
+ assertNotNull(config);
+ assertEquals(mutable, config.parsedConfig.mutable);
+ assertEquals(enabled, config.parsedConfig.enabled);
+ assertEquals(configIndex, config.configIndex);
+ }
+
+ @Test
+ public void testImmutableAfterNonImmutableFails() throws IOException {
+ mExpectedException.expect(IllegalStateException.class);
+ mExpectedException.expectMessage("immutable overlays must precede mutable overlays");
+
+ createFile("/product/overlay/config/config.xml",
+ "<config>"
+ + " <overlay package=\"one\" enabled=\"true\" />"
+ + " <overlay package=\"two\" mutable=\"false\" enabled=\"true\" />"
+ + "</config>");
+
+ mScannerRule.addOverlay(createFile("/product/overlay/one.apk"), "one");
+ mScannerRule.addOverlay(createFile("/product/overlay/two.apk"), "two");
+ createConfigImpl();
+ }
+
+ @Test
+ public void testConfigureAbsentPackageFails() throws IOException {
+ mExpectedException.expect(IllegalStateException.class);
+ mExpectedException.expectMessage("not present in partition");
+
+ createFile("/product/overlay/config/config.xml",
+ "<config>"
+ + " <overlay package=\"one\" enabled=\"true\" />"
+ + "</config>");
+
+ createConfigImpl();
+ }
+
+ @Test
+ public void testConfigurePackageTwiceFails() throws IOException {
+ mExpectedException.expect(IllegalStateException.class);
+ mExpectedException.expectMessage("configured multiple times in a single partition");
+
+ createFile("/product/overlay/config/config.xml",
+ "<config>"
+ + " <overlay package=\"one\" enabled=\"true\" />"
+ + " <overlay package=\"one\" mutable=\"false\" />"
+ + "</config>");
+
+ mScannerRule.addOverlay(createFile("/product/overlay/one.apk"), "one");
+ createConfigImpl();
+ }
+
+ @Test
+ public void testConfigureOverlayAcrossPartitionsFails() throws IOException {
+ mExpectedException.expect(IllegalStateException.class);
+ mExpectedException.expectMessage("not present in partition");
+
+ createFile("/vendor/overlay/config/config.xml",
+ "<config>"
+ + " <overlay package=\"one\" enabled=\"true\" />"
+ + "</config>");
+
+ mScannerRule.addOverlay(createFile("/product/overlay/one.apk"), "one");
+ createConfigImpl();
+ }
+
+ @Test
+ public void testConfigureOverlayOutsideOverlayDirFails() throws IOException {
+ mExpectedException.expect(IllegalStateException.class);
+ mExpectedException.expectMessage("not present in partition");
+
+ createFile("/vendor/overlay/config/config.xml",
+ "<config>"
+ + " <overlay package=\"one\" enabled=\"true\" />"
+ + "</config>");
+
+ mScannerRule.addOverlay(createFile("/product/app/one.apk"), "one");
+ createConfigImpl();
+ }
+
+ @Test
+ public void testMergeOAbsolutePathFails() throws IOException {
+ mExpectedException.expect(IllegalStateException.class);
+ mExpectedException.expectMessage("must be relative to the directory");
+
+ createFile("/product/overlay/config/config.xml",
+ "<config>"
+ + " <merge path=\"/product/overlay/config/auto-generated-config.xml\" />"
+ + "</config>");
+
+ createConfigImpl();
+ }
+
+ @Test
+ public void testMergeOutsideDirFails() throws IOException {
+ mExpectedException.expect(IllegalStateException.class);
+ mExpectedException.expectMessage("outside of configuration directory");
+
+ createFile("/product/overlay/auto-generated-config.xml");
+ createFile("/product/overlay/config/config.xml",
+ "<config>"
+ + " <merge path=\"../auto-generated-config.xml\" />"
+ + "</config>");
+
+ createConfigImpl();
+ }
+
+ @Test
+ public void testMergeOutsidePartitionFails() throws IOException {
+ mExpectedException.expect(IllegalStateException.class);
+ mExpectedException.expectMessage("outside of configuration directory");
+
+ createFile("/vendor/overlay/config/config2.xml");
+ createFile("/product/overlay/config/config.xml",
+ "<config>"
+ + " <merge path=\"../../../vendor/overlay/config/config2.xml\" />"
+ + "</config>");
+
+ createConfigImpl();
+ }
+
+ @Test
+ public void testMergeCircularFails() throws IOException {
+ mExpectedException.expect(IllegalStateException.class);
+ mExpectedException.expectMessage("Maximum <merge> depth exceeded");
+
+ createFile("/product/overlay/config/config.xml",
+ "<config>"
+ + " <merge path=\"config2.xml\" />"
+ + "</config>");
+ createFile("/product/overlay/config/config2.xml",
+ "<config>"
+ + " <merge path=\"config.xml\" />"
+ + "</config>");
+
+ createConfigImpl();
+ }
+
+ @Test
+ public void testMergeMissingFileFails() throws IOException {
+ mExpectedException.expect(IllegalStateException.class);
+ mExpectedException.expectMessage("does not exist");
+
+ createFile("/product/overlay/config/config.xml",
+ "<config>"
+ + " <merge path=\"config2.xml\" />"
+ + "</config>");
+ createConfigImpl();
+ }
+
+ @Test
+ public void testProductOverridesVendor() throws IOException {
+ createFile("/vendor/overlay/config/config.xml",
+ "<config>"
+ + " <overlay package=\"one\" enabled=\"false\" />"
+ + "</config>");
+ createFile("/product/overlay/config/config.xml",
+ "<config>"
+ + " <overlay package=\"one\" enabled=\"true\" />"
+ + "</config>");
+
+ mScannerRule.addOverlay(createFile("/vendor/overlay/one.apk"), "one");
+ mScannerRule.addOverlay(createFile("/product/overlay/one.apk"), "one");
+
+ final OverlayConfig overlayConfig = createConfigImpl();
+ assertConfig(overlayConfig, "one", true, true, 1);
+ }
+
+ @Test
+ public void testPartitionPrecedence() throws IOException {
+ createFile("/vendor/overlay/config/config.xml",
+ "<config>"
+ + " <overlay package=\"one\" enabled=\"true\" />"
+ + "</config>");
+ createFile("/odm/overlay/config/config.xml",
+ "<config>"
+ + " <overlay package=\"two\" enabled=\"true\" />"
+ + "</config>");
+ createFile("/oem/overlay/config/config.xml",
+ "<config>"
+ + " <overlay package=\"three\" enabled=\"true\" />"
+ + "</config>");
+ createFile("/product/overlay/config/config.xml",
+ "<config>"
+ + " <overlay package=\"four\" enabled=\"true\" />"
+ + "</config>");
+ createFile("/system_ext/overlay/config/config.xml",
+ "<config>"
+ + " <overlay package=\"five\" enabled=\"true\" />"
+ + "</config>");
+
+ mScannerRule.addOverlay(createFile("/vendor/overlay/one.apk"), "one");
+ mScannerRule.addOverlay(createFile("/odm/overlay/two.apk"), "two");
+ mScannerRule.addOverlay(createFile("/oem/overlay/three.apk"), "three");
+ mScannerRule.addOverlay(createFile("/product/overlay/four.apk"), "four");
+ mScannerRule.addOverlay(createFile("/system_ext/overlay/five.apk"), "five");
+
+ final OverlayConfig overlayConfig = createConfigImpl();
+ assertConfig(overlayConfig, "one", true, true, 0);
+ assertConfig(overlayConfig, "two", true, true, 1);
+ assertConfig(overlayConfig, "three", true, true, 2);
+ assertConfig(overlayConfig, "four", true, true, 3);
+ assertConfig(overlayConfig, "five", true, true, 4);
+ }
+
+ @Test
+ public void testImmutable() throws IOException {
+ createFile("/product/overlay/config/config.xml",
+ "<config>"
+ + " <overlay package=\"one\" mutable=\"false\" />"
+ + " <overlay package=\"two\" />"
+ + " <overlay package=\"three\" mutable=\"true\" />"
+ + "</config>");
+
+
+ mScannerRule.addOverlay(createFile("/product/overlay/one.apk"), "one");
+ mScannerRule.addOverlay(createFile("/product/overlay/two.apk"), "two");
+ mScannerRule.addOverlay(createFile("/product/overlay/three.apk"), "three");
+
+ final OverlayConfig overlayConfig = createConfigImpl();
+ assertConfig(overlayConfig, "one", false, false, 0);
+ assertConfig(overlayConfig, "two", true, false, 1);
+ assertConfig(overlayConfig, "three", true, false, 2);
+ }
+
+ @Test
+ public void testEnabled() throws IOException {
+ createFile("/product/overlay/config/config.xml",
+ "<config>"
+ + " <overlay package=\"one\" />"
+ + " <overlay package=\"two\" enabled=\"true\" />"
+ + " <overlay package=\"three\" enabled=\"false\" />"
+ + "</config>");
+
+
+ mScannerRule.addOverlay(createFile("/product/overlay/one.apk"), "one");
+ mScannerRule.addOverlay(createFile("/product/overlay/two.apk"), "two");
+ mScannerRule.addOverlay(createFile("/product/overlay/three.apk"), "three");
+
+ final OverlayConfig overlayConfig = createConfigImpl();
+ assertConfig(overlayConfig, "one", true, false, 0);
+ assertConfig(overlayConfig, "two", true, true, 1);
+ assertConfig(overlayConfig, "three", true, false, 2);
+ }
+
+ @Test
+ public void testMerge() throws IOException {
+ createFile("/product/overlay/config/auto-generated-config.xml",
+ "<config>"
+ + " <overlay package=\"two\" mutable=\"false\" enabled=\"true\" />"
+ + " <overlay package=\"three\" mutable=\"false\" enabled=\"true\" />"
+ + "</config>");
+
+ createFile("/product/overlay/config/config.xml",
+ "<config>"
+ + " <overlay package=\"one\" mutable=\"false\" enabled=\"true\" />"
+ + " <merge path=\"auto-generated-config.xml\" />"
+ + " <overlay package=\"four\" enabled=\"true\" />"
+ + "</config>");
+
+ mScannerRule.addOverlay(createFile("/product/overlay/one.apk"), "one");
+ mScannerRule.addOverlay(createFile("/product/overlay/two.apk"), "two");
+ mScannerRule.addOverlay(createFile("/product/overlay/three.apk"), "three");
+ mScannerRule.addOverlay(createFile("/product/overlay/four.apk"), "four");
+
+ final OverlayConfig overlayConfig = createConfigImpl();
+ OverlayConfig.Configuration o1 = overlayConfig.getConfiguration("one");
+ assertNotNull(o1);
+ assertFalse(o1.parsedConfig.mutable);
+ assertTrue(o1.parsedConfig.enabled);
+ assertEquals(0, o1.configIndex);
+
+ OverlayConfig.Configuration o2 = overlayConfig.getConfiguration("two");
+ assertNotNull(o2);
+ assertFalse(o2.parsedConfig.mutable);
+ assertTrue(o2.parsedConfig.enabled);
+ assertEquals(1, o2.configIndex);
+
+ OverlayConfig.Configuration o3 = overlayConfig.getConfiguration("three");
+ assertNotNull(o3);
+ assertFalse(o3.parsedConfig.mutable);
+ assertTrue(o3.parsedConfig.enabled);
+ assertEquals(2, o3.configIndex);
+
+ OverlayConfig.Configuration o4 = overlayConfig.getConfiguration("four");
+ assertNotNull(o4);
+ assertTrue(o4.parsedConfig.mutable);
+ assertTrue(o4.parsedConfig.enabled);
+ assertEquals(3, o4.configIndex);
+ }
+
+ @Test
+ public void testIdmapInvocationsFrameworkImmutable() throws IOException {
+ createFile("/vendor/overlay/config/config.xml",
+ "<config>"
+ + " <overlay package=\"one\" mutable=\"false\" enabled=\"true\" />"
+ + " <overlay package=\"two\" mutable=\"false\" enabled=\"true\" />"
+ + " <overlay package=\"three\" enabled=\"true\" />"
+ + "</config>");
+
+ createFile("/product/overlay/config/config.xml",
+ "<config>"
+ + " <overlay package=\"four\" mutable=\"false\" enabled=\"true\" />"
+ + " <overlay package=\"five\" mutable=\"false\" enabled=\"true\" />"
+ + " <overlay package=\"six\" mutable=\"false\" enabled=\"false\" />"
+ + "</config>");
+
+ mScannerRule.addOverlay(createFile("/vendor/overlay/one.apk"), "one", "android");
+ mScannerRule.addOverlay(createFile("/vendor/overlay/two.apk"), "two", "android");
+ mScannerRule.addOverlay(createFile("/vendor/overlay/three.apk"), "three", "android");
+ mScannerRule.addOverlay(createFile("/product/overlay/four.apk"), "four", "android");
+ mScannerRule.addOverlay(createFile("/product/overlay/five.apk"), "five");
+ mScannerRule.addOverlay(createFile("/product/overlay/six.apk"), "six", "android");
+
+ final OverlayConfig overlayConfig = createConfigImpl();
+ if (mScannerRule.getIteration() == OverlayConfigIterationRule.Iteration.ZYGOTE) {
+ final ArrayList<IdmapInvocation> idmapInvocations =
+ overlayConfig.getImmutableFrameworkOverlayIdmapInvocations();
+ assertEquals(2, idmapInvocations.size());
+
+ final IdmapInvocation i0 = idmapInvocations.get(0);
+ assertTrue(i0.enforceOverlayable);
+ assertEquals("vendor", i0.policy);
+ assertEquals(2, i0.overlayPaths.size());
+ assertTrue(i0.overlayPaths.get(0).endsWith("/vendor/overlay/one.apk"));
+ assertTrue(i0.overlayPaths.get(1).endsWith("/vendor/overlay/two.apk"));
+
+ final IdmapInvocation i1 = idmapInvocations.get(1);
+ assertTrue(i1.enforceOverlayable);
+ assertEquals("product", i1.policy);
+ assertEquals(1, i1.overlayPaths.size());
+ assertTrue(i1.overlayPaths.get(0).endsWith("/product/overlay/four.apk"));
+ }
+ }
+
+ @Test
+ public void testIdmapInvocationsDifferentTargetSdk() throws IOException {
+ createFile("/product/overlay/config/config.xml",
+ "<config>"
+ + " <overlay package=\"one\" mutable=\"false\" enabled=\"true\" />"
+ + " <overlay package=\"two\" mutable=\"false\" enabled=\"true\" />"
+ + " <overlay package=\"three\" mutable=\"false\" enabled=\"true\" />"
+ + " <overlay package=\"four\" mutable=\"false\" enabled=\"true\" />"
+ + "</config>");
+
+ mScannerRule.addOverlay(createFile("/product/overlay/one.apk"), "one", "android");
+ mScannerRule.addOverlay(createFile("/product/overlay/two.apk"), "two", "android");
+ mScannerRule.addOverlay(createFile("/product/overlay/three.apk"), "three", "android", 28);
+ mScannerRule.addOverlay(createFile("/product/overlay/four.apk"), "four", "android");
+
+ final OverlayConfig overlayConfig = createConfigImpl();
+
+ if (mScannerRule.getIteration() == OverlayConfigIterationRule.Iteration.ZYGOTE) {
+ final ArrayList<IdmapInvocation> idmapInvocations =
+ overlayConfig.getImmutableFrameworkOverlayIdmapInvocations();
+ assertEquals(3, idmapInvocations.size());
+
+ final IdmapInvocation i0 = idmapInvocations.get(0);
+ assertTrue(i0.enforceOverlayable);
+ assertEquals(2, i0.overlayPaths.size());
+ assertTrue(i0.overlayPaths.get(0).endsWith("/product/overlay/one.apk"));
+ assertTrue(i0.overlayPaths.get(1).endsWith("/product/overlay/two.apk"));
+
+ final IdmapInvocation i1 = idmapInvocations.get(1);
+ assertFalse(i1.enforceOverlayable);
+ assertEquals(1, i1.overlayPaths.size());
+ assertTrue(i1.overlayPaths.get(0).endsWith("/product/overlay/three.apk"));
+
+ final IdmapInvocation i2 = idmapInvocations.get(2);
+ assertTrue(i2.enforceOverlayable);
+ assertEquals(1, i2.overlayPaths.size());
+ assertTrue(i2.overlayPaths.get(0).endsWith("/product/overlay/four.apk"));
+ }
+ }
+
+ @Test
+ public void testNoConfigIsStatic() throws IOException {
+ mScannerRule.addOverlay(createFile("/product/overlay/one.apk"), "one", "android", 28, true,
+ 1);
+ mScannerRule.addOverlay(createFile("/product/overlay/two.apk"), "two", "android", 28, false,
+ 0);
+ mScannerRule.addOverlay(createFile("/product/overlay/three.apk"), "three", "android", 28,
+ true, 0);
+ mScannerRule.addOverlay(createFile("/product/overlay/four.apk"), "four", "android", 28,
+ false, 2);
+
+ final OverlayConfig overlayConfig = createConfigImpl();
+ assertConfig(overlayConfig, "one", false, true, 1);
+ assertConfig(overlayConfig, "three", false, true, 0);
+
+ }
+
+ @Test
+ public void testVendorStaticPrecedesProductImmutable() throws IOException {
+ createFile("/product/overlay/config/config.xml",
+ "<config>"
+ + " <overlay package=\"two\" mutable=\"false\" enabled=\"true\" />"
+ + "</config>");
+
+ mScannerRule.addOverlay(createFile("/vendor/overlay/one.apk"), "one", "android", 0, true,
+ 1);
+ mScannerRule.addOverlay(createFile("/product/overlay/two.apk"), "two", "android", 0, true,
+ 0);
+
+ final OverlayConfig overlayConfig = createConfigImpl();
+ assertConfig(overlayConfig, "one", false, true, 0);
+ assertConfig(overlayConfig, "two", false, true, 1);
+ }
+
+ @Test
+ public void testVendorImmutablePrecededProductStatic() throws IOException {
+ createFile("/vendor/overlay/config/config.xml",
+ "<config>"
+ + " <overlay package=\"one\" mutable=\"false\" enabled=\"true\" />"
+ + "</config>");
+
+ mScannerRule.addOverlay(createFile("/vendor/overlay/one.apk"), "one", "android", 0, true,
+ 1);
+ mScannerRule.addOverlay(createFile("/product/overlay/two.apk"), "two", "android", 0, true,
+ 0);
+
+ final OverlayConfig overlayConfig = createConfigImpl();
+ assertConfig(overlayConfig, "one", false, true, 0);
+ assertConfig(overlayConfig, "two", false, true, 1);
+ }
+
+ @Test
+ public void testNoConfigsAllowPartitionReordering() throws IOException {
+ mScannerRule.addOverlay(createFile("/vendor/overlay/one.apk"), "one", "android", 0, true,
+ 1);
+ mScannerRule.addOverlay(createFile("/product/overlay/two.apk"), "two", "android", 0, true,
+ 0);
+
+ final OverlayConfig overlayConfig = createConfigImpl();
+ assertConfig(overlayConfig, "one", false, true, 1);
+ assertConfig(overlayConfig, "two", false, true, 0);
+ }
+
+ @Test
+ public void testConfigDisablesPartitionReordering() throws IOException {
+ createFile("/odm/overlay/config/config.xml",
+ "<config>"
+ + " <overlay package=\"two\" enabled=\"true\" />"
+ + "</config>");
+
+ mScannerRule.addOverlay(createFile("/vendor/overlay/one.apk"), "one", "android", 0, true,
+ 1);
+ mScannerRule.addOverlay(createFile("/odm/overlay/two.apk"), "two");
+ mScannerRule.addOverlay(createFile("/product/overlay/three.apk"), "three", "android", 0,
+ true, 0);
+
+ final OverlayConfig overlayConfig = createConfigImpl();
+ assertConfig(overlayConfig, "one", false, true, 0);
+ assertConfig(overlayConfig, "two", true, true, 1);
+ assertConfig(overlayConfig, "three", false, true, 2);
+ }
+
+ @Test
+ public void testStaticOverlayOutsideOverlayDir() throws IOException {
+ mScannerRule.addOverlay(createFile("/product/app/one.apk"), "one", "android", 0, true, 0);
+
+ final OverlayConfig overlayConfig = createConfigImpl();
+ if (mScannerRule.getIteration() == OverlayConfigIterationRule.Iteration.SYSTEM_SERVER) {
+ assertConfig(overlayConfig, "one", false, true, 0);
+ }
+ }
+
+ @Test
+ public void testSortStaticOverlaysDifferentTargets() throws IOException {
+ mScannerRule.addOverlay(createFile("/vendor/overlay/one.apk"), "one", "other", 0, true, 0);
+ mScannerRule.addOverlay(createFile("/product/overlay/two.apk"), "two", "android", 0, true,
+ 0);
+
+ final OverlayConfig overlayConfig = createConfigImpl();
+ assertConfig(overlayConfig, "one", false, true, 1);
+ assertConfig(overlayConfig, "two", false, true, 0);
+ }
+
+ @Test
+ public void testSortStaticOverlaysSamePriority() throws IOException {
+ mScannerRule.addOverlay(createFile("/vendor/overlay/one.apk"), "one", "android", 0, true,
+ 0);
+ mScannerRule.addOverlay(createFile("/product/overlay/two.apk"), "two", "android", 0, true,
+ 0);
+
+ final OverlayConfig overlayConfig = createConfigImpl();
+ assertConfig(overlayConfig, "one", false, true, 1);
+ assertConfig(overlayConfig, "two", false, true, 0);
+ }
+
+ @Test
+ public void testNonSystemOverlayCannotBeStatic() throws IOException {
+ mScannerRule.addOverlay(createFile("/data/overlay/one.apk"), "one", "android", 0, true,
+ 0);
+
+ final OverlayConfig overlayConfig = createConfigImpl();
+ assertTrue(overlayConfig.isMutable("one"));
+ assertFalse(overlayConfig.isEnabled("one"));
+ assertEquals(Integer.MAX_VALUE, overlayConfig.getPriority("one"));
+ }
+
+ @Test
+ public void testGetOverlayInfo() throws IOException {
+ if (mScannerRule.getIteration() != OverlayConfigIterationRule.Iteration.ZYGOTE) {
+ // Run only one iteration of the test.
+ return;
+ }
+
+ final InputStream is = InstrumentationRegistry.getContext().getResources()
+ .openRawResource(R.raw.overlay_config);
+ final File partitionDir = mTestFolder.newFolder("product", "overlay");
+ final File testApk = new File(partitionDir, "test.apk");
+ FileUtils.copy(is, new FileOutputStream(testApk));
+
+ final OverlayScanner scanner = new OverlayScanner();
+ scanner.scanDir(partitionDir);
+
+ final OverlayScanner.ParsedOverlayInfo info = scanner.getParsedInfo(TEST_APK_PACKAGE_NAME);
+ assertNotNull(info);
+ assertEquals(TEST_APK_PACKAGE_NAME, info.packageName);
+ assertEquals("android", info.targetPackageName);
+ assertEquals(testApk.getPath(), info.path.getPath());
+ assertEquals(21, info.targetSdkVersion);
+ }
+}
diff --git a/media/java/android/media/AudioDevice.aidl b/media/java/android/media/AudioDeviceAttributes.aidl
similarity index 94%
rename from media/java/android/media/AudioDevice.aidl
rename to media/java/android/media/AudioDeviceAttributes.aidl
index 02071e5..82d4226 100644
--- a/media/java/android/media/AudioDevice.aidl
+++ b/media/java/android/media/AudioDeviceAttributes.aidl
@@ -15,4 +15,4 @@
package android.media;
-parcelable AudioDevice;
+parcelable AudioDeviceAttributes;
diff --git a/media/java/android/media/AudioDevice.java b/media/java/android/media/AudioDeviceAttributes.java
similarity index 82%
rename from media/java/android/media/AudioDevice.java
rename to media/java/android/media/AudioDeviceAttributes.java
index 31ecc7b..f5b0806 100644
--- a/media/java/android/media/AudioDevice.java
+++ b/media/java/android/media/AudioDeviceAttributes.java
@@ -28,8 +28,8 @@
/**
* @hide
- * Class to represent device type (speaker, headset...), address (if known) and role (input, output)
- * of an audio device.
+ * Class to represent the attributes of an audio device: its type (speaker, headset...), address
+ * (if known) and role (input, output).
* <p>Unlike {@link AudioDeviceInfo}, the device
* doesn't need to be connected to be uniquely identified, it can
* for instance represent a specific A2DP headset even after a
@@ -39,7 +39,7 @@
* permission, APIs using one rely on MODIFY_AUDIO_ROUTING.
*/
@SystemApi
-public final class AudioDevice implements Parcelable {
+public final class AudioDeviceAttributes implements Parcelable {
/**
* A role identifying input devices, such as microphones.
@@ -78,7 +78,7 @@
* type and address.
*/
@SystemApi
- public AudioDevice(@NonNull AudioDeviceInfo deviceInfo) {
+ public AudioDeviceAttributes(@NonNull AudioDeviceInfo deviceInfo) {
Objects.requireNonNull(deviceInfo);
mRole = deviceInfo.isSink() ? ROLE_OUTPUT : ROLE_INPUT;
mType = deviceInfo.getType();
@@ -93,7 +93,7 @@
* @param address the address of the device, or an empty string for devices without one
*/
@SystemApi
- public AudioDevice(@Role int role, @AudioDeviceInfo.AudioDeviceType int type,
+ public AudioDeviceAttributes(@Role int role, @AudioDeviceInfo.AudioDeviceType int type,
@NonNull String address) {
Objects.requireNonNull(address);
if (role != ROLE_OUTPUT && role != ROLE_INPUT) {
@@ -111,7 +111,7 @@
mAddress = address;
}
- /*package*/ AudioDevice(int nativeType, @NonNull String address) {
+ /*package*/ AudioDeviceAttributes(int nativeType, @NonNull String address) {
mRole = (nativeType & AudioSystem.DEVICE_BIT_IN) != 0 ? ROLE_INPUT : ROLE_OUTPUT;
mType = AudioDeviceInfo.convertInternalDeviceToDeviceType(nativeType);
mAddress = address;
@@ -157,7 +157,7 @@
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
- AudioDevice that = (AudioDevice) o;
+ AudioDeviceAttributes that = (AudioDeviceAttributes) o;
return ((mRole == that.mRole)
&& (mType == that.mType)
&& mAddress.equals(that.mAddress));
@@ -170,7 +170,7 @@
@Override
public String toString() {
- return new String("AudioDevice:"
+ return new String("AudioDeviceAttributes:"
+ " role:" + roleToString(mRole)
+ " type:" + (mRole == ROLE_OUTPUT ? AudioSystem.getOutputDeviceName(
AudioDeviceInfo.convertDeviceTypeToInternalDevice(mType))
@@ -191,25 +191,25 @@
dest.writeString(mAddress);
}
- private AudioDevice(@NonNull Parcel in) {
+ private AudioDeviceAttributes(@NonNull Parcel in) {
mRole = in.readInt();
mType = in.readInt();
mAddress = in.readString();
}
- public static final @NonNull Parcelable.Creator<AudioDevice> CREATOR =
- new Parcelable.Creator<AudioDevice>() {
+ public static final @NonNull Parcelable.Creator<AudioDeviceAttributes> CREATOR =
+ new Parcelable.Creator<AudioDeviceAttributes>() {
/**
- * Rebuilds an AudioDevice previously stored with writeToParcel().
- * @param p Parcel object to read the AudioDevice from
- * @return a new AudioDevice created from the data in the parcel
+ * Rebuilds an AudioDeviceAttributes previously stored with writeToParcel().
+ * @param p Parcel object to read the AudioDeviceAttributes from
+ * @return a new AudioDeviceAttributes created from the data in the parcel
*/
- public AudioDevice createFromParcel(Parcel p) {
- return new AudioDevice(p);
+ public AudioDeviceAttributes createFromParcel(Parcel p) {
+ return new AudioDeviceAttributes(p);
}
- public AudioDevice[] newArray(int size) {
- return new AudioDevice[size];
+ public AudioDeviceAttributes[] newArray(int size) {
+ return new AudioDeviceAttributes[size];
}
};
}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 112bb9c..0b825f6 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -1597,7 +1597,7 @@
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
public boolean setPreferredDeviceForStrategy(@NonNull AudioProductStrategy strategy,
- @NonNull AudioDevice device) {
+ @NonNull AudioDeviceAttributes device) {
Objects.requireNonNull(strategy);
Objects.requireNonNull(device);
try {
@@ -1612,7 +1612,7 @@
/**
* @hide
* Removes the preferred audio device previously set with
- * {@link #setPreferredDeviceForStrategy(AudioProductStrategy, AudioDevice)}.
+ * {@link #setPreferredDeviceForStrategy(AudioProductStrategy, AudioDeviceAttributes)}.
* @param strategy the audio strategy whose routing will be affected
* @return true if the operation was successful, false otherwise (invalid strategy, or no
* device set for example)
@@ -1633,14 +1633,14 @@
/**
* @hide
* Return the preferred device for an audio strategy, previously set with
- * {@link #setPreferredDeviceForStrategy(AudioProductStrategy, AudioDevice)}
+ * {@link #setPreferredDeviceForStrategy(AudioProductStrategy, AudioDeviceAttributes)}
* @param strategy the strategy to query
* @return the preferred device for that strategy, or null if none was ever set or if the
* strategy is invalid
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
- public @Nullable AudioDevice getPreferredDeviceForStrategy(
+ public @Nullable AudioDeviceAttributes getPreferredDeviceForStrategy(
@NonNull AudioProductStrategy strategy) {
Objects.requireNonNull(strategy);
try {
@@ -1654,7 +1654,7 @@
* @hide
* Interface to be notified of changes in the preferred audio device set for a given audio
* strategy.
- * @see #setPreferredDeviceForStrategy(AudioProductStrategy, AudioDevice)
+ * @see #setPreferredDeviceForStrategy(AudioProductStrategy, AudioDeviceAttributes)
* @see #removePreferredDeviceForStrategy(AudioProductStrategy)
* @see #getPreferredDeviceForStrategy(AudioProductStrategy)
*/
@@ -1668,7 +1668,7 @@
* preferred audio device
*/
void onPreferredDeviceForStrategyChanged(@NonNull AudioProductStrategy strategy,
- @Nullable AudioDevice device);
+ @Nullable AudioDeviceAttributes device);
}
/**
@@ -1768,7 +1768,8 @@
extends IStrategyPreferredDeviceDispatcher.Stub {
@Override
- public void dispatchPrefDeviceChanged(int strategyId, @Nullable AudioDevice device) {
+ public void dispatchPrefDeviceChanged(int strategyId,
+ @Nullable AudioDeviceAttributes device) {
// make a shallow copy of listeners so callback is not executed under lock
final ArrayList<PrefDevListenerInfo> prefDevListeners;
synchronized (mPrefDevListenerLock) {
@@ -4553,7 +4554,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
- public @NonNull List<AudioDevice> getDevicesForAttributes(
+ public @NonNull List<AudioDeviceAttributes> getDevicesForAttributes(
@NonNull AudioAttributes attributes) {
Objects.requireNonNull(attributes);
final IAudioService service = getService();
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 53379b87..8b973a1 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -1096,18 +1096,18 @@
* @return an empty list if there was an issue with the request, a list of audio devices
* otherwise (typically one device, except for duplicated paths).
*/
- public static @NonNull ArrayList<AudioDevice> getDevicesForAttributes(
+ public static @NonNull ArrayList<AudioDeviceAttributes> getDevicesForAttributes(
@NonNull AudioAttributes attributes) {
Objects.requireNonNull(attributes);
- final AudioDevice[] devices = new AudioDevice[MAX_DEVICE_ROUTING];
+ final AudioDeviceAttributes[] devices = new AudioDeviceAttributes[MAX_DEVICE_ROUTING];
final int res = getDevicesForAttributes(attributes, devices);
- final ArrayList<AudioDevice> routeDevices = new ArrayList<>();
+ final ArrayList<AudioDeviceAttributes> routeDevices = new ArrayList<>();
if (res != SUCCESS) {
Log.e(TAG, "error " + res + " in getDevicesForAttributes for " + attributes);
return routeDevices;
}
- for (AudioDevice device : devices) {
+ for (AudioDeviceAttributes device : devices) {
if (device != null) {
routeDevices.add(device);
}
@@ -1117,12 +1117,12 @@
/**
* Maximum number of audio devices a track is ever routed to, determines the size of the
- * array passed to {@link #getDevicesForAttributes(AudioAttributes, AudioDevice[])}
+ * array passed to {@link #getDevicesForAttributes(AudioAttributes, AudioDeviceAttributes[])}
*/
private static final int MAX_DEVICE_ROUTING = 4;
private static native int getDevicesForAttributes(@NonNull AudioAttributes aa,
- @NonNull AudioDevice[] devices);
+ @NonNull AudioDeviceAttributes[] devices);
/** @hide returns true if master mono is enabled. */
public static native boolean getMasterMono();
@@ -1257,7 +1257,7 @@
* @return {@link #SUCCESS} if successfully set
*/
public static int setPreferredDeviceForStrategy(
- int strategy, @NonNull AudioDevice device) {
+ int strategy, @NonNull AudioDeviceAttributes device) {
return setPreferredDeviceForStrategy(strategy,
AudioDeviceInfo.convertDeviceTypeToInternalDevice(device.getType()),
device.getAddress());
@@ -1288,7 +1288,7 @@
* and written to the array
*/
public static native int getPreferredDeviceForStrategy(int strategy,
- AudioDevice[] device);
+ AudioDeviceAttributes[] device);
// Items shared with audio service
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 27bf3fe..5f320cd 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -18,7 +18,7 @@
import android.bluetooth.BluetoothDevice;
import android.media.AudioAttributes;
-import android.media.AudioDevice;
+import android.media.AudioDeviceAttributes;
import android.media.AudioFocusInfo;
import android.media.AudioPlaybackConfiguration;
import android.media.AudioRecordingConfiguration;
@@ -275,13 +275,13 @@
boolean isCallScreeningModeSupported();
- int setPreferredDeviceForStrategy(in int strategy, in AudioDevice device);
+ int setPreferredDeviceForStrategy(in int strategy, in AudioDeviceAttributes device);
int removePreferredDeviceForStrategy(in int strategy);
- AudioDevice getPreferredDeviceForStrategy(in int strategy);
+ AudioDeviceAttributes getPreferredDeviceForStrategy(in int strategy);
- List<AudioDevice> getDevicesForAttributes(in AudioAttributes attributes);
+ List<AudioDeviceAttributes> getDevicesForAttributes(in AudioAttributes attributes);
int setAllowedCapturePolicy(in int capturePolicy);
diff --git a/media/java/android/media/IStrategyPreferredDeviceDispatcher.aidl b/media/java/android/media/IStrategyPreferredDeviceDispatcher.aidl
index 6db9e52..b1f99e6 100644
--- a/media/java/android/media/IStrategyPreferredDeviceDispatcher.aidl
+++ b/media/java/android/media/IStrategyPreferredDeviceDispatcher.aidl
@@ -16,7 +16,7 @@
package android.media;
-import android.media.AudioDevice;
+import android.media.AudioDeviceAttributes;
/**
* AIDL for AudioService to signal audio strategy-preferred device updates.
@@ -25,6 +25,6 @@
*/
oneway interface IStrategyPreferredDeviceDispatcher {
- void dispatchPrefDeviceChanged(int strategyId, in AudioDevice device);
+ void dispatchPrefDeviceChanged(int strategyId, in AudioDeviceAttributes device);
}
diff --git a/media/java/android/media/MediaCas.java b/media/java/android/media/MediaCas.java
index cefc9db..3a771bb 100644
--- a/media/java/android/media/MediaCas.java
+++ b/media/java/android/media/MediaCas.java
@@ -19,14 +19,20 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.Context;
import android.hardware.cas.V1_0.HidlCasPluginDescriptor;
import android.hardware.cas.V1_0.ICas;
import android.hardware.cas.V1_0.IMediaCasService;
import android.hardware.cas.V1_2.ICasListener;
+import android.hardware.cas.V1_2.Status;
import android.media.MediaCasException.*;
import android.media.tv.TvInputService.PriorityHintUseCaseType;
+import android.media.tv.tunerresourcemanager.CasSessionRequest;
+import android.media.tv.tunerresourcemanager.ResourceClientProfile;
+import android.media.tv.tunerresourcemanager.TunerResourceManager;
import android.os.Bundle;
import android.os.Handler;
+import android.os.HandlerExecutor;
import android.os.HandlerThread;
import android.os.IHwBinder;
import android.os.Looper;
@@ -39,6 +45,9 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
/**
* MediaCas can be used to obtain keys for descrambling protected media streams, in
@@ -110,6 +119,10 @@
private EventHandler mEventHandler;
private @PriorityHintUseCaseType int mPriorityHint;
private String mTvInputServiceSessionId;
+ private int mClientId;
+ private int mCasSystemId;
+ private TunerResourceManager mTunerResourceManager = null;
+ private final Map<Session, Integer> mSessionMap = new HashMap<>();
/**
* Scrambling modes used to open cas sessions.
@@ -329,6 +342,10 @@
createFromSessionId(sessionId), msg.arg1, msg.arg2,
bundle.getByteArray(DATA_KEY));
} else if (msg.what == MSG_CAS_STATUS_EVENT) {
+ if ((msg.arg1 == PLUGIN_STATUS_SESSION_NUMBER_CHANGED)
+ && (mTunerResourceManager != null)) {
+ mTunerResourceManager.updateCasInfo(mCasSystemId, msg.arg2);
+ }
mListener.onPluginStatusUpdate(MediaCas.this, msg.arg1, msg.arg2);
} else if (msg.what == MSG_CAS_RESOURCE_LOST) {
mListener.onResourceLost(MediaCas.this);
@@ -364,6 +381,19 @@
EventHandler.MSG_CAS_STATUS_EVENT, status, arg));
}
};
+
+ private final TunerResourceManager.ResourcesReclaimListener mResourceListener =
+ new TunerResourceManager.ResourcesReclaimListener() {
+ @Override
+ public void onReclaimResources() {
+ synchronized (mSessionMap) {
+ mSessionMap.forEach((casSession, sessionResourceId) -> casSession.close());
+ }
+ mEventHandler.sendMessage(mEventHandler.obtainMessage(
+ EventHandler.MSG_CAS_RESOURCE_LOST));
+ }
+ };
+
/**
* Describe a CAS plugin with its CA_system_ID and string name.
*
@@ -429,11 +459,21 @@
*/
public final class Session implements AutoCloseable {
final ArrayList<Byte> mSessionId;
+ boolean mIsClosed = false;
Session(@NonNull ArrayList<Byte> sessionId) {
mSessionId = new ArrayList<Byte>(sessionId);
}
+ private void validateSessionInternalStates() {
+ if (mICas == null) {
+ throw new IllegalStateException();
+ }
+ if (mIsClosed) {
+ MediaCasStateException.throwExceptionIfNeeded(Status.ERROR_CAS_SESSION_NOT_OPENED);
+ }
+ }
+
/**
* Query if an object equal current Session object.
*
@@ -459,7 +499,7 @@
*/
public void setPrivateData(@NonNull byte[] data)
throws MediaCasException {
- validateInternalStates();
+ validateSessionInternalStates();
try {
MediaCasException.throwExceptionIfNeeded(
@@ -483,7 +523,7 @@
*/
public void processEcm(@NonNull byte[] data, int offset, int length)
throws MediaCasException {
- validateInternalStates();
+ validateSessionInternalStates();
try {
MediaCasException.throwExceptionIfNeeded(
@@ -522,7 +562,7 @@
*/
public void sendSessionEvent(int event, int arg, @Nullable byte[] data)
throws MediaCasException {
- validateInternalStates();
+ validateSessionInternalStates();
if (mICasV11 == null) {
Log.d(TAG, "Send Session Event isn't supported by cas@1.0 interface");
@@ -546,7 +586,7 @@
*/
@NonNull
public byte[] getSessionId() {
- validateInternalStates();
+ validateSessionInternalStates();
return toBytes(mSessionId);
}
@@ -558,11 +598,12 @@
*/
@Override
public void close() {
- validateInternalStates();
-
+ validateSessionInternalStates();
try {
MediaCasStateException.throwExceptionIfNeeded(
mICas.closeSession(mSessionId));
+ mIsClosed = true;
+ removeSessionFromResourceMap(this);
} catch (RemoteException e) {
cleanupAndRethrowIllegalState();
}
@@ -664,6 +705,7 @@
/**
* Instantiate a CA system of the specified system id.
*
+ * @param context the context of the caller.
* @param casSystemId The system id of the CA system.
* @param tvInputServiceSessionId The Id of the session opened in TV Input Service (TIS)
* {@link android.media.tv.TvInputService#onCreateSession(String, String)}
@@ -672,11 +714,23 @@
* @throws UnsupportedCasException if the device does not support the
* specified CA system.
*/
- public MediaCas(int casSystemId, @Nullable String tvInputServiceSessionId,
- @PriorityHintUseCaseType int priorityHint) throws UnsupportedCasException {
+ public MediaCas(@NonNull Context context, int casSystemId,
+ @Nullable String tvInputServiceSessionId,
+ @PriorityHintUseCaseType int priorityHint) throws UnsupportedCasException {
this(casSystemId);
- mPriorityHint = priorityHint;
- mTvInputServiceSessionId = tvInputServiceSessionId;
+
+ Objects.requireNonNull(context, "context must not be null");
+ mCasSystemId = casSystemId;
+ mTunerResourceManager = (TunerResourceManager)
+ context.getSystemService(Context.TV_TUNER_RESOURCE_MGR_SERVICE);
+ if (mTunerResourceManager != null) {
+ int[] clientId = new int[1];
+ ResourceClientProfile profile =
+ new ResourceClientProfile(tvInputServiceSessionId, priorityHint);
+ mTunerResourceManager.registerClientProfile(
+ profile, new HandlerExecutor(mEventHandler), mResourceListener, clientId);
+ mClientId = clientId[0];
+ }
}
IHwBinder getBinder() {
@@ -813,6 +867,40 @@
}
}
+ private int getSessionResourceId() throws MediaCasException {
+ validateInternalStates();
+
+ int[] sessionResourceId = new int[1];
+ sessionResourceId[0] = -1;
+ if (mTunerResourceManager != null) {
+ CasSessionRequest casSessionRequest = new CasSessionRequest(mClientId, mCasSystemId);
+ if (!mTunerResourceManager.requestCasSession(casSessionRequest, sessionResourceId)) {
+ throw new MediaCasException.ResourceBusyException(
+ "insufficient resource to Open Session");
+ }
+ }
+ return sessionResourceId[0];
+ }
+
+ private void addSessionToResourceMap(Session session, int sessionResourceId) {
+
+ if (sessionResourceId != -1) {
+ synchronized (mSessionMap) {
+ mSessionMap.put(session, sessionResourceId);
+ }
+ }
+ }
+
+ private void removeSessionFromResourceMap(Session session) {
+
+ synchronized (mSessionMap) {
+ if (mSessionMap.get(session) != null) {
+ mTunerResourceManager.releaseCasSession(mSessionMap.get(session));
+ mSessionMap.remove(session);
+ }
+ }
+ }
+
/**
* Open a session to descramble one or more streams scrambled by the
* conditional access system.
@@ -824,12 +912,13 @@
* @throws MediaCasStateException for CAS-specific state exceptions.
*/
public Session openSession() throws MediaCasException {
- validateInternalStates();
+ int sessionResourceId = getSessionResourceId();
try {
OpenSessionCallback cb = new OpenSessionCallback();
mICas.openSession(cb);
MediaCasException.throwExceptionIfNeeded(cb.mStatus);
+ addSessionToResourceMap(cb.mSession, sessionResourceId);
return cb.mSession;
} catch (RemoteException e) {
cleanupAndRethrowIllegalState();
@@ -853,7 +942,7 @@
@Nullable
public Session openSession(@SessionUsage int sessionUsage, @ScramblingMode int scramblingMode)
throws MediaCasException {
- validateInternalStates();
+ int sessionResourceId = getSessionResourceId();
if (mICasV12 == null) {
Log.d(TAG, "Open Session with scrambling mode is only supported by cas@1.2+ interface");
@@ -864,6 +953,7 @@
OpenSession_1_2_Callback cb = new OpenSession_1_2_Callback();
mICasV12.openSession_1_2(sessionUsage, scramblingMode, cb);
MediaCasException.throwExceptionIfNeeded(cb.mStatus);
+ addSessionToResourceMap(cb.mSession, sessionResourceId);
return cb.mSession;
} catch (RemoteException e) {
cleanupAndRethrowIllegalState();
@@ -987,6 +1077,16 @@
mICas = null;
}
}
+
+ if (mTunerResourceManager != null) {
+ mTunerResourceManager.unregisterClientProfile(mClientId);
+ mTunerResourceManager = null;
+ }
+
+ if (mHandlerThread != null) {
+ mHandlerThread.quit();
+ mHandlerThread = null;
+ }
}
@Override
diff --git a/media/java/android/media/audiofx/AudioEffect.java b/media/java/android/media/audiofx/AudioEffect.java
index 6157ef4..2587350 100644
--- a/media/java/android/media/audiofx/AudioEffect.java
+++ b/media/java/android/media/audiofx/AudioEffect.java
@@ -25,7 +25,7 @@
import android.annotation.TestApi;
import android.app.ActivityThread;
import android.compat.annotation.UnsupportedAppUsage;
-import android.media.AudioDevice;
+import android.media.AudioDeviceAttributes;
import android.media.AudioDeviceInfo;
import android.media.AudioSystem;
import android.os.Build;
@@ -476,12 +476,12 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_DEFAULT_AUDIO_EFFECTS)
- public AudioEffect(@NonNull UUID uuid, @NonNull AudioDevice device) {
+ public AudioEffect(@NonNull UUID uuid, @NonNull AudioDeviceAttributes device) {
this(EFFECT_TYPE_NULL, Objects.requireNonNull(uuid), 0, -2, Objects.requireNonNull(device));
}
private AudioEffect(UUID type, UUID uuid, int priority,
- int audioSession, @Nullable AudioDevice device)
+ int audioSession, @Nullable AudioDeviceAttributes device)
throws IllegalArgumentException, UnsupportedOperationException,
RuntimeException {
int[] id = new int[1];
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index 62c7e51..b579144 100755
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -111,37 +111,32 @@
public @interface PriorityHintUseCaseType {}
/**
- * Use case of priority hint for {@link android.media.MediaCas#MediaCas(int, String , int)}:
- * Background.
- * TODO Link: Tuner#Tuner(Context, string, int).
+ * Use case of priority hint for {@link android.media.MediaCas#MediaCas(Context, int, String,
+ * int)}: Background. TODO Link: Tuner#Tuner(Context, string, int).
*/
public static final int PRIORITY_HINT_USE_CASE_TYPE_BACKGROUND = 100;
/**
- * Use case of priority hint for {@link android.media.MediaCas#MediaCas(int, String , int)}:
- * Scan.
- * TODO Link: Tuner#Tuner(Context, string, int).
+ * Use case of priority hint for {@link android.media.MediaCas#MediaCas(Context, int, String,
+ * int)}: Scan. TODO Link: Tuner#Tuner(Context, string, int).
*/
public static final int PRIORITY_HINT_USE_CASE_TYPE_SCAN = 200;
/**
- * Use case of priority hint for {@link android.media.MediaCas#MediaCas(int, String , int)}:
- * Playback.
- * TODO Link: Tuner#Tuner(Context, string, int).
+ * Use case of priority hint for {@link android.media.MediaCas#MediaCas(Context, int, String,
+ * int)}: Playback. TODO Link: Tuner#Tuner(Context, string, int).
*/
public static final int PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK = 300;
/**
- * Use case of priority hint for {@link android.media.MediaCas#MediaCas(int, String , int)}:
- * Live.
- * TODO Link: Tuner#Tuner(Context, string, int).
+ * Use case of priority hint for {@link android.media.MediaCas#MediaCas(Context, int, String,
+ * int)}: Live. TODO Link: Tuner#Tuner(Context, string, int).
*/
public static final int PRIORITY_HINT_USE_CASE_TYPE_LIVE = 400;
/**
- * Use case of priority hint for {@link android.media.MediaCas#MediaCas(int, String , int)}:
- * Record.
- * TODO Link: Tuner#Tuner(Context, string, int).
+ * Use case of priority hint for {@link android.media.MediaCas#MediaCas(Context, int, String,
+ * int)}: Record. TODO Link: Tuner#Tuner(Context, string, int).
*/
public static final int PRIORITY_HINT_USE_CASE_TYPE_RECORD = 500;
diff --git a/media/java/android/media/tv/tuner/DemuxCapabilities.java b/media/java/android/media/tv/tuner/DemuxCapabilities.java
index 364516c..0f5bf08 100644
--- a/media/java/android/media/tv/tuner/DemuxCapabilities.java
+++ b/media/java/android/media/tv/tuner/DemuxCapabilities.java
@@ -18,7 +18,7 @@
import android.annotation.BytesLong;
import android.annotation.IntDef;
-import android.annotation.Nullable;
+import android.annotation.NonNull;
import android.annotation.Size;
import android.annotation.SystemApi;
import android.media.tv.tuner.filter.Filter;
@@ -159,7 +159,7 @@
* {@link FilterConfiguration}.
* <p>The ith element represents the filter's capability as the source for the ith type.
*/
- @Nullable
+ @NonNull
@Size(5)
public int[] getLinkCapabilities() {
return mLinkCaps;
diff --git a/media/java/android/media/tv/tuner/Descrambler.java b/media/java/android/media/tv/tuner/Descrambler.java
index f46d3ce..40add56 100644
--- a/media/java/android/media/tv/tuner/Descrambler.java
+++ b/media/java/android/media/tv/tuner/Descrambler.java
@@ -17,12 +17,15 @@
package android.media.tv.tuner;
import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.media.tv.tuner.TunerConstants.Result;
import android.media.tv.tuner.filter.Filter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
/**
* This class is used to interact with descramblers.
@@ -75,6 +78,7 @@
* @param filter an optional filter instance to identify upper stream.
* @return result status of the operation.
*/
+ @Result
public int addPid(@PidType int pidType, int pid, @Nullable Filter filter) {
return nativeAddPid(pidType, pid, filter);
}
@@ -89,6 +93,7 @@
* @param filter an optional filter instance to identify upper stream.
* @return result status of the operation.
*/
+ @Result
public int removePid(@PidType int pidType, int pid, @Nullable Filter filter) {
return nativeRemovePid(pidType, pid, filter);
}
@@ -102,7 +107,9 @@
* @param keyToken the token to be used to link the key slot.
* @return result status of the operation.
*/
- public int setKeyToken(@Nullable byte[] keyToken) {
+ @Result
+ public int setKeyToken(@NonNull byte[] keyToken) {
+ Objects.requireNonNull(keyToken, "key token must not be null");
return nativeSetKeyToken(keyToken);
}
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index bd00201..012b8d6 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -38,6 +38,7 @@
import android.media.tv.tuner.frontend.FrontendInfo;
import android.media.tv.tuner.frontend.FrontendSettings;
import android.media.tv.tuner.frontend.FrontendStatus;
+import android.media.tv.tuner.frontend.FrontendStatus.FrontendStatusType;
import android.media.tv.tuner.frontend.OnTuneEventListener;
import android.media.tv.tuner.frontend.ScanCallback;
import android.os.Handler;
@@ -45,6 +46,7 @@
import android.os.Message;
import java.util.List;
+import java.util.Objects;
import java.util.concurrent.Executor;
/**
@@ -88,6 +90,10 @@
private ScanCallback mScanCallback;
@Nullable
private Executor mScanCallbackExecutor;
+ @Nullable
+ private OnResourceLostListener mOnResourceLostListener;
+ @Nullable
+ private Executor mOnResourceLostListenerExecutor;
/**
* Constructs a Tuner instance.
@@ -97,14 +103,37 @@
* @param useCase the use case of this Tuner instance.
*/
@RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
- public Tuner(@NonNull Context context, @NonNull String tvInputSessionId,
- @TvInputService.PriorityHintUseCaseType int useCase,
- @Nullable OnResourceLostListener listener) {
+ public Tuner(@NonNull Context context, @Nullable String tvInputSessionId,
+ @TvInputService.PriorityHintUseCaseType int useCase) {
nativeSetup();
mContext = context;
}
/**
+ * Sets the listener for resource lost.
+ *
+ * @param executor the executor on which the listener should be invoked.
+ * @param listener the listener that will be run.
+ */
+ @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
+ public void setResourceLostListener(@NonNull @CallbackExecutor Executor executor,
+ @NonNull OnResourceLostListener listener) {
+ Objects.requireNonNull(executor, "OnResourceLostListener must not be null");
+ Objects.requireNonNull(listener, "executor must not be null");
+ mOnResourceLostListener = listener;
+ mOnResourceLostListenerExecutor = executor;
+ }
+
+ /**
+ * Removes the listener for resource lost.
+ */
+ @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
+ public void clearResourceLostListener() {
+ mOnResourceLostListener = null;
+ mOnResourceLostListenerExecutor = null;
+ }
+
+ /**
* Shares the frontend resource with another Tuner instance
*
* @param tuner the Tuner instance to share frontend resource with.
@@ -387,7 +416,7 @@
*/
@RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@Result
- public int setLna(boolean enable) {
+ public int setLnaEnabled(boolean enable) {
TunerUtils.checkTunerPermission(mContext);
return nativeSetLna(enable);
}
@@ -398,10 +427,10 @@
* <p>This retrieve the statuses of the frontend for given status types.
*
* @param statusTypes an array of status types which the caller requests.
- * @return statuses which response the caller's requests.
+ * @return statuses which response the caller's requests. {@code null} if the operation failed.
*/
@Nullable
- public FrontendStatus getFrontendStatus(@NonNull int[] statusTypes) {
+ public FrontendStatus getFrontendStatus(@NonNull @FrontendStatusType int[] statusTypes) {
return nativeGetFrontendStatus(statusTypes);
}
@@ -482,6 +511,10 @@
/**
* Gets Demux capabilities.
+ *
+ * @param context the context of the caller.
+ * @return A {@link DemuxCapabilities} instance that represents the demux capabilities.
+ * {@code null} if the operation failed.
*/
@RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@Nullable
@@ -637,13 +670,15 @@
*/
@RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@Nullable
- public Lnb openLnb(@CallbackExecutor @Nullable Executor executor, @Nullable LnbCallback cb) {
+ public Lnb openLnb(@CallbackExecutor @NonNull Executor executor, @NonNull LnbCallback cb) {
+ Objects.requireNonNull(executor, "executor must not be null");
+ Objects.requireNonNull(cb, "LnbCallback must not be null");
TunerUtils.checkTunerPermission(mContext);
return openLnbByName(null, executor, cb);
}
/**
- * Opens an LNB (low-noise block downconverter) object.
+ * Opens an LNB (low-noise block downconverter) object specified by the give name.
*
* @param name the LNB name.
* @param executor the executor on which callback will be invoked. The default event handler
@@ -653,8 +688,10 @@
*/
@RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@Nullable
- public Lnb openLnbByName(@Nullable String name, @CallbackExecutor @Nullable Executor executor,
+ public Lnb openLnbByName(@NonNull String name, @CallbackExecutor @NonNull Executor executor,
@NonNull LnbCallback cb) {
+ Objects.requireNonNull(executor, "executor must not be null");
+ Objects.requireNonNull(cb, "LnbCallback must not be null");
TunerUtils.checkTunerPermission(mContext);
// TODO: use resource manager to get LNB ID.
return new Lnb(0);
@@ -718,8 +755,10 @@
@Nullable
public DvrRecorder openDvrRecorder(
@BytesLong long bufferSize,
- @CallbackExecutor @Nullable Executor executor,
- @Nullable OnRecordStatusChangedListener l) {
+ @CallbackExecutor @NonNull Executor executor,
+ @NonNull OnRecordStatusChangedListener l) {
+ Objects.requireNonNull(executor, "executor must not be null");
+ Objects.requireNonNull(l, "OnRecordStatusChangedListener must not be null");
TunerUtils.checkTunerPermission(mContext);
DvrRecorder dvr = nativeOpenDvrRecorder(bufferSize);
return dvr;
@@ -739,8 +778,10 @@
@Nullable
public DvrPlayback openDvrPlayback(
@BytesLong long bufferSize,
- @CallbackExecutor @Nullable Executor executor,
- @Nullable OnPlaybackStatusChangedListener l) {
+ @CallbackExecutor @NonNull Executor executor,
+ @NonNull OnPlaybackStatusChangedListener l) {
+ Objects.requireNonNull(executor, "executor must not be null");
+ Objects.requireNonNull(l, "OnPlaybackStatusChangedListener must not be null");
TunerUtils.checkTunerPermission(mContext);
DvrPlayback dvr = nativeOpenDvrPlayback(bufferSize);
return dvr;
diff --git a/media/java/android/media/tv/tuner/frontend/ScanCallback.java b/media/java/android/media/tv/tuner/frontend/ScanCallback.java
index 8105c74..63bc248 100644
--- a/media/java/android/media/tv/tuner/frontend/ScanCallback.java
+++ b/media/java/android/media/tv/tuner/frontend/ScanCallback.java
@@ -53,7 +53,7 @@
void onInputStreamIds(@NonNull int[] inputStreamIds);
/** Locked signal standard for DVBS. */
- void onDvbsStandard(@DvbsFrontendSettings.Standard int dvbsStandandard);
+ void onDvbsStandard(@DvbsFrontendSettings.Standard int dvbsStandard);
/** Locked signal standard. for DVBT */
void onDvbtStandard(@DvbtFrontendSettings.Standard int dvbtStandard);
diff --git a/media/tests/TunerTest/src/com/android/mediatunertest/TunerTest.java b/media/tests/TunerTest/src/com/android/mediatunertest/TunerTest.java
index cbfbf77..afdbce0 100644
--- a/media/tests/TunerTest/src/com/android/mediatunertest/TunerTest.java
+++ b/media/tests/TunerTest/src/com/android/mediatunertest/TunerTest.java
@@ -48,13 +48,13 @@
@Test
public void testTunerConstructor() throws Exception {
- Tuner tuner = new Tuner(mContext, "123", 1, null);
+ Tuner tuner = new Tuner(mContext, "123", 1);
assertNotNull(tuner);
}
@Test
public void testOpenDescrambler() throws Exception {
- Tuner tuner = new Tuner(mContext, "123", 1, null);
+ Tuner tuner = new Tuner(mContext, "123", 1);
Descrambler descrambler = tuner.openDescrambler();
assertNotNull(descrambler);
}
diff --git a/packages/SettingsProvider/res/values-af/strings.xml b/packages/SettingsProvider/res/values-af/strings.xml
index 8c2f8b3..24efbb6 100644
--- a/packages/SettingsProvider/res/values-af/strings.xml
+++ b/packages/SettingsProvider/res/values-af/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Instellingsberging"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Veranderings aan jou warmkolinstellings"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Jou warmkolband het verander."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Hierdie toestel steun nie jou voorkeur vir net 5 GHz nie. Hierdie toestel sal pleks daarvan die 5 GHz-band gebruik wanneer dit beskikbaar is."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Warmkolinstellings het verander"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Tik om besonderhede te sien"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-am/strings.xml b/packages/SettingsProvider/res/values-am/strings.xml
index 640301a..48fb705 100644
--- a/packages/SettingsProvider/res/values-am/strings.xml
+++ b/packages/SettingsProvider/res/values-am/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"የቅንብሮች ማከማቻ"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"በእርስዎ ሆትስፖት ቅንብሮች ላይ ለውጦች"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"የእርስዎ ሆትስፖት ባንድ ተለውጧል።"</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"ይህ መሣሪያ የእርስዎን ምርጫ ለ5GHz ብቻ አይደግፍም። በምትኩ፣ ይህ መሣሪያ ሲገኝ 5GHz ባንድ ይጠቀማል።"</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"የመገናኛ ነጥብ ቅንብሮች ተለውጠዋል"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"ዝርዝሮችን ለማየት መታ ያድርጉ"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-ar/strings.xml b/packages/SettingsProvider/res/values-ar/strings.xml
index 2675839..6371f2c 100644
--- a/packages/SettingsProvider/res/values-ar/strings.xml
+++ b/packages/SettingsProvider/res/values-ar/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"تخزين الإعدادات"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"التغييرات التي طرأت على إعدادات نقطة الاتصال"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"تمّ تغيير نطاق نقطة الاتصال الخاصة بك."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"لا يتوافق هذا الجهاز مع إعدادك المفضّل الخاص باستخدام النطاق 5 غيغاهرتز فقط. وسيستخدم الجهاز بدلاً من ذلك النطاق 5 غيغاهرتز عندما يكون متاحًا."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"تم تغيير إعدادات نقطة الاتصال."</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"انقر للاطّلاع على التفاصيل."</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-as/strings.xml b/packages/SettingsProvider/res/values-as/strings.xml
index b70146a..5235e3c 100644
--- a/packages/SettingsProvider/res/values-as/strings.xml
+++ b/packages/SettingsProvider/res/values-as/strings.xml
@@ -20,7 +20,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"ছেটিংছসমূহৰ সঞ্চয়াগাৰ"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"আপোনাৰ হটস্পট ছেটিংসমূহত হোৱা সালসলনিসমূহ"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"আপোনাৰ হটস্পটৰ বেণ্ড সলনি কৰা হৈছে।"</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"আপোনাৰ কেৱল ৫ গিগাহাৰ্টজৰ প্ৰতি অগ্ৰাধিকাৰ এই ডিভাচইচটোৱে সমৰ্থন নকৰে। ইয়াৰ পৰিৱৰ্তে, ডিভাচইচটোৱে যেতিয়া ৫ গিগাহাৰ্টজ বেণ্ড উপলব্ধ হ’ব তেতিয়া তাক ব্যৱহাৰ কৰিব।"</string>
+ <!-- no translation found for wifi_softap_config_change (5688373762357941645) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-az/strings.xml b/packages/SettingsProvider/res/values-az/strings.xml
index 8b4f75b..b0e8642 100644
--- a/packages/SettingsProvider/res/values-az/strings.xml
+++ b/packages/SettingsProvider/res/values-az/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Ayarlar Deposu"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Hotspot ayarlarınızda dəyişiklik"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Hotspot diapazonu dəyişib."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Bu cihaz yalnız 5GHz üçün tərcihinizi dəstəkləmir. Əvəzində, əlçatan olduqda bu cihaz 5GHz diapazonundan istifadə edəcək."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Hotspot ayarları dəyişib"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Detalları görmək üçün toxunun"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-b+sr+Latn/strings.xml b/packages/SettingsProvider/res/values-b+sr+Latn/strings.xml
index 9c3a00e..def4b68 100644
--- a/packages/SettingsProvider/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsProvider/res/values-b+sr+Latn/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Podešavanja skladišta"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Promene podešavanja za hotspot"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Opseg hotspota je promenjen."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Ovaj uređaj ne podržava podešavanje samo za 5 GHz. Uređaj će koristiti opseg od 5 GHz kada bude dostupan."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Podešavanja hotspota su promenjena"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Dodirnite da biste videli detalje"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-be/strings.xml b/packages/SettingsProvider/res/values-be/strings.xml
index 0e098e7..709178e 100644
--- a/packages/SettingsProvider/res/values-be/strings.xml
+++ b/packages/SettingsProvider/res/values-be/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Сховішча налад"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Змяненні ў наладах хот-спота"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Частата хот-спота змянілася."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Прылада не можа працаваць толькі на частаце 5 ГГц. Гэта частата будзе выкарыстоўвацца, калі гэта магчыма."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Налады хот-спота змяніліся"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Дакраніцеся, каб убачыць падрабязныя звесткі"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-bg/strings.xml b/packages/SettingsProvider/res/values-bg/strings.xml
index 30526f2..b2eae73 100644
--- a/packages/SettingsProvider/res/values-bg/strings.xml
+++ b/packages/SettingsProvider/res/values-bg/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Настройки за хранилище"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Промени в настройките ви за точка за достъп"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Честотната лента на точката ви за достъп е променена."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Това устройство не поддържа предпочитанието ви за използване само на честотната лента от 5 ГХц. Вместо това то ще я ползва, когато е възможно."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Настройките за точката за достъп са променени"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Докоснете, за да видите подробности"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-bn/strings.xml b/packages/SettingsProvider/res/values-bn/strings.xml
index 8fc6bbb..c785cd8 100644
--- a/packages/SettingsProvider/res/values-bn/strings.xml
+++ b/packages/SettingsProvider/res/values-bn/strings.xml
@@ -20,7 +20,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"সেটিংস স্টোরেজ"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"আপনার হটস্পট সেটিংসে করা পরিবর্তনগুলি"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"আপনার হটস্পট ব্যান্ড পরিবর্তন করা হয়েছে।"</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"এই ডিভাইসটি শুধুমাত্র 5GHz এর জন্য আপনার পছন্দ সমর্থন করে না। পরিবর্তে, এই ডিভাইসটি 5GHz ব্যান্ড ব্যবহার করবে।"</string>
+ <!-- no translation found for wifi_softap_config_change (5688373762357941645) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-bs/strings.xml b/packages/SettingsProvider/res/values-bs/strings.xml
index ddacb32..506fea2 100644
--- a/packages/SettingsProvider/res/values-bs/strings.xml
+++ b/packages/SettingsProvider/res/values-bs/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Postavke za pohranu podataka"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Promjene postavki pristupne tačke"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Opseg pristupne tačke je promijenjen."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Ovaj uređaj ne podržava vašu postavku za mreže od isključivo 5 GHz. Uređaj će koristiti opseg of 5 GHz kada bude dostupan."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Postavke pristupne tačke su promijenjene"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Dodirnite da vidite detalje"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-ca/strings.xml b/packages/SettingsProvider/res/values-ca/strings.xml
index 0c2ad73..58d3572e 100644
--- a/packages/SettingsProvider/res/values-ca/strings.xml
+++ b/packages/SettingsProvider/res/values-ca/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Configuració de l\'emmagatzematge"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Canvis en la configuració del punt d\'accés Wi‑Fi"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Ha canviat la teva banda del punt d\'accés Wi‑Fi."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Aquest dispositiu no admet utilitzar exclusivament una banda de 5 GHz. El dispositiu utilitzarà una banda de 5 GHz quan estigui disponible."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"La configuració del punt d\'accés Wi‑Fi ha canviat"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Toca per veure\'n els detalls"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-cs/strings.xml b/packages/SettingsProvider/res/values-cs/strings.xml
index ab474b1..449c632 100644
--- a/packages/SettingsProvider/res/values-cs/strings.xml
+++ b/packages/SettingsProvider/res/values-cs/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Paměť pro nastavení"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Změny nastavení hotspotu"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Pásmo hotspotu se změnilo."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Toto zařízení nepodporuje vaše nastavení jen 5GHz pásma. Zařízení použije pásmo 5 GHz, jen když bude dostupné."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Nastavení hotspotu se změnilo"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Klepnutím zobrazíte podrobnosti"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-da/strings.xml b/packages/SettingsProvider/res/values-da/strings.xml
index 719614c..278d978 100644
--- a/packages/SettingsProvider/res/values-da/strings.xml
+++ b/packages/SettingsProvider/res/values-da/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Lagring af indstillinger"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Ændringer af dine indstillinger for hotspot"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Dit hotspotbånd er ændret."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Denne enhed understøtter ikke din præference om kun 5 GHz. Denne enhed vil i stedet bruge 5 GHz-båndet, når det er muligt."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Indstillingerne for hotspots har ændret sig"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Tryk for at se flere oplysninger"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-de/strings.xml b/packages/SettingsProvider/res/values-de/strings.xml
index 6e253e0..a469936 100644
--- a/packages/SettingsProvider/res/values-de/strings.xml
+++ b/packages/SettingsProvider/res/values-de/strings.xml
@@ -20,7 +20,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Einstellungsspeicher"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Änderungen an deinen Hotspot-Einstellungen"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Dein Hotspot-Band hat sich geändert."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Dieses Gerät unterstützt die ausschließliche Nutzung von 5 GHz nicht. Es greift aber immer auf das 5-GHz-Band zurück, wenn dieses verfügbar ist."</string>
+ <!-- no translation found for wifi_softap_config_change (5688373762357941645) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-el/strings.xml b/packages/SettingsProvider/res/values-el/strings.xml
index c47fea2..1bfbf27 100644
--- a/packages/SettingsProvider/res/values-el/strings.xml
+++ b/packages/SettingsProvider/res/values-el/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Αποθηκευτικός χώρος ρυθμίσεων"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Αλλαγές στις ρυθμίσεις σημείου πρόσβασης Wi-Fi"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Το εύρος σημείου πρόσβασης Wi-Fi άλλαξε."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Αυτή η συσκευή δεν υποστηρίζει την προτίμησή σας για αποκλειστική χρήση του εύρους 5 GHz. Αντ\' αυτού, αυτή η συσκευή θα χρησιμοποιεί το εύρος 5 GHz όταν είναι διαθέσιμο."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Οι ρυθμίσεις σημείου πρόσβασης Wi-Fi έχουν αλλάξει"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Πατήστε για προβολή λεπτομερειών."</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-en-rAU/strings.xml b/packages/SettingsProvider/res/values-en-rAU/strings.xml
index fac51d83..4e90cad 100644
--- a/packages/SettingsProvider/res/values-en-rAU/strings.xml
+++ b/packages/SettingsProvider/res/values-en-rAU/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Settings Storage"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Changes to your hotspot settings"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Your hotspot band has changed."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"This device doesn’t support your preference for 5 GHz only. Instead, this device will use the 5 GHz band when available."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Hotspot settings have changed"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Tap to see details"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-en-rCA/strings.xml b/packages/SettingsProvider/res/values-en-rCA/strings.xml
index fac51d83..4e90cad 100644
--- a/packages/SettingsProvider/res/values-en-rCA/strings.xml
+++ b/packages/SettingsProvider/res/values-en-rCA/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Settings Storage"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Changes to your hotspot settings"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Your hotspot band has changed."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"This device doesn’t support your preference for 5 GHz only. Instead, this device will use the 5 GHz band when available."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Hotspot settings have changed"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Tap to see details"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-en-rGB/strings.xml b/packages/SettingsProvider/res/values-en-rGB/strings.xml
index fac51d83..4e90cad 100644
--- a/packages/SettingsProvider/res/values-en-rGB/strings.xml
+++ b/packages/SettingsProvider/res/values-en-rGB/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Settings Storage"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Changes to your hotspot settings"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Your hotspot band has changed."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"This device doesn’t support your preference for 5 GHz only. Instead, this device will use the 5 GHz band when available."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Hotspot settings have changed"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Tap to see details"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-en-rIN/strings.xml b/packages/SettingsProvider/res/values-en-rIN/strings.xml
index fac51d83..4e90cad 100644
--- a/packages/SettingsProvider/res/values-en-rIN/strings.xml
+++ b/packages/SettingsProvider/res/values-en-rIN/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Settings Storage"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Changes to your hotspot settings"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Your hotspot band has changed."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"This device doesn’t support your preference for 5 GHz only. Instead, this device will use the 5 GHz band when available."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Hotspot settings have changed"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Tap to see details"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-en-rXC/strings.xml b/packages/SettingsProvider/res/values-en-rXC/strings.xml
index fbc348b..4ea5c57 100644
--- a/packages/SettingsProvider/res/values-en-rXC/strings.xml
+++ b/packages/SettingsProvider/res/values-en-rXC/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Settings Storage"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Changes to your hotspot settings"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Your hotspot band has changed."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"This device doesn’t support your preference for 5GHz only. Instead, this device will use the 5GHz band when available."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Hotspot settings have changed"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Tap to see details"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-es-rUS/strings.xml b/packages/SettingsProvider/res/values-es-rUS/strings.xml
index af90257..4345b7a 100644
--- a/packages/SettingsProvider/res/values-es-rUS/strings.xml
+++ b/packages/SettingsProvider/res/values-es-rUS/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Almacenamiento de configuración"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Cambios en la configuración de tu hotspot"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Cambió la banda de tu hotspot."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Si bien este dispositivo no admite la opción para conectarse exclusivamente a bandas de 5 GHz, las usará cuando estén disponibles."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Se modificó la configuración de hotspot"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Presiona para obtener más información"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-es/strings.xml b/packages/SettingsProvider/res/values-es/strings.xml
index ff4ee38..3f1fa61 100644
--- a/packages/SettingsProvider/res/values-es/strings.xml
+++ b/packages/SettingsProvider/res/values-es/strings.xml
@@ -20,7 +20,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Almacenamiento de configuración"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Cambios en los ajustes del punto de acceso"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"La banda de tu punto de acceso ha cambiado."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Este dispositivo no admite la opción de conectarse únicamente a bandas de 5 GHz, pero las usará cuando estén disponibles."</string>
+ <!-- no translation found for wifi_softap_config_change (5688373762357941645) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-et/strings.xml b/packages/SettingsProvider/res/values-et/strings.xml
index a0ec593..856ccf1 100644
--- a/packages/SettingsProvider/res/values-et/strings.xml
+++ b/packages/SettingsProvider/res/values-et/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Seadete talletusruum"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Muudatused teie kuumkoha seadetes"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Teie kuumkoha sagedusriba on muutunud."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"See seade ei toeta teie eelistatud ainult 5 GHz riba. Seade kasutab 5 GHz riba ainult siis, kui see on saadaval."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Kuumkoha seaded on muutunud"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Puudutage üksikasjade vaatamiseks"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-eu/strings.xml b/packages/SettingsProvider/res/values-eu/strings.xml
index 220b486..7ca91d8 100644
--- a/packages/SettingsProvider/res/values-eu/strings.xml
+++ b/packages/SettingsProvider/res/values-eu/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Ezarpenen biltegia"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Aldaketak egin dira sare publikoaren ezarpenetan"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Aldatu da sare publikoaren banda."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Gailuak ez du onartzen 5 GHz-ko banda soilik erabiltzeko hobespena. Horren ordez, erabilgarri dagoen bakoitzean erabiliko da 5 GHz-ko banda."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Sare publikoaren ezarpenak aldatu dira"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Sakatu hau xehetasunak ikusteko"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-fa/strings.xml b/packages/SettingsProvider/res/values-fa/strings.xml
index 6819d2f..cc0b557 100644
--- a/packages/SettingsProvider/res/values-fa/strings.xml
+++ b/packages/SettingsProvider/res/values-fa/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"تنظیم محل ذخیره"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"تغییرات در تنظیمات نقطه اتصال"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"نوار نقطه اتصال شما تغییر کرد."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"این دستگاه از اولویت فقط ۵ گیگاهرتز شما پشتیبانی نمیکند. هرزمان نوار ۵ گیگاهرتزی دردسترس باشد، این دستگاه از آن استفاده خواهد کرد."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"تنظیمات نقطه اتصال تغییر کرده است"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"برای مشاهده جزئیات ضربه بزنید"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-fi/strings.xml b/packages/SettingsProvider/res/values-fi/strings.xml
index 9ad01eb..829bb3b 100644
--- a/packages/SettingsProvider/res/values-fi/strings.xml
+++ b/packages/SettingsProvider/res/values-fi/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Asetuksien tallennus"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Hotspot-asetustesi muutokset"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Hotspot-taajuutesi on muuttunut."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Tämä laite ei tue asetustasi (vain 5 GHz). Sen sijaan laite käyttää 5 GHz:n taajuutta sen ollessa käytettävissä."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Hotspot-asetuksia on muutettu"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Katso lisätiedot napauttamalla"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-fr-rCA/strings.xml b/packages/SettingsProvider/res/values-fr-rCA/strings.xml
index 62951bd..d640845 100644
--- a/packages/SettingsProvider/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsProvider/res/values-fr-rCA/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Stockage des paramètres"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Modifications apportées à vos paramètres de point d\'accès"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"La bande de votre point d\'accès a changé."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Cet appareil ne prend pas en charge votre préférence pour la bande de 5 GHz seulement. Au lieu de cela, cet appareil utilisera la bande de 5 GHz lorsqu\'elle sera disponible."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Les paramètres de point d\'accès ont changé"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Touchez pour afficher les renseignements"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-fr/strings.xml b/packages/SettingsProvider/res/values-fr/strings.xml
index 56bc65b..ba6ec0b 100644
--- a/packages/SettingsProvider/res/values-fr/strings.xml
+++ b/packages/SettingsProvider/res/values-fr/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Stockage des paramètres"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Modifications apportées à vos paramètres de point d\'accès"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"La bande utilisée par votre point d\'accès a été modifiée."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Cet appareil n\'est pas conçu pour utiliser exclusivement la bande 5 GHz, mais il l\'utilisera chaque fois que disponible."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Les paramètres de point d\'accès ont changé"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Appuyer ici pour plus d\'infos"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-gl/strings.xml b/packages/SettingsProvider/res/values-gl/strings.xml
index 771fade..1be162e 100644
--- a/packages/SettingsProvider/res/values-gl/strings.xml
+++ b/packages/SettingsProvider/res/values-gl/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Almacenamento da configuración"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Cambios na configuración da zona wifi"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Modificouse a banda da zona wifi."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Este dispositivo non admite a opción de conectarse só a bandas de 5 GHz, pero usaraas se están dispoñibles."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"A configuración da zona wifi cambiou"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Toca a notificación para ver os detalles"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-gu/strings.xml b/packages/SettingsProvider/res/values-gu/strings.xml
index a561924..074675f 100644
--- a/packages/SettingsProvider/res/values-gu/strings.xml
+++ b/packages/SettingsProvider/res/values-gu/strings.xml
@@ -20,7 +20,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"સેટિંગ્સ સંગ્રહ"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"તમારા હૉટસ્પૉટ સેટિંગને બદલે છે"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"તમારું હૉટસ્પૉટ બૅન્ડ બદલાઈ ગયું છે."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"આ ડિવાઇસ તમારી ફક્ત 5GHz માટેની પસંદગીને સપોર્ટ કરતું નથી. તેના બદલે, જ્યારે 5GHz બૅન્ડ ઉપલબ્ધ હશે ત્યારે આ ડિવાઇસ તેનો ઉપયોગ કરશે."</string>
+ <!-- no translation found for wifi_softap_config_change (5688373762357941645) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-hi/strings.xml b/packages/SettingsProvider/res/values-hi/strings.xml
index 199a546..9441a59 100644
--- a/packages/SettingsProvider/res/values-hi/strings.xml
+++ b/packages/SettingsProvider/res/values-hi/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"सेटिंग मेमोरी"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"आपकी हॉटस्पॉट की सेटिंग में किए गए बदलाव"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"आपका हॉटस्पॉट का बैंड बदल दिया गया है."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"इस डिवाइस पर आप \'सिर्फ़ 5 गीगाहर्ट्ज़\' वाला विकल्प नहीं चुन सकते. इसके बजाय, 5 गीगाहर्ट्ज़ बैंड उपलब्ध होने पर यह डिवाइस उसका इस्तेमाल करेगा."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"हॉटस्पॉट की सेटिंग बदल गई हैं"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"जानकारी देखने के लिए टैप करें"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-hr/strings.xml b/packages/SettingsProvider/res/values-hr/strings.xml
index 9129a04..206f50f 100644
--- a/packages/SettingsProvider/res/values-hr/strings.xml
+++ b/packages/SettingsProvider/res/values-hr/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Postavke pohrane"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Promjene postavki vaše žarišne točke"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Promijenila se frekvencija vaše žarišne točke."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Ovaj uređaj ne podržava vašu postavku za upotrebu samo 5 GHz. Upotrebljavat će frekvenciju od 5 GHz kada je dostupna."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Promijenile su se postavke žarišne točke"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Dodirnite da biste vidjeli pojedinosti"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-hu/strings.xml b/packages/SettingsProvider/res/values-hu/strings.xml
index a1ed494..a7ca0d2 100644
--- a/packages/SettingsProvider/res/values-hu/strings.xml
+++ b/packages/SettingsProvider/res/values-hu/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Beállítástároló"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"A hotspot beállításainak módosítása"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"A hotspot sávja megváltozott."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Ez az eszköz nem támogatja a csak 5 GHz-es sávra vonatkozó beállítást. Az eszköz akkor használ 5 GHz-es sávot, ha a sáv rendelkezésre áll."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"A hotspot beállításai módosultak"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Koppintson a részletek megtekintéséhez"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-hy/strings.xml b/packages/SettingsProvider/res/values-hy/strings.xml
index 6d716f8..4fdb880 100644
--- a/packages/SettingsProvider/res/values-hy/strings.xml
+++ b/packages/SettingsProvider/res/values-hy/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Կարգավորումների պահուստ"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Փոփոխություններ թեժ կետի կարգավորումներում"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Ձեր թեժ կետի հաճախականությունը փոխվել է։"</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Սարքը չի կարող աշխատել միայն 5 ԳՀց հաճախականությամբ։ Այդ հաճախականությունը կօգտագործվի հնարավորության դեպքում։"</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Թեժ կետի կարգավորումները փոխվել են"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Հպեք՝ ավելին իմանալու համար"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-in/strings.xml b/packages/SettingsProvider/res/values-in/strings.xml
index 8b1b1f4..911892b 100644
--- a/packages/SettingsProvider/res/values-in/strings.xml
+++ b/packages/SettingsProvider/res/values-in/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Setelan Penyimpanan"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Perubahan pada setelan hotspot Anda"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Band hotspot Anda telah berubah."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Perangkat ini tidak mendukung preferensi Anda, yaitu hanya 5GHz. Sebagai gantinya, perangkat ini akan menggunakan band 5GHz jika tersedia."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Setelan hotspot telah berubah"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Ketuk untuk melihat detail"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-is/strings.xml b/packages/SettingsProvider/res/values-is/strings.xml
index 150c084..c72442e 100644
--- a/packages/SettingsProvider/res/values-is/strings.xml
+++ b/packages/SettingsProvider/res/values-is/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Stillingageymsla"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Breytingar á stillingum heits reits"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Tíðnisvið heita reitsins hefur breyst."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Þetta tæki styður ekki val þitt fyrir aðeins 5 GHz. Í staðinn mun þetta tæki nota 5 GHz tíðnisvið þegar það er í boði."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Stillingum heits reits hefur verið breytt"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Ýttu til að sjá upplýsingar"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-it/strings.xml b/packages/SettingsProvider/res/values-it/strings.xml
index 6715c3c..0e11d06 100644
--- a/packages/SettingsProvider/res/values-it/strings.xml
+++ b/packages/SettingsProvider/res/values-it/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Memoria impostazioni"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Modifiche alle tue impostazioni dell\'hotspot"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"La banda dell\'hotspot è cambiata."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Questo dispositivo non supporta la tua preferenza esclusiva per 5 GHz. Utilizzerà la banda a 5 GHz solo quando è disponibile."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Le impostazioni di hotspot sono state modificate"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Tocca per vedere i dettagli"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-iw/strings.xml b/packages/SettingsProvider/res/values-iw/strings.xml
index dd44329..8d8594d 100644
--- a/packages/SettingsProvider/res/values-iw/strings.xml
+++ b/packages/SettingsProvider/res/values-iw/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"אחסון הגדרות"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"שינויים להגדרות של הנקודה לשיתוף אינטרנט"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"התדר של הנקודה לשיתוף אינטרנט השתנה."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"מכשיר זה לא תומך בהעדפות שלך ל-5GHz בלבד. במקום זאת, מכשיר זה ישתמש בתדר 5GHz כשיהיה זמין."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"ההגדרות של הנקודה לשיתוף אינטרנט השתנו"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"יש להקיש להצגת פרטים"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-ja/strings.xml b/packages/SettingsProvider/res/values-ja/strings.xml
index 7bbcd46..5b91b2d 100644
--- a/packages/SettingsProvider/res/values-ja/strings.xml
+++ b/packages/SettingsProvider/res/values-ja/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"ストレージの設定"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"アクセス ポイントの設定の変更"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"アクセス ポイントの帯域幅が変更されました。"</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"このデバイスは 5 GHz のみという設定に対応していません。ただし、5 GHz 周波数帯が利用できるときには利用します。"</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"アクセス ポイントの設定が変更されました"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"タップして詳細を確認してください"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-ka/strings.xml b/packages/SettingsProvider/res/values-ka/strings.xml
index 86db4f3..70845ac 100644
--- a/packages/SettingsProvider/res/values-ka/strings.xml
+++ b/packages/SettingsProvider/res/values-ka/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"პარამეტრების საცავი"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"თქვენი უსადენო ქსელის პარამეტრების ცვლილება"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"თქვენი უსადენო ქსელის დიაპაზონი შეიცვალა."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"ამ მოწყობილობას არ შეუძლია მხოლოდ 5 გჰც სიხშირეზე მუშაობა. აღნიშნული სიხშირის გამოყენება მოხდება მაშინ, როცა ეს შესაძლებელია."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"უსადენო ქსელის პარამეტრები შეიცვალა"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"შეეხეთ დეტალების სანახავად"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-kk/strings.xml b/packages/SettingsProvider/res/values-kk/strings.xml
index a093d08..2823e4e 100644
--- a/packages/SettingsProvider/res/values-kk/strings.xml
+++ b/packages/SettingsProvider/res/values-kk/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Параметрлер жады"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Хотспот параметрлеріне өзгерістер енгізілді"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Хотспот жолағы өзгертілді."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Бұл құрылғы тек 5 ГГц жиілікте жұмыс істей алмайды. Бұл жиілік мүмкін болған жағдайда ғана қолданылады."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Хотспот параметрлері өзгертілді"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Мәліметтерді көру үшін түртіңіз."</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-km/strings.xml b/packages/SettingsProvider/res/values-km/strings.xml
index f0a2712..cdae410 100644
--- a/packages/SettingsProvider/res/values-km/strings.xml
+++ b/packages/SettingsProvider/res/values-km/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"កំណត់ការផ្ទុក"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"ប្ដូរទៅការកំណត់ហតស្ប៉តរបស់អ្នក"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"កម្រិតបញ្ជូនហតស្ប៉តរបស់អ្នកបានផ្លាស់ប្ដូរ។"</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"ឧបករណ៍នេះមិនស្គាល់ចំណូលចិត្តរបស់អ្នកសម្រាប់តែ 5GHz ប៉ុណ្ណោះ។ ផ្ទុយមកវិញ ឧបករណ៍នេះនឹងប្រើកម្រិតបញ្ជូន 5GHz នៅពេលដែលអាចប្រើបាន។"</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"បានប្ដូរការកំណត់ហតស្ប៉ត"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"ចុចដើម្បីមើលព័ត៌មានលម្អិត"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-kn/strings.xml b/packages/SettingsProvider/res/values-kn/strings.xml
index f2c1d5e..0b0000d 100644
--- a/packages/SettingsProvider/res/values-kn/strings.xml
+++ b/packages/SettingsProvider/res/values-kn/strings.xml
@@ -20,7 +20,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"ಸೆಟ್ಟಿಂಗ್ಗಳ ಸಂಗ್ರಹಣೆ"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"ನಿಮ್ಮ ಹಾಟ್ಸ್ಪಾಟ್ ಸೆಟ್ಟಿಂಗ್ಗಳಲ್ಲಿನ ಬದಲಾವಣೆಗಳು"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"ನಿಮ್ಮ ಹಾಟ್ಸ್ಪಾಟ್ ಬ್ಯಾಂಡ್ ಬದಲಾಗಿದೆ."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"ಈ ಸಾಧನವು 5GHz ಗೆ ಮಾತ್ರ ನಿಮ್ಮ ಆದ್ಯತೆಯನ್ನು ಬೆಂಬಲಿಸುವುದಿಲ್ಲ. ಬದಲಿಗೆ, ಈ ಸಾಧನವು 5GHz ಬ್ಯಾಂಡ್ ಅನ್ನು ಲಭ್ಯವಿರುವಾಗ ಬಳಸುತ್ತದೆ."</string>
+ <!-- no translation found for wifi_softap_config_change (5688373762357941645) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-ko/strings.xml b/packages/SettingsProvider/res/values-ko/strings.xml
index 841832d..d76b766 100644
--- a/packages/SettingsProvider/res/values-ko/strings.xml
+++ b/packages/SettingsProvider/res/values-ko/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"설정 저장소"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"핫스팟 설정 변경"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"핫스팟 대역이 변경되었습니다."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"이 기기에서는 5GHz 전용 환경설정이 지원되지 않습니다. 대신 가능할 때만 기기에서 5GHz 대역이 사용됩니다."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"핫스팟 설정 변경됨"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"세부정보를 보려면 탭하세요."</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-ky/strings.xml b/packages/SettingsProvider/res/values-ky/strings.xml
index 014c66c..e5b82c6 100644
--- a/packages/SettingsProvider/res/values-ky/strings.xml
+++ b/packages/SettingsProvider/res/values-ky/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Жөндөөлөрдү сактоо"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Байланыш түйүнүңүздүн жөндөөлөрү өзгөрүлдү"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Байланыш түйүнүңүздүн жыштыгы өзгөрдү."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Бул түзмөк 5ГГцти гана колдонуу жөндөөсүн колдоого албайт. Анын ордуна, бул түзмөк 5ГГц жыштыгын ал жеткиликтүү болгондо колдонот."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Хотспот жөндөөлөрү өзгөрдү"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Чоо-жайын билүү үчүн басыңыз"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-lo/strings.xml b/packages/SettingsProvider/res/values-lo/strings.xml
index 9d60ba1..c2b5df7 100644
--- a/packages/SettingsProvider/res/values-lo/strings.xml
+++ b/packages/SettingsProvider/res/values-lo/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"ບ່ອນເກັບຂໍ້ມູນການຕັ້ງຄ່າ"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"ການປ່ຽນແປງການຕັ້ງຄ່າຮັອດສະປອດຂອງທ່ານ"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"ຄື້ນຄວາມຖີ່ຮັອດສະປອດຂອງທ່ານປ່ຽນແປງແລ້ວ."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"ອຸປະກອນນີ້ບໍ່ຮອງຮັບການຕັ້ງຄ່າຂອງທ່ານສຳລັບ 5GHz ເທົ່ານັ້ນ. ແຕ່ວ່າອຸປະກອນນີ້ຈະໃຊ້ຄື້ນຄວາມຖີ່ 5GHz ເມື່ອສາມາດໃຊ້ໄດ້."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"ບັນທຶກການຕັ້ງຄ່າຮັອດສະປອດແລ້ວ"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"ແຕະເພື່ອເບິ່ງລາຍລະອຽດ"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-lt/strings.xml b/packages/SettingsProvider/res/values-lt/strings.xml
index 775d3b9..64f429b 100644
--- a/packages/SettingsProvider/res/values-lt/strings.xml
+++ b/packages/SettingsProvider/res/values-lt/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Nustatymų saugykla"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Viešosios interneto prieigos taško nustatymų pakeitimai"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Viešosios prieigos taško dažnio juosta pasikeitė."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Šiame įrenginyje nepalaikoma tik 5 GHz nuostata. Vietoj to šiame įrenginyje bus naudojama 5 GHz dažnio juosta, kai bus pasiekiama."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Buvo pakeisti viešosios interneto prieigos taško nustatymai"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Palieskite ir peržiūrėkite išsamią informaciją"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-lv/strings.xml b/packages/SettingsProvider/res/values-lv/strings.xml
index f7f3117..e5af8f7 100644
--- a/packages/SettingsProvider/res/values-lv/strings.xml
+++ b/packages/SettingsProvider/res/values-lv/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Iestatījumu krātuve"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Izmaiņas tīklāja iestatījumos"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Ir mainīts tīklāja joslas platums."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Šajā ierīcē netiek atbalstīta jūsu preference par tikai 5 GHz joslu. 5 GHz josla ierīcē tiks izmantota, kad tā būs pieejama."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Ir mainīti tīklāja iestatījumi"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Pieskarieties, lai skatītu detalizētāku informāciju."</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-mk/strings.xml b/packages/SettingsProvider/res/values-mk/strings.xml
index a245e5f..13ff8a2 100644
--- a/packages/SettingsProvider/res/values-mk/strings.xml
+++ b/packages/SettingsProvider/res/values-mk/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Поставки за меморија"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Промени на поставките за точка на пристап"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Опсегот за точка на пристап е променет."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Уредов не ги поддржува вашите поставки за само 5 GHz. Наместо тоа, ќе го користи опсегот од 5 GHz кога е достапен."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Поставките за точка на пристап се променија"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Допрете за да видите детали"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-ml/strings.xml b/packages/SettingsProvider/res/values-ml/strings.xml
index b63f20e..54a05fb 100644
--- a/packages/SettingsProvider/res/values-ml/strings.xml
+++ b/packages/SettingsProvider/res/values-ml/strings.xml
@@ -20,7 +20,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"സംഭരണ ക്രമീകരണം"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"നിങ്ങളുടെ ഹോട്ട്സ്പോട്ട് ക്രമീകരണത്തിൽ വരുത്തിയ മാറ്റങ്ങൾ"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"നിങ്ങളുടെ ഹോട്ട്സ്പോട്ട് ബാൻഡ് മാറിയിരിക്കുന്നു."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"നിങ്ങളുടെ മുൻഗണനയനുസരിച്ചുള്ള, 5GHz മാത്രം എന്നത് ഈ ഉപകരണം പിന്തുണയ്ക്കുന്നില്ല. പകരം, 5GHz ബാൻഡ് ലഭ്യമാകുമ്പോൾ അത് ഉപയോഗിക്കും."</string>
+ <!-- no translation found for wifi_softap_config_change (5688373762357941645) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-mn/strings.xml b/packages/SettingsProvider/res/values-mn/strings.xml
index c839177..a9c2e8c 100644
--- a/packages/SettingsProvider/res/values-mn/strings.xml
+++ b/packages/SettingsProvider/res/values-mn/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Тохиргооны Сан"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Таны сүлжээний цэгийн тохиргооны өөрчлөлт"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Таны сүлжээний цэгийн хязгаарыг өөрчилсөн."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Энэ төхөөрөмж нь зөвхөн 5Гц гэсэн таны сонголтыг дэмждэггүй. Оронд нь энэ төхөөрөмж 5Гц-н хязгаарыг боломжтой үед нь ашиглах болно."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Сүлжээний цэгийн тохиргоог өөрчиллөө"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Дэлгэрэнгүй мэдээлэл харахын тулд товшино уу"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-mr/strings.xml b/packages/SettingsProvider/res/values-mr/strings.xml
index 0c7041e..0e80f70 100644
--- a/packages/SettingsProvider/res/values-mr/strings.xml
+++ b/packages/SettingsProvider/res/values-mr/strings.xml
@@ -20,7 +20,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"सेटिंग्ज संचयन"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"तुमच्या हॉटस्पॉट सेटिंग्जमधील बदल"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"तुमचा हॉटस्पॉट बँड बदलला गेला आहे."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"हे डिव्हाइस फक्त ५GHz च्या तुमच्या प्राधान्याला सपोर्ट करत नाही. त्याऐवजी, उपलब्ध असेल तेव्हा हे डिव्हाइस ५GHz बँड वापरेल."</string>
+ <!-- no translation found for wifi_softap_config_change (5688373762357941645) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-ms/strings.xml b/packages/SettingsProvider/res/values-ms/strings.xml
index a1574df..51a8f2b 100644
--- a/packages/SettingsProvider/res/values-ms/strings.xml
+++ b/packages/SettingsProvider/res/values-ms/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Storan Tetapan"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Perubahan kepada tetapan tempat liputan anda"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Jalur tempat liputan anda telah berubah."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Peranti ini tidak menyokong pilihan anda untuk 5GHz sahaja. Sebaliknya, peranti ini akan menggunakan jalur 5GHz apabila tersedia."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Tetapan tempat liputan telah berubah"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Ketik untuk melihat butiran"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-my/strings.xml b/packages/SettingsProvider/res/values-my/strings.xml
index 48d4dba..dc9f531 100644
--- a/packages/SettingsProvider/res/values-my/strings.xml
+++ b/packages/SettingsProvider/res/values-my/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"သိုလှောင်မှုဆက်တင်များ"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"သင်၏ဟော့စပေါ့ ဆက်တင်များ ပြောင်းလဲမှု"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"သင်၏ ဟော့စပေါ့လိုင်း ပြောင်းသွားပါပြီ။"</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"ဤစက်ပစ္စည်းသည် သင်၏ 5GHz သီးသန့်ရွေးချယ်မှုအတွက် ပံ့ပိုးမထားပါ။ ၎င်းအစား ဤစက်ပစ္စည်းသည် ရနိုင်သည့်အခါ 5GHz လိုင်းကို သုံးသွားပါမည်။"</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"ဟော့စပေါ့ ဆက်တင်များ ပြောင်းသွားပြီ"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"အသေးစိတ်ကြည့်ရန် တို့ပါ"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-nb/strings.xml b/packages/SettingsProvider/res/values-nb/strings.xml
index e0cbd7e..3bdaf83 100644
--- a/packages/SettingsProvider/res/values-nb/strings.xml
+++ b/packages/SettingsProvider/res/values-nb/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Lagring av innstillinger"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Endres til innstillingene dine for Wi-Fi-soner"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Båndet ditt for Wi-Fi-sone er endret."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Denne enheten støtter ikke innstillingen din for bare 5 GHz. I stedet bruker enheten 5 GHz-båndet når det er tilgjengelig."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Innstillingene for Wi-Fi-sone er endret"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Trykk for å se detaljer"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-ne/strings.xml b/packages/SettingsProvider/res/values-ne/strings.xml
index 2fd9b00..bb04b6ba 100644
--- a/packages/SettingsProvider/res/values-ne/strings.xml
+++ b/packages/SettingsProvider/res/values-ne/strings.xml
@@ -20,7 +20,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"सेटिङहरू भण्डारण"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"तपाईंका हटस्पट सेटिङहरूमा गरिएका परिवर्तनहरू"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"तपाईंको हटस्पट ब्यान्ड परिवर्तन भएको छ।"</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"यो यन्त्रले तपाईंको 5GHz मात्रको प्राथमिकतालाई समर्थन गर्दैन। बरु, उपलब्ध भएको खण्डमा यो यन्त्रले 5GHz ब्यान्ड प्रयोग गर्ने छ।"</string>
+ <!-- no translation found for wifi_softap_config_change (5688373762357941645) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-nl/strings.xml b/packages/SettingsProvider/res/values-nl/strings.xml
index 0b843ae..91b8542 100644
--- a/packages/SettingsProvider/res/values-nl/strings.xml
+++ b/packages/SettingsProvider/res/values-nl/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Opslagruimte voor instellingen"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Wijzigingen in je hotspot-instellingen"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Je hotspot-band is gewijzigd."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Dit apparaat biedt geen ondersteuning voor je voorkeur voor alleen 5 GHz. In plaats daarvan gebruikt dit apparaat de 5-GHz-band wanneer deze beschikbaar is."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Hotspot-instellingen zijn gewijzigd"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Tik voor meer informatie"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-or/strings.xml b/packages/SettingsProvider/res/values-or/strings.xml
index 53f6104..4b73a55 100644
--- a/packages/SettingsProvider/res/values-or/strings.xml
+++ b/packages/SettingsProvider/res/values-or/strings.xml
@@ -20,7 +20,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"ସେଟିଙ୍ଗ ଷ୍ଟୋରେଜ୍"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"ଆପଣଙ୍କର ହଟ୍ସ୍ପଟ୍ ସେଟିଂସ୍କୁ ବଦଳାଇଥାଏ"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"ଆପଣଙ୍କର ହଟ୍ସ୍ପଟ୍ ପରିବର୍ତ୍ତନ କରାଯାଇଛି।"</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"କେବଳ 5GHz ପାଇଁ, ଏହି ଡିଭାଇସ୍ ଆପଣଙ୍କର ପସନ୍ଦକୁ ସମର୍ଥନ କରେ ନାହିଁ। ଏହା ପରିବର୍ତ୍ତେ, ଉପଲବ୍ଧ ହେଲେ ଏହି ଡିଭାଇସ୍ 5GHz ବ୍ୟାଣ୍ଡ ବ୍ୟବହାର କରିବ।"</string>
+ <!-- no translation found for wifi_softap_config_change (5688373762357941645) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-pa/strings.xml b/packages/SettingsProvider/res/values-pa/strings.xml
index 9a41e36..5af8d6a 100644
--- a/packages/SettingsProvider/res/values-pa/strings.xml
+++ b/packages/SettingsProvider/res/values-pa/strings.xml
@@ -20,7 +20,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"ਸੈਟਿੰਗਾਂ ਸਟੋਰੇਜ"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"ਤੁਹਾਡੀਆਂ ਹੌਟਸਪੌਟ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਬਦਲਾਅ"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"ਤੁਹਾਡਾ ਹੌਟਸਪੌਟ ਬੈਂਡ ਬਦਲ ਗਿਆ ਹੈ।"</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"ਇਹ ਡੀਵਾਈਸ ਸਿਰਫ਼ 5GHz ਦੀ ਤੁਹਾਡੀ ਤਰਜੀਹ ਦਾ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦਾ ਹੈ। ਇਸਦੀ ਬਜਾਏ, ਇਹ ਡੀਵਾਈਸ ਉਪਲਬਧ ਹੋਣ \'ਤੇ 5GHz ਬੈਂਡ ਵਰਤੇਗਾ।"</string>
+ <!-- no translation found for wifi_softap_config_change (5688373762357941645) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-pl/strings.xml b/packages/SettingsProvider/res/values-pl/strings.xml
index 7fd2b13..d86fc4d 100644
--- a/packages/SettingsProvider/res/values-pl/strings.xml
+++ b/packages/SettingsProvider/res/values-pl/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Pamięć ustawień"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Zmieniono ustawienia hotspotu"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Zmieniono pasmo hotspotu."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"To urządzenie nie może korzystać tylko z częstotliwości 5 GHz. Będzie korzystać z tego pasma, jeśli będzie ono dostępne."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Ustawienia hotspotu zostały zmienione"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Kliknij, by zobaczyć szczegóły"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-pt-rBR/strings.xml b/packages/SettingsProvider/res/values-pt-rBR/strings.xml
index 18db8f6..a860018 100644
--- a/packages/SettingsProvider/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsProvider/res/values-pt-rBR/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Armazenamento de configurações"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Mudanças nas suas configurações de ponto de acesso"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Sua banda de ponto de acesso foi modificada."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Este dispositivo não é compatível com sua preferência apenas por 5 GHz. Em vez disso, o dispositivo usará a banda de 5 GHz quando ela estiver disponível."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"As configurações de ponto de acesso mudaram"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Toque para ver os detalhes"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-pt-rPT/strings.xml b/packages/SettingsProvider/res/values-pt-rPT/strings.xml
index be88cce..a8a8e07 100644
--- a/packages/SettingsProvider/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsProvider/res/values-pt-rPT/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Armazenamento de definições"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Alterações às definições de zona Wi-Fi"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"A banda da sua zona Wi-Fi foi alterada."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Este dispositivo não suporta a sua preferência apenas para 5 GHz. Em alternativa, este dispositivo vai utilizar a banda de 5 GHz quando estiver disponível."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"As definições da zona Wi-Fi foram alteradas"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Toque para ver os detalhes."</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-pt/strings.xml b/packages/SettingsProvider/res/values-pt/strings.xml
index 18db8f6..a860018 100644
--- a/packages/SettingsProvider/res/values-pt/strings.xml
+++ b/packages/SettingsProvider/res/values-pt/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Armazenamento de configurações"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Mudanças nas suas configurações de ponto de acesso"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Sua banda de ponto de acesso foi modificada."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Este dispositivo não é compatível com sua preferência apenas por 5 GHz. Em vez disso, o dispositivo usará a banda de 5 GHz quando ela estiver disponível."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"As configurações de ponto de acesso mudaram"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Toque para ver os detalhes"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-ro/strings.xml b/packages/SettingsProvider/res/values-ro/strings.xml
index 3a234e1..561a213 100644
--- a/packages/SettingsProvider/res/values-ro/strings.xml
+++ b/packages/SettingsProvider/res/values-ro/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Stocare setări"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Modificări aduse setărilor pentru hotspot"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"S-a schimbat banda de frecvență a hotspotului."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Dispozitivul nu acceptă doar preferința pentru 5 GHz. Dispozitivul va folosi banda de 5 GHz când este disponibilă."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Setările hotspotului s-au modificat"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Atingeți pentru detalii"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-ru/strings.xml b/packages/SettingsProvider/res/values-ru/strings.xml
index 184afdd..331fae1 100644
--- a/packages/SettingsProvider/res/values-ru/strings.xml
+++ b/packages/SettingsProvider/res/values-ru/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Хранилище настроек"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Изменения в настройках точки доступа"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Частота точки доступа изменена."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Устройство не может работать только на частоте 5 ГГц. Эта частота будет использоваться, когда это возможно."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Настройки точки доступа изменены"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Нажмите, чтобы узнать больше."</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-si/strings.xml b/packages/SettingsProvider/res/values-si/strings.xml
index 69e04f1..a9c4d0b 100644
--- a/packages/SettingsProvider/res/values-si/strings.xml
+++ b/packages/SettingsProvider/res/values-si/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"සැකසීම් ගබඩාව"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"ඔබගේ හොට්ස්පොට් සැකසීම්වලට වෙනස් කිරීම්"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"ඔබගේ හොට්ස්පොට් කලාපය වෙනස් වී ඇත."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"මෙම උපාංගය 5GHz සඳහා ඔබේ මනාපවලට සහාය නොදක්වයි. ඒ වෙනුවට, මෙම උපාංගය ලබා ගත හැකි විට 5GHz කලාපය භාවිතා කරනු ඇත."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"හොට්ස්පොට් සැකසීම් වෙනස් කර ඇත"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"විස්තර බැලීමට තට්ටු කරන්න"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-sk/strings.xml b/packages/SettingsProvider/res/values-sk/strings.xml
index a53178d..5712d05 100644
--- a/packages/SettingsProvider/res/values-sk/strings.xml
+++ b/packages/SettingsProvider/res/values-sk/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Ukladací priestor nastavení"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Zmeny nastavení hotspotu"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Pásmo vášho hotspotu sa zmenilo."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Toto zariadenie nepodporuje vašu predvoľbu používať iba 5 GHz. Namiesto toho bude pásmo 5 GHz používať vtedy, keď bude k dispozícii."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Nastavenia hotspotu boli zmenené"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Klepnutím zobrazíte podrobnosti"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-sl/strings.xml b/packages/SettingsProvider/res/values-sl/strings.xml
index ea697fe..4e265fb 100644
--- a/packages/SettingsProvider/res/values-sl/strings.xml
+++ b/packages/SettingsProvider/res/values-sl/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Shramba nastavitev"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Spremembe nastavitev dostopne točke"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Pas dostopne točke je spremenjen."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Ta naprava ne podpira prednostne nastavitve samo za 5-GHz pas. Namesto tega bo ta naprava uporabljala 5-GHz pas, ko bo na voljo."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Nastavitve dostopne ročke so spremenjene"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Dotaknite se za ogled podrobnosti"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-sq/strings.xml b/packages/SettingsProvider/res/values-sq/strings.xml
index a111576..8bbe2e7 100644
--- a/packages/SettingsProvider/res/values-sq/strings.xml
+++ b/packages/SettingsProvider/res/values-sq/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Hapësira ruajtëse e \"Cilësimeve\""</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Ndryshimet në cilësimet e zonës së qasjes për internet"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Brezi yt i zonës së qasjes për internet ka ndryshuar."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Kjo pajisje nuk e mbështet preferencën për vetëm 5 GHz. Përkundrazi, pajisja do të përdorë brezin 5 GHz nëse ka."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Cilësimet e zonës së qasjes për internet kanë ndryshuar"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Trokit për të parë detajet"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-sr/strings.xml b/packages/SettingsProvider/res/values-sr/strings.xml
index d473102..4d05762 100644
--- a/packages/SettingsProvider/res/values-sr/strings.xml
+++ b/packages/SettingsProvider/res/values-sr/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Подешавања складишта"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Промене подешавања за хотспот"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Опсег хотспота је промењен."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Овај уређај не подржава подешавање само за 5 GHz. Уређај ће користити опсег од 5 GHz када буде доступан."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Подешавања хотспота су промењена"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Додирните да бисте видели детаље"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-sv/strings.xml b/packages/SettingsProvider/res/values-sv/strings.xml
index fea3e5e..5ee4703 100644
--- a/packages/SettingsProvider/res/values-sv/strings.xml
+++ b/packages/SettingsProvider/res/values-sv/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Lagring av inställningar"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Ändringar i inställningarna för surfzon"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Frekvensbandet för surfzonen har ändrats."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Den här enheten har inte stöd för inställningen för att endast använda 5 GHz. I stället används 5 GHz när det är möjligt."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Inställningarna för surfzon har ändrats"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Tryck här för mer information"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-sw/strings.xml b/packages/SettingsProvider/res/values-sw/strings.xml
index 4d05817..59f82a9 100644
--- a/packages/SettingsProvider/res/values-sw/strings.xml
+++ b/packages/SettingsProvider/res/values-sw/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Hifadhi ya Mipangilio"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Mabadiliko kwenye mipangilio ya mtandaopepe"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Bendi ya mtandaopepe wako imebadilika."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Kifaa hiki hakitumii mapendeleo yako ya GHz 5 pekee. Badala yake, kifaa hiki kitatumia bendi ya GHz 5 itakapopatikana."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Mipangilio ya mtandaopepe imebadilika"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Gusa ili uangalie maelezo"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-ta/strings.xml b/packages/SettingsProvider/res/values-ta/strings.xml
index f518a78..fa6b8cd 100644
--- a/packages/SettingsProvider/res/values-ta/strings.xml
+++ b/packages/SettingsProvider/res/values-ta/strings.xml
@@ -20,7 +20,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"அமைப்புகளின் சேமிப்பிடம்"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"உங்கள் ஹாட்ஸ்பாட் அமைப்புகளில் செய்யப்பட்டுள்ள மாற்றங்கள்"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"உங்கள் ஹாட்ஸ்பாட்டின் அலைவரிசை வரம்பு மாறிவிட்டது."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"இந்தச் சாதனத்தில், ’5GHz மட்டும்’ எனும் முன்னுரிமைத் தேர்வு ஆதரிக்கப்படவில்லை. எனினும் 5GHz அலைவரிசை வரம்பிற்குள் இருக்கும்போது சாதனம் அதைப் பயன்படுத்திக்கொள்ளும்."</string>
+ <!-- no translation found for wifi_softap_config_change (5688373762357941645) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-te/strings.xml b/packages/SettingsProvider/res/values-te/strings.xml
index 6c59223..b1955ed 100644
--- a/packages/SettingsProvider/res/values-te/strings.xml
+++ b/packages/SettingsProvider/res/values-te/strings.xml
@@ -20,7 +20,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"సెట్టింగ్ల నిల్వ"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"మీ హాట్స్పాట్ సెట్టింగ్లకు మార్పులు"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"మీ హాట్స్పాట్ బ్యాండ్ మార్చబడింది."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"ఈ పరికరం 5GHz కోసం మాత్రమే మీ ప్రాధాన్యతకు మద్దతు ఇవ్వదు. బదులుగా, ఈ పరికరం అందుబాటులో ఉన్నప్పుడు 5GHz బ్యాండ్ను ఉపయోగిస్తుంది."</string>
+ <!-- no translation found for wifi_softap_config_change (5688373762357941645) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-th/strings.xml b/packages/SettingsProvider/res/values-th/strings.xml
index 4bf148f..ed63174 100644
--- a/packages/SettingsProvider/res/values-th/strings.xml
+++ b/packages/SettingsProvider/res/values-th/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"ที่เก็บข้อมูลการตั้งค่า"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"มีการเปลี่ยนแปลงการตั้งค่าฮอตสปอต"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"ย่านความถี่ฮอตสปอตมีการเปลี่ยนแปลง"</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"อุปกรณ์นี้ไม่รองรับค่ากำหนดของคุณเฉพาะสำหรับ 5 GHz เท่านั้น และจะใช้ย่านความถี่ 5 GHz แทน เมื่อใช้ได้"</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"การตั้งค่าฮอตสปอตมีการเปลี่ยนแปลง"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"แตะเพื่อดูรายละเอียด"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-tl/strings.xml b/packages/SettingsProvider/res/values-tl/strings.xml
index 2a36d58..3d6be40 100644
--- a/packages/SettingsProvider/res/values-tl/strings.xml
+++ b/packages/SettingsProvider/res/values-tl/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Storage ng Mga Setting"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Mga pagbabago sa mga setting ng iyong hotspot"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Nagbago ang band ng iyong hotspot."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Hindi sinusuportahan ng device na ito ang kagustuhan mong gumamit lang ng 5GHz. Sa halip, gagamitin ng device na ito ang 5GHz na band kapag available."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Nabago ang mga setting ng hotspot"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"I-tap para makita ang mga detalye"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-tr/strings.xml b/packages/SettingsProvider/res/values-tr/strings.xml
index add1fdb..75e908f 100644
--- a/packages/SettingsProvider/res/values-tr/strings.xml
+++ b/packages/SettingsProvider/res/values-tr/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Ayarlar Deposu"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Hotspot ayarlarınız değişti"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Hotspot bandınız değişti."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Bu cihaz yalnızca 5 GHz bandının kullanılmasına yönelik tercihinizi desteklemiyor. Bunun yerine, bu cihaz 5 GHz bandını mevcut olduğunda kullanacak."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Hotspot ayarları değişti"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Ayrıntıları görmek için dokunun"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-uk/strings.xml b/packages/SettingsProvider/res/values-uk/strings.xml
index cd678bc..2dbb360 100644
--- a/packages/SettingsProvider/res/values-uk/strings.xml
+++ b/packages/SettingsProvider/res/values-uk/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Сховище налаштувань"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Зміни в налаштуваннях точки доступу"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Діапазон частот точки доступу змінено."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"На цьому пристрої не підтримується налаштування \"Лише 5 ГГц\". Натомість буде використано діапазон частот 5 ГГц (якщо доступно)."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Налаштування точки доступу змінились"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Торкніться, щоб переглянути докладні відомості"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-ur/strings.xml b/packages/SettingsProvider/res/values-ur/strings.xml
index 2241ce9..2ce44b1 100644
--- a/packages/SettingsProvider/res/values-ur/strings.xml
+++ b/packages/SettingsProvider/res/values-ur/strings.xml
@@ -20,7 +20,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"ترتیبات کا اسٹوریج"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"اپنے ہاٹ اسپاٹ کی ترتیبات میں تبدیلیاں"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"آپ کا ہاٹ اسپات بینڈ تبدیل ہو گیا ہے۔"</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"یہ آلہ صرف 5GHz کے لیے آپ کی ترجیح کو سپورٹ نہیں کرے گا۔ بلکہ 5GHz بینڈ کے دستیاب ہونے پر اس کا استعمال کرے گا۔"</string>
+ <!-- no translation found for wifi_softap_config_change (5688373762357941645) -->
+ <skip />
+ <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) -->
+ <skip />
</resources>
diff --git a/packages/SettingsProvider/res/values-uz/strings.xml b/packages/SettingsProvider/res/values-uz/strings.xml
index a266bf0..bb6e22e 100644
--- a/packages/SettingsProvider/res/values-uz/strings.xml
+++ b/packages/SettingsProvider/res/values-uz/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Sozlamalar xotirasi"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Hotspot sozlamalari o‘zgartirildi"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Hotspot chastotasi oʻzgartirildi."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Qurilma faqat 5 GGs chastotada ishlay olmaydi. Bu chastotadan imkoniyatga qarab foydalaniladi."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Hotspot sozlamalari oʻzgardi"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Tafsilotlar uchun bosing"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-vi/strings.xml b/packages/SettingsProvider/res/values-vi/strings.xml
index 74f93b2..4608983 100644
--- a/packages/SettingsProvider/res/values-vi/strings.xml
+++ b/packages/SettingsProvider/res/values-vi/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Lưu trữ bộ nhớ"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Những thay đổi trong mục cài đặt điểm phát sóng của bạn"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Bằng tần của điểm phát sóng đã thay đổi."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Thiết bị này không hỗ trợ tùy chọn chỉ sử dụng băng tần 5 GHz. Thay vào đó, thiết bị này sẽ sử dụng băng tần 5 GHz khi có thể."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Đã thay đổi các tùy chọn cài đặt điểm phát sóng"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Nhấn để xem chi tiết"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-zh-rCN/strings.xml b/packages/SettingsProvider/res/values-zh-rCN/strings.xml
index 95b15e0..a08afc8 100644
--- a/packages/SettingsProvider/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsProvider/res/values-zh-rCN/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"设置存储"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"您的热点设置已变更"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"您的热点频段已变更。"</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"此设备不支持您的偏好设置(仅限 5GHz),而且会在 5GHz 频段可用时使用该频段。"</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"热点设置已更改"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"点按即可查看详细信息"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-zh-rHK/strings.xml b/packages/SettingsProvider/res/values-zh-rHK/strings.xml
index 41ebe27..fb91dbb 100644
--- a/packages/SettingsProvider/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsProvider/res/values-zh-rHK/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"設定儲存空間"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"您的熱點設定變更"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"您的熱點頻段已變更。"</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"此裝置不支援只限 5 GHz 的偏好設定,但會在 5 GHz 頻段可用時採用。"</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"熱點設定已變更"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"輕按以查看詳情"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-zh-rTW/strings.xml b/packages/SettingsProvider/res/values-zh-rTW/strings.xml
index d0a30f5..1b8fcb2 100644
--- a/packages/SettingsProvider/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsProvider/res/values-zh-rTW/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"設定儲存空間"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"無線基地台設定變更"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"你的無線基地台頻帶已變更。"</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"這部裝置不支援你的偏好設定 (僅限 5GHz),而是會在 5GHz 可用時使用該頻帶。"</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"無線基地台設定有所變更"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"輕觸即可查看詳細資料"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-zu/strings.xml b/packages/SettingsProvider/res/values-zu/strings.xml
index 0440b3b..dad24b4 100644
--- a/packages/SettingsProvider/res/values-zu/strings.xml
+++ b/packages/SettingsProvider/res/values-zu/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"Izilungiselelo zesitoreji"</string>
- <string name="wifi_softap_config_change" msgid="5338670993556993667">"Ushintsho kuzilungiselelo zakho ze-hotspot"</string>
- <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Ibhendi yakho ye-hotspot ishintshile."</string>
- <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Le divayisi ayisekeli okuncamelayo kwe-5GHz kuphela. Kunalokho, le divayisi izosebenzisa ibhendi ye-5GHz uma itholakala."</string>
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"Izilungiselelo ze-Hotspot zishintshile"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Thepha ukuze ubone imininingwane"</string>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 3d9865c..955edcf 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -648,7 +648,7 @@
String appName = topBubble.getAppName();
Notification notification = topBubble.getEntry().getSbn().getNotification();
CharSequence titleCharSeq = notification.extras.getCharSequence(Notification.EXTRA_TITLE);
- String titleStr = getResources().getString(R.string.stream_notification);
+ String titleStr = getResources().getString(R.string.notification_bubble_title);
if (titleCharSeq != null) {
titleStr = titleCharSeq.toString();
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index 6c8aaf4..0a527d4 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -230,6 +230,10 @@
/* This is exactly PendingIntent.getActivity, separated out for testability */
PendingIntent getPendingIntentActivity(Context context, int requestCode, Intent intent,
int flags);
+
+ void setGestureDetectionPassthroughRegion(int displayId, Region region);
+
+ void setTouchExplorationPassthroughRegion(int displayId, Region region);
}
public AbstractAccessibilityServiceConnection(Context context, ComponentName componentName,
@@ -1736,4 +1740,14 @@
public boolean isMultiFingerGesturesEnabled() {
return mRequestMultiFingerGestures;
}
+
+ @Override
+ public void setGestureDetectionPassthroughRegion(int displayId, Region region) {
+ mSystemSupport.setGestureDetectionPassthroughRegion(displayId, region);
+ }
+
+ @Override
+ public void setTouchExplorationPassthroughRegion(int displayId, Region region) {
+ mSystemSupport.setTouchExplorationPassthroughRegion(displayId, region);
+ }
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
index efddd86..020f225 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -17,6 +17,7 @@
package com.android.server.accessibility;
import android.content.Context;
+import android.graphics.Region;
import android.os.PowerManager;
import android.util.Slog;
import android.util.SparseArray;
@@ -726,4 +727,16 @@
return shouldProcess;
}
}
+
+ public void setGestureDetectionPassthroughRegion(int displayId, Region region) {
+ if (region != null && mTouchExplorer.contains(displayId)) {
+ mTouchExplorer.get(displayId).setGestureDetectionPassthroughRegion(region);
+ }
+ }
+
+ public void setTouchExplorationPassthroughRegion(int displayId, Region region) {
+ if (region != null && mTouchExplorer.contains(displayId)) {
+ mTouchExplorer.get(displayId).setTouchExplorationPassthroughRegion(region);
+ }
+ }
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 055bb4c..1a0ca26 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -3058,4 +3058,40 @@
}
}
}
+
+ @Override
+ public void setGestureDetectionPassthroughRegion(int displayId, Region region) {
+ mMainHandler.sendMessage(
+ obtainMessage(
+ AccessibilityManagerService::setGestureDetectionPassthroughRegionInternal,
+ this,
+ displayId,
+ region));
+ }
+
+ @Override
+ public void setTouchExplorationPassthroughRegion(int displayId, Region region) {
+ mMainHandler.sendMessage(
+ obtainMessage(
+ AccessibilityManagerService::setTouchExplorationPassthroughRegionInternal,
+ this,
+ displayId,
+ region));
+ }
+
+ private void setTouchExplorationPassthroughRegionInternal(int displayId, Region region) {
+ synchronized (mLock) {
+ if (mHasInputFilter && mInputFilter != null) {
+ mInputFilter.setTouchExplorationPassthroughRegion(displayId, region);
+ }
+ }
+ }
+
+ private void setGestureDetectionPassthroughRegionInternal(int displayId, Region region) {
+ synchronized (mLock) {
+ if (mHasInputFilter && mInputFilter != null) {
+ mInputFilter.setGestureDetectionPassthroughRegion(displayId, region);
+ }
+ }
+ }
}
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
index 2cc11c5..61c6ef5 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
@@ -23,6 +23,7 @@
import android.accessibilityservice.AccessibilityGestureEvent;
import android.content.Context;
import android.graphics.Point;
+import android.graphics.Region;
import android.os.Handler;
import android.util.Slog;
import android.view.InputDevice;
@@ -120,6 +121,8 @@
// Context in which this explorer operates.
private final Context mContext;
+ private Region mGestureDetectionPassthroughRegion;
+ private Region mTouchExplorationPassthroughRegion;
/**
* Creates a new instance.
@@ -165,6 +168,8 @@
} else {
mGestureDetector = detector;
}
+ mGestureDetectionPassthroughRegion = new Region();
+ mTouchExplorationPassthroughRegion = new Region();
}
@Override
@@ -230,10 +235,11 @@
}
mState.onReceivedMotionEvent(rawEvent);
-
- if (mGestureDetector.onMotionEvent(event, rawEvent, policyFlags)) {
- // Event was handled by the gesture detector.
- return;
+ if (shouldPerformGestureDetection(event)) {
+ if (mGestureDetector.onMotionEvent(event, rawEvent, policyFlags)) {
+ // Event was handled by the gesture detector.
+ return;
+ }
}
if (event.getActionMasked() == MotionEvent.ACTION_CANCEL) {
@@ -418,6 +424,21 @@
mSendTouchExplorationEndDelayed.forceSendAndRemove();
mSendTouchInteractionEndDelayed.forceSendAndRemove();
mDispatcher.sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_START);
+ if (mTouchExplorationPassthroughRegion.contains(
+ (int) event.getX(), (int) event.getY())) {
+ // The touch exploration passthrough overrides the gesture detection passthrough in
+ // the event they overlap.
+ // Pass this entire gesture through to the system as-is.
+ mState.startDelegating();
+ event = MotionEvent.obtainNoHistory(event);
+ mDispatcher.sendMotionEvent(
+ event, event.getAction(), rawEvent, ALL_POINTER_ID_BITS, policyFlags);
+ mSendHoverEnterAndMoveDelayed.cancel();
+ } else if (mGestureDetectionPassthroughRegion.contains(
+ (int) event.getX(), (int) event.getY())) {
+ // Jump straight to touch exploration.
+ mSendHoverEnterAndMoveDelayed.forceSendAndRemove();
+ }
} else {
// Avoid duplicated TYPE_TOUCH_INTERACTION_START event when 2nd tap of double tap.
mSendTouchInteractionEndDelayed.cancel();
@@ -909,6 +930,29 @@
mGestureDetector.setMultiFingerGesturesEnabled(enabled);
}
+ public void setGestureDetectionPassthroughRegion(Region region) {
+ mGestureDetectionPassthroughRegion = region;
+ }
+
+ public void setTouchExplorationPassthroughRegion(Region region) {
+ mTouchExplorationPassthroughRegion = region;
+ }
+
+ private boolean shouldPerformGestureDetection(MotionEvent event) {
+ if (mState.isDelegating()) {
+ return false;
+ }
+ if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
+ final int x = (int) event.getX();
+ final int y = (int) event.getY();
+ if (mTouchExplorationPassthroughRegion.contains(x, y)
+ || mGestureDetectionPassthroughRegion.contains(x, y)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
/**
* Class for delayed exiting from gesture detecting mode.
*/
@@ -1135,5 +1179,4 @@
+ ", mTempPoint: " + mTempPoint
+ " }";
}
-
}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 697e5d7..f544517 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -2624,6 +2624,8 @@
mService.getServicePackageName(), mComponentName,
serviceLabel, serviceIcon, this, id, mCompatMode);
+ mService.logDatasetShown(id, mClientState);
+
synchronized (mLock) {
if (mUiShownTime == 0) {
// Log first time UI is shown.
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index 63d0924..fde654d 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -69,6 +69,25 @@
public static final int PACKAGE_COMPANION = 14;
public static final int PACKAGE_RETAIL_DEMO = 15;
+ @IntDef(flag = true, prefix = "RESOLVE_", value = {
+ RESOLVE_NON_BROWSER_ONLY,
+ RESOLVE_NON_RESOLVER_ONLY
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PrivateResolveFlags {}
+
+ /**
+ * Internal {@link #resolveIntent(Intent, String, int, int, int, boolean, int)} flag:
+ * only match components that contain a generic web intent filter.
+ */
+ public static final int RESOLVE_NON_BROWSER_ONLY = 0x00000001;
+
+ /**
+ * Internal {@link #resolveIntent(Intent, String, int, int, int, boolean, int)} flag: do not
+ * match to the resolver.
+ */
+ public static final int RESOLVE_NON_RESOLVER_ONLY = 0x00000002;
+
@IntDef(value = {
INTEGRITY_VERIFICATION_ALLOW,
INTEGRITY_VERIFICATION_REJECT,
@@ -507,7 +526,8 @@
* Resolves an activity intent, allowing instant apps to be resolved.
*/
public abstract ResolveInfo resolveIntent(Intent intent, String resolvedType,
- int flags, int userId, boolean resolveForStart, int filterCallingUid);
+ int flags, @PrivateResolveFlags int privateResolveFlags, int userId,
+ boolean resolveForStart, int filterCallingUid);
/**
* Resolves a service intent, allowing instant apps to be resolved.
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index a651d9d..a2ae678 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -1994,12 +1994,11 @@
if (app.hasForegroundServices()) {
capability |= capabilityFromFGS;
} else if (!ActivityManager.isProcStateBackground(procState)) {
- // procState higher than PROCESS_STATE_TRANSIENT_BACKGROUND implicitly has
+ // procState higher than PROCESS_STATE_BOUND_FOREGROUND_SERVICE implicitly has
// camera/microphone capability
if (procState == PROCESS_STATE_FOREGROUND_SERVICE && procStateFromFGSClient) {
// if the FGS state is passed down from client, do not grant implicit capabilities.
} else {
- //TODO: remove this line when enforcing the feature.
capability |= PROCESS_CAPABILITY_ALL_IMPLICIT;
}
}
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index a934f22..40acfe1 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -536,9 +536,8 @@
// The FGS has the location capability, but due to FGS BG start
// restriction it lost the capability, use temp location capability
// to mark this case.
- // TODO change to MODE_IGNORED when enforcing the feature.
maybeShowWhileInUseDebugToast(op, mode);
- return AppOpsManager.MODE_ALLOWED;
+ return AppOpsManager.MODE_IGNORED;
} else {
return AppOpsManager.MODE_IGNORED;
}
@@ -546,17 +545,15 @@
if ((capability & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0) {
return AppOpsManager.MODE_ALLOWED;
} else {
- //TODO change to MODE_IGNORED when enforcing the feature.
maybeShowWhileInUseDebugToast(op, mode);
- return AppOpsManager.MODE_ALLOWED;
+ return AppOpsManager.MODE_IGNORED;
}
case OP_RECORD_AUDIO:
if ((capability & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0) {
return AppOpsManager.MODE_ALLOWED;
} else {
- //TODO change to MODE_IGNORED when enforcing the feature.
maybeShowWhileInUseDebugToast(op, mode);
- return AppOpsManager.MODE_ALLOWED;
+ return AppOpsManager.MODE_IGNORED;
}
default:
return AppOpsManager.MODE_ALLOWED;
@@ -571,17 +568,15 @@
if ((capability & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0) {
return AppOpsManager.MODE_ALLOWED;
} else {
- //TODO change to MODE_IGNORED when enforcing the feature.
maybeShowWhileInUseDebugToast(op, mode);
- return AppOpsManager.MODE_ALLOWED;
+ return AppOpsManager.MODE_IGNORED;
}
case OP_RECORD_AUDIO:
if ((capability & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0) {
return AppOpsManager.MODE_ALLOWED;
} else {
- //TODO change to MODE_IGNORED when enforcing the feature.
maybeShowWhileInUseDebugToast(op, mode);
- return AppOpsManager.MODE_ALLOWED;
+ return AppOpsManager.MODE_IGNORED;
}
default:
return MODE_ALLOWED;
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 566b72d..b546120 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -24,7 +24,7 @@
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
-import android.media.AudioDevice;
+import android.media.AudioDeviceAttributes;
import android.media.AudioManager;
import android.media.AudioRoutesInfo;
import android.media.AudioSystem;
@@ -403,7 +403,7 @@
}
/*package*/ int setPreferredDeviceForStrategySync(int strategy,
- @NonNull AudioDevice device) {
+ @NonNull AudioDeviceAttributes device) {
return mDeviceInventory.setPreferredDeviceForStrategySync(strategy, device);
}
@@ -554,7 +554,8 @@
sendLMsgNoDelay(MSG_L_SCOCLIENT_DIED, SENDMSG_QUEUE, obj);
}
- /*package*/ void postSaveSetPreferredDeviceForStrategy(int strategy, AudioDevice device)
+ /*package*/ void postSaveSetPreferredDeviceForStrategy(int strategy,
+ AudioDeviceAttributes device)
{
sendILMsgNoDelay(MSG_IL_SAVE_PREF_DEVICE_FOR_STRATEGY, SENDMSG_QUEUE, strategy, device);
}
@@ -915,7 +916,7 @@
} break;
case MSG_IL_SAVE_PREF_DEVICE_FOR_STRATEGY: {
final int strategy = msg.arg1;
- final AudioDevice device = (AudioDevice) msg.obj;
+ final AudioDeviceAttributes device = (AudioDeviceAttributes) msg.obj;
mDeviceInventory.onSaveSetPreferredDevice(strategy, device);
} break;
case MSG_I_SAVE_REMOVE_PREF_DEVICE_FOR_STRATEGY: {
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index e170db0..c17ed3e 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -24,7 +24,7 @@
import android.bluetooth.BluetoothHearingAid;
import android.bluetooth.BluetoothProfile;
import android.content.Intent;
-import android.media.AudioDevice;
+import android.media.AudioDeviceAttributes;
import android.media.AudioDevicePort;
import android.media.AudioFormat;
import android.media.AudioManager;
@@ -77,7 +77,7 @@
private final ArrayMap<Integer, String> mApmConnectedDevices = new ArrayMap<>();
// List of preferred devices for strategies
- private final ArrayMap<Integer, AudioDevice> mPreferredDevices = new ArrayMap<>();
+ private final ArrayMap<Integer, AudioDeviceAttributes> mPreferredDevices = new ArrayMap<>();
// the wrapper for AudioSystem static methods, allows us to spy AudioSystem
private final @NonNull AudioSystemAdapter mAudioSystem;
@@ -474,7 +474,7 @@
}
}
- /*package*/ void onSaveSetPreferredDevice(int strategy, @NonNull AudioDevice device) {
+ /*package*/ void onSaveSetPreferredDevice(int strategy, @NonNull AudioDeviceAttributes device) {
mPreferredDevices.put(strategy, device);
dispatchPreferredDevice(strategy, device);
}
@@ -488,7 +488,7 @@
//
/*package*/ int setPreferredDeviceForStrategySync(int strategy,
- @NonNull AudioDevice device) {
+ @NonNull AudioDeviceAttributes device) {
final long identity = Binder.clearCallingIdentity();
final int status = mAudioSystem.setPreferredDeviceForStrategy(strategy, device);
Binder.restoreCallingIdentity(identity);
@@ -1112,7 +1112,7 @@
}
}
- private void dispatchPreferredDevice(int strategy, @Nullable AudioDevice device) {
+ private void dispatchPreferredDevice(int strategy, @Nullable AudioDeviceAttributes device) {
final int nbDispatchers = mPrefDevDispatchers.beginBroadcast();
for (int i = 0; i < nbDispatchers; i++) {
try {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 4be74b5..f3d42ad 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -65,7 +65,7 @@
import android.hidl.manager.V1_0.IServiceManager;
import android.media.AudioAttributes;
import android.media.AudioAttributes.AttributeSystemUsage;
-import android.media.AudioDevice;
+import android.media.AudioDeviceAttributes;
import android.media.AudioDeviceInfo;
import android.media.AudioFocusInfo;
import android.media.AudioFocusRequest;
@@ -1734,7 +1734,7 @@
// IPC methods
///////////////////////////////////////////////////////////////////////////
/** @see AudioManager#setPreferredDeviceForStrategy(AudioProductStrategy, AudioDeviceInfo) */
- public int setPreferredDeviceForStrategy(int strategy, AudioDevice device) {
+ public int setPreferredDeviceForStrategy(int strategy, AudioDeviceAttributes device) {
if (device == null) {
return AudioSystem.ERROR;
}
@@ -1743,7 +1743,7 @@
"setPreferredDeviceForStrategy u/pid:%d/%d strat:%d dev:%s",
Binder.getCallingUid(), Binder.getCallingPid(), strategy, device.toString());
sDeviceLogger.log(new AudioEventLogger.StringEvent(logString).printLog(TAG));
- if (device.getRole() == AudioDevice.ROLE_INPUT) {
+ if (device.getRole() == AudioDeviceAttributes.ROLE_INPUT) {
Log.e(TAG, "Unsupported input routing in " + logString);
return AudioSystem.ERROR;
}
@@ -1771,9 +1771,9 @@
}
/** @see AudioManager#getPreferredDeviceForStrategy(AudioProductStrategy) */
- public AudioDevice getPreferredDeviceForStrategy(int strategy) {
+ public AudioDeviceAttributes getPreferredDeviceForStrategy(int strategy) {
enforceModifyAudioRoutingPermission();
- AudioDevice[] devices = new AudioDevice[1];
+ AudioDeviceAttributes[] devices = new AudioDeviceAttributes[1];
final long identity = Binder.clearCallingIdentity();
final int status = AudioSystem.getPreferredDeviceForStrategy(strategy, devices);
Binder.restoreCallingIdentity(identity);
@@ -1807,7 +1807,7 @@
}
/** @see AudioManager#getDevicesForAttributes(AudioAttributes) */
- public @NonNull ArrayList<AudioDevice> getDevicesForAttributes(
+ public @NonNull ArrayList<AudioDeviceAttributes> getDevicesForAttributes(
@NonNull AudioAttributes attributes) {
Objects.requireNonNull(attributes);
enforceModifyAudioRoutingPermission();
diff --git a/services/core/java/com/android/server/audio/AudioSystemAdapter.java b/services/core/java/com/android/server/audio/AudioSystemAdapter.java
index a3086c0..9f8f9f8 100644
--- a/services/core/java/com/android/server/audio/AudioSystemAdapter.java
+++ b/services/core/java/com/android/server/audio/AudioSystemAdapter.java
@@ -17,7 +17,7 @@
package com.android.server.audio;
import android.annotation.NonNull;
-import android.media.AudioDevice;
+import android.media.AudioDeviceAttributes;
import android.media.AudioSystem;
import android.util.Log;
@@ -86,12 +86,12 @@
}
/**
- * Same as {@link AudioSystem#setPreferredDeviceForStrategy(int, AudioDevice)}
+ * Same as {@link AudioSystem#setPreferredDeviceForStrategy(int, AudioDeviceAttributes)}
* @param strategy
* @param device
* @return
*/
- public int setPreferredDeviceForStrategy(int strategy, @NonNull AudioDevice device) {
+ public int setPreferredDeviceForStrategy(int strategy, @NonNull AudioDeviceAttributes device) {
return AudioSystem.setPreferredDeviceForStrategy(strategy, device);
}
@@ -138,7 +138,8 @@
}
@Override
- public int setPreferredDeviceForStrategy(int strategy, @NonNull AudioDevice device) {
+ public int setPreferredDeviceForStrategy(int strategy,
+ @NonNull AudioDeviceAttributes device) {
return AudioSystem.AUDIO_STATUS_OK;
}
diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java
index 7f7c9c4..3f03e09 100644
--- a/services/core/java/com/android/server/compat/CompatConfig.java
+++ b/services/core/java/com/android/server/compat/CompatConfig.java
@@ -16,6 +16,7 @@
package com.android.server.compat;
+import android.app.compat.ChangeIdStateCache;
import android.compat.Compatibility.ChangeConfig;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -80,6 +81,7 @@
void addChange(CompatChange change) {
synchronized (mChanges) {
mChanges.put(change.getId(), change);
+ invalidateCache();
}
}
@@ -172,6 +174,7 @@
addChange(c);
}
c.addPackageOverride(packageName, enabled);
+ invalidateCache();
}
return alreadyKnown;
}
@@ -228,6 +231,7 @@
// Should never occur, since validator is in the same process.
throw new RuntimeException("Unable to call override validator!", e);
}
+ invalidateCache();
}
return overrideExists;
}
@@ -250,6 +254,7 @@
addOverride(changeId, packageName, false);
}
+ invalidateCache();
}
}
@@ -279,6 +284,7 @@
throw new RuntimeException("Unable to call override validator!", e);
}
}
+ invalidateCache();
}
}
@@ -406,4 +412,8 @@
IOverrideValidator getOverrideValidator() {
return mOverrideValidator;
}
+
+ private void invalidateCache() {
+ ChangeIdStateCache.invalidate();
+ }
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index ad4e81b..fd86f1d 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -8609,21 +8609,11 @@
@VisibleForTesting
boolean canUseManagedServices(String pkg, Integer userId, String requiredPermission) {
- boolean canUseManagedServices = !mActivityManager.isLowRamDevice()
- || mPackageManagerClient.hasSystemFeature(PackageManager.FEATURE_WATCH);
-
- for (String whitelisted : getContext().getResources().getStringArray(
- R.array.config_allowedManagedServicesOnLowRamDevices)) {
- if (whitelisted.equals(pkg)) {
- canUseManagedServices = true;
- break;
- }
- }
-
+ boolean canUseManagedServices = true;
if (requiredPermission != null) {
try {
if (mPackageManager.checkPermission(requiredPermission, pkg, userId)
- != PackageManager.PERMISSION_GRANTED) {
+ != PackageManager.PERMISSION_GRANTED) {
canUseManagedServices = false;
}
} catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index d75eb6d..f221285 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -62,6 +62,7 @@
import android.util.Slog;
import android.util.SparseArray;
+import com.android.internal.content.om.OverlayConfig;
import com.android.server.FgThread;
import com.android.server.IoThread;
import com.android.server.LocalServices;
@@ -248,7 +249,8 @@
IdmapManager im = new IdmapManager(mPackageManager);
mSettings = new OverlayManagerSettings();
mImpl = new OverlayManagerServiceImpl(mPackageManager, im, mSettings,
- getDefaultOverlayPackages(), new OverlayChangeListener());
+ OverlayConfig.getSystemInstance(), getDefaultOverlayPackages(),
+ new OverlayChangeListener());
mActorEnforcer = new OverlayActorEnforcer(mPackageManager);
final IntentFilter packageFilter = new IntentFilter();
@@ -835,7 +837,7 @@
case "basecodepath":
case "state":
case "isenabled":
- case "isstatic":
+ case "ismutable":
case "priority":
case "category":
dumpState.setField(arg);
diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
index 9623542..2493057 100644
--- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
@@ -18,7 +18,7 @@
import static android.content.om.OverlayInfo.STATE_DISABLED;
import static android.content.om.OverlayInfo.STATE_ENABLED;
-import static android.content.om.OverlayInfo.STATE_ENABLED_STATIC;
+import static android.content.om.OverlayInfo.STATE_ENABLED_IMMUTABLE;
import static android.content.om.OverlayInfo.STATE_MISSING_TARGET;
import static android.content.om.OverlayInfo.STATE_NO_IDMAP;
import static android.content.om.OverlayInfo.STATE_OVERLAY_IS_BEING_REPLACED;
@@ -37,6 +37,7 @@
import android.util.ArraySet;
import android.util.Slog;
+import com.android.internal.content.om.OverlayConfig;
import com.android.internal.util.ArrayUtils;
import java.io.PrintWriter;
@@ -69,6 +70,7 @@
private final PackageManagerHelper mPackageManager;
private final IdmapManager mIdmapManager;
private final OverlayManagerSettings mSettings;
+ private final OverlayConfig mOverlayConfig;
private final String[] mDefaultOverlays;
private final OverlayChangeListener mListener;
@@ -83,7 +85,7 @@
* should either scrap the overlay manager's previous settings or merge the old
* settings with the new.
*/
- private static boolean mustReinitializeOverlay(@NonNull final PackageInfo theTruth,
+ private boolean mustReinitializeOverlay(@NonNull final PackageInfo theTruth,
@Nullable final OverlayInfo oldSettings) {
if (oldSettings == null) {
return true;
@@ -94,27 +96,35 @@
if (!Objects.equals(theTruth.targetOverlayableName, oldSettings.targetOverlayableName)) {
return true;
}
- if (theTruth.isStaticOverlayPackage() != oldSettings.isStatic) {
+
+ boolean isMutable = isPackageConfiguredMutable(theTruth.packageName);
+ if (isMutable != oldSettings.isMutable) {
return true;
}
- // a change in priority is only relevant for static RROs: specifically,
- // a regular RRO should not have its state reset only because a change
- // in priority
- if (theTruth.isStaticOverlayPackage()
- && theTruth.overlayPriority != oldSettings.priority) {
+
+ if (getPackageConfiguredPriority(theTruth.packageName) != oldSettings.priority) {
return true;
}
+
+ // If an immutable overlay changes its configured enabled state, reinitialize the overlay.
+ if (!isMutable && isPackageConfiguredEnabled(theTruth.packageName)
+ != oldSettings.isEnabled()) {
+ return true;
+ }
+
return false;
}
OverlayManagerServiceImpl(@NonNull final PackageManagerHelper packageManager,
@NonNull final IdmapManager idmapManager,
@NonNull final OverlayManagerSettings settings,
+ @NonNull final OverlayConfig overlayConfig,
@NonNull final String[] defaultOverlays,
@NonNull final OverlayChangeListener listener) {
mPackageManager = packageManager;
mIdmapManager = idmapManager;
mSettings = settings;
+ mOverlayConfig = overlayConfig;
mDefaultOverlays = defaultOverlays;
mListener = listener;
}
@@ -162,8 +172,9 @@
overlayPackage.overlayTarget,
overlayPackage.targetOverlayableName,
overlayPackage.applicationInfo.getBaseCodePath(),
- overlayPackage.isStaticOverlayPackage(),
- overlayPackage.overlayPriority,
+ isPackageConfiguredMutable(overlayPackage.packageName),
+ isPackageConfiguredEnabled(overlayPackage.packageName),
+ getPackageConfiguredPriority(overlayPackage.packageName),
overlayPackage.overlayCategory);
}
@@ -374,7 +385,9 @@
mSettings.init(packageName, userId, overlayPackage.overlayTarget,
overlayPackage.targetOverlayableName,
overlayPackage.applicationInfo.getBaseCodePath(),
- overlayPackage.isStaticOverlayPackage(), overlayPackage.overlayPriority,
+ isPackageConfiguredMutable(overlayPackage.packageName),
+ isPackageConfiguredEnabled(overlayPackage.packageName),
+ getPackageConfiguredPriority(overlayPackage.packageName),
overlayPackage.overlayCategory);
try {
if (updateState(overlayPackage.overlayTarget, packageName, userId, 0)) {
@@ -439,8 +452,10 @@
mListener.onOverlaysChanged(pkg.overlayTarget, userId);
}
mSettings.init(packageName, userId, pkg.overlayTarget, pkg.targetOverlayableName,
- pkg.applicationInfo.getBaseCodePath(), pkg.isStaticOverlayPackage(),
- pkg.overlayPriority, pkg.overlayCategory);
+ pkg.applicationInfo.getBaseCodePath(),
+ isPackageConfiguredMutable(pkg.packageName),
+ isPackageConfiguredEnabled(pkg.packageName),
+ getPackageConfiguredPriority(pkg.packageName), pkg.overlayCategory);
}
if (updateState(pkg.overlayTarget, packageName, userId, 0)) {
@@ -492,13 +507,13 @@
return false;
}
- // Ignore static overlays.
- if (overlayPackage.isStaticOverlayPackage()) {
- return false;
- }
-
try {
final OverlayInfo oi = mSettings.getOverlayInfo(packageName, userId);
+ if (!oi.isMutable) {
+ // Ignore immutable overlays.
+ return false;
+ }
+
boolean modified = mSettings.setEnabled(packageName, userId, enable);
modified |= updateState(oi.targetPackageName, oi.packageName, userId, 0);
@@ -534,7 +549,8 @@
// Disable all other overlays.
allOverlays.remove(oi);
for (int i = 0; i < allOverlays.size(); i++) {
- final String disabledOverlayPackageName = allOverlays.get(i).packageName;
+ final OverlayInfo disabledInfo = allOverlays.get(i);
+ final String disabledOverlayPackageName = disabledInfo.packageName;
final PackageInfo disabledOverlayPackageInfo = mPackageManager.getPackageInfo(
disabledOverlayPackageName, userId);
if (disabledOverlayPackageInfo == null) {
@@ -542,8 +558,8 @@
continue;
}
- if (disabledOverlayPackageInfo.isStaticOverlayPackage()) {
- // Don't touch static overlays.
+ if (!disabledInfo.isMutable) {
+ // Don't touch immutable overlays.
continue;
}
if (withinCategory && !Objects.equals(disabledOverlayPackageInfo.overlayCategory,
@@ -570,12 +586,16 @@
}
}
- private boolean isPackageUpdatableOverlay(@NonNull final String packageName, final int userId) {
- final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
- if (overlayPackage == null || overlayPackage.isStaticOverlayPackage()) {
- return false;
- }
- return true;
+ private boolean isPackageConfiguredMutable(@NonNull final String packageName) {
+ return mOverlayConfig.isMutable(packageName);
+ }
+
+ private int getPackageConfiguredPriority(@NonNull final String packageName) {
+ return mOverlayConfig.getPriority(packageName);
+ }
+
+ private boolean isPackageConfiguredEnabled(@NonNull final String packageName) {
+ return mOverlayConfig.isEnabled(packageName);
}
boolean setPriority(@NonNull final String packageName,
@@ -585,7 +605,7 @@
+ newParentPackageName + " userId=" + userId);
}
- if (!isPackageUpdatableOverlay(packageName, userId)) {
+ if (!isPackageConfiguredMutable(packageName)) {
return false;
}
@@ -605,7 +625,7 @@
Slog.d(TAG, "setHighestPriority packageName=" + packageName + " userId=" + userId);
}
- if (!isPackageUpdatableOverlay(packageName, userId)) {
+ if (!isPackageConfiguredMutable(packageName)) {
return false;
}
@@ -625,7 +645,7 @@
Slog.d(TAG, "setLowestPriority packageName=" + packageName + " userId=" + userId);
}
- if (!isPackageUpdatableOverlay(packageName, userId)) {
+ if (!isPackageConfiguredMutable(packageName)) {
return false;
}
@@ -682,10 +702,10 @@
final PackageInfo overlayPackage = mPackageManager.getPackageInfo(overlayPackageName,
userId);
- // Static RROs targeting to "android", ie framework-res.apk, are handled by native layers.
+ // Immutable RROs targeting to "android", ie framework-res.apk, are handled by native layers.
if (targetPackage != null && overlayPackage != null
&& !("android".equals(targetPackageName)
- && overlayPackage.isStaticOverlayPackage())) {
+ && !isPackageConfiguredMutable(overlayPackageName))) {
mIdmapManager.createIdmap(targetPackage, overlayPackage, userId);
}
@@ -737,10 +757,6 @@
return STATE_NO_IDMAP;
}
- if (overlayPackage.isStaticOverlayPackage()) {
- return STATE_ENABLED_STATIC;
- }
-
final boolean enabled = mSettings.getEnabled(overlayPackage.packageName, userId);
return enabled ? STATE_ENABLED : STATE_DISABLED;
}
diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java
index b7346d4..6bccdfc 100644
--- a/services/core/java/com/android/server/om/OverlayManagerSettings.java
+++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java
@@ -67,32 +67,27 @@
private final ArrayList<SettingsItem> mItems = new ArrayList<>();
void init(@NonNull final String packageName, final int userId,
- @NonNull final String targetPackageName, @Nullable final String targetOverlayableName,
- @NonNull final String baseCodePath, boolean isStatic, int priority,
+ @NonNull final String targetPackageName, @Nullable final String targetOverlayableName,
+ @NonNull final String baseCodePath, boolean isMutable, boolean isEnabled, int priority,
@Nullable String overlayCategory) {
remove(packageName, userId);
final SettingsItem item =
new SettingsItem(packageName, userId, targetPackageName, targetOverlayableName,
- baseCodePath, isStatic, priority, overlayCategory);
- if (isStatic) {
- // All static overlays are always enabled.
- item.setEnabled(true);
+ baseCodePath, OverlayInfo.STATE_UNKNOWN, isEnabled, isMutable, priority,
+ overlayCategory);
- int i;
- for (i = mItems.size() - 1; i >= 0; i--) {
- SettingsItem parentItem = mItems.get(i);
- if (parentItem.mIsStatic && parentItem.mPriority <= priority) {
- break;
- }
+ int i;
+ for (i = mItems.size() - 1; i >= 0; i--) {
+ SettingsItem parentItem = mItems.get(i);
+ if (parentItem.mPriority <= priority) {
+ break;
}
- int pos = i + 1;
- if (pos == mItems.size()) {
- mItems.add(item);
- } else {
- mItems.add(pos, item);
- }
- } else {
+ }
+ int pos = i + 1;
+ if (pos == mItems.size()) {
mItems.add(item);
+ } else {
+ mItems.add(pos, item);
}
}
@@ -182,19 +177,19 @@
List<OverlayInfo> getOverlaysForTarget(@NonNull final String targetPackageName,
final int userId) {
- // Static RROs targeting "android" are loaded from AssetManager, and so they should be
+ // Immutable RROs targeting "android" are loaded from AssetManager, and so they should be
// ignored in OverlayManagerService.
return selectWhereTarget(targetPackageName, userId)
- .filter((i) -> !(i.isStatic() && "android".equals(i.getTargetPackageName())))
+ .filter((i) -> i.isMutable() || !"android".equals(i.getTargetPackageName()))
.map(SettingsItem::getOverlayInfo)
.collect(Collectors.toList());
}
ArrayMap<String, List<OverlayInfo>> getOverlaysForUser(final int userId) {
- // Static RROs targeting "android" are loaded from AssetManager, and so they should be
+ // Immutable RROs targeting "android" are loaded from AssetManager, and so they should be
// ignored in OverlayManagerService.
return selectWhereUser(userId)
- .filter((i) -> !(i.isStatic() && "android".equals(i.getTargetPackageName())))
+ .filter((i) -> i.isMutable() || !"android".equals(i.getTargetPackageName()))
.map(SettingsItem::getOverlayInfo)
.collect(Collectors.groupingBy(info -> info.targetPackageName, ArrayMap::new,
Collectors.toList()));
@@ -320,7 +315,7 @@
pw.println("mBaseCodePath..........: " + item.getBaseCodePath());
pw.println("mState.................: " + OverlayInfo.stateToString(item.getState()));
pw.println("mIsEnabled.............: " + item.isEnabled());
- pw.println("mIsStatic..............: " + item.isStatic());
+ pw.println("mIsMutable.............: " + item.isMutable());
pw.println("mPriority..............: " + item.mPriority);
pw.println("mCategory..............: " + item.mCategory);
@@ -352,8 +347,8 @@
case "isenabled":
pw.println(item.mIsEnabled);
break;
- case "isstatic":
- pw.println(item.mIsStatic);
+ case "ismutable":
+ pw.println(item.mIsMutable);
break;
case "priority":
pw.println(item.mPriority);
@@ -446,7 +441,7 @@
final String category = XmlUtils.readStringAttribute(parser, ATTR_CATEGORY);
return new SettingsItem(packageName, userId, targetPackageName, targetOverlayableName,
- baseCodePath, state, isEnabled, isStatic, priority, category);
+ baseCodePath, state, isEnabled, !isStatic, priority, category);
}
public static void persist(@NonNull final ArrayList<SettingsItem> table,
@@ -478,7 +473,7 @@
XmlUtils.writeStringAttribute(xml, ATTR_BASE_CODE_PATH, item.mBaseCodePath);
XmlUtils.writeIntAttribute(xml, ATTR_STATE, item.mState);
XmlUtils.writeBooleanAttribute(xml, ATTR_IS_ENABLED, item.mIsEnabled);
- XmlUtils.writeBooleanAttribute(xml, ATTR_IS_STATIC, item.mIsStatic);
+ XmlUtils.writeBooleanAttribute(xml, ATTR_IS_STATIC, !item.mIsMutable);
XmlUtils.writeIntAttribute(xml, ATTR_PRIORITY, item.mPriority);
XmlUtils.writeStringAttribute(xml, ATTR_CATEGORY, item.mCategory);
xml.endTag(null, TAG_ITEM);
@@ -494,36 +489,28 @@
private @OverlayInfo.State int mState;
private boolean mIsEnabled;
private OverlayInfo mCache;
- private boolean mIsStatic;
+ private boolean mIsMutable;
private int mPriority;
private String mCategory;
SettingsItem(@NonNull final String packageName, final int userId,
@NonNull final String targetPackageName,
@Nullable final String targetOverlayableName, @NonNull final String baseCodePath,
- final @OverlayInfo.State int state, final boolean isEnabled, final boolean isStatic,
- final int priority, @Nullable String category) {
+ final @OverlayInfo.State int state, final boolean isEnabled,
+ final boolean isMutable, final int priority, @Nullable String category) {
mPackageName = packageName;
mUserId = userId;
mTargetPackageName = targetPackageName;
mTargetOverlayableName = targetOverlayableName;
mBaseCodePath = baseCodePath;
mState = state;
- mIsEnabled = isEnabled || isStatic;
+ mIsEnabled = isEnabled;
mCategory = category;
mCache = null;
- mIsStatic = isStatic;
+ mIsMutable = isMutable;
mPriority = priority;
}
- SettingsItem(@NonNull final String packageName, final int userId,
- @NonNull final String targetPackageName,
- @Nullable final String targetOverlayableName, @NonNull final String baseCodePath,
- final boolean isStatic, final int priority, @Nullable String category) {
- this(packageName, userId, targetPackageName, targetOverlayableName, baseCodePath,
- OverlayInfo.STATE_UNKNOWN, false, isStatic, priority, category);
- }
-
private String getTargetPackageName() {
return mTargetPackageName;
}
@@ -567,7 +554,7 @@
}
private boolean setEnabled(boolean enable) {
- if (mIsStatic) {
+ if (!mIsMutable) {
return false;
}
@@ -591,7 +578,7 @@
private OverlayInfo getOverlayInfo() {
if (mCache == null) {
mCache = new OverlayInfo(mPackageName, mTargetPackageName, mTargetOverlayableName,
- mCategory, mBaseCodePath, mState, mUserId, mPriority, mIsStatic);
+ mCategory, mBaseCodePath, mState, mUserId, mPriority, mIsMutable);
}
return mCache;
}
@@ -600,8 +587,8 @@
mCache = null;
}
- private boolean isStatic() {
- return mIsStatic;
+ private boolean isMutable() {
+ return mIsMutable;
}
private int getPriority() {
diff --git a/services/core/java/com/android/server/om/OverlayManagerShellCommand.java b/services/core/java/com/android/server/om/OverlayManagerShellCommand.java
index eb43275..bf99bd6 100644
--- a/services/core/java/com/android/server/om/OverlayManagerShellCommand.java
+++ b/services/core/java/com/android/server/om/OverlayManagerShellCommand.java
@@ -181,7 +181,7 @@
private void printListOverlay(PrintWriter out, OverlayInfo oi) {
String status;
switch (oi.state) {
- case OverlayInfo.STATE_ENABLED_STATIC:
+ case OverlayInfo.STATE_ENABLED_IMMUTABLE:
case OverlayInfo.STATE_ENABLED:
status = "[x]";
break;
diff --git a/services/core/java/com/android/server/pm/ComponentResolver.java b/services/core/java/com/android/server/pm/ComponentResolver.java
index 13bd7e5..ea48395 100644
--- a/services/core/java/com/android/server/pm/ComponentResolver.java
+++ b/services/core/java/com/android/server/pm/ComponentResolver.java
@@ -32,6 +32,7 @@
import android.content.pm.InstantAppResolveInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
+import android.content.pm.PackageManagerInternal.PrivateResolveFlags;
import android.content.pm.PackageUserState;
import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
@@ -229,9 +230,11 @@
}
@Nullable
- List<ResolveInfo> queryActivities(Intent intent, String resolvedType, int flags, int userId) {
+ List<ResolveInfo> queryActivities(Intent intent, String resolvedType, int flags,
+ @PrivateResolveFlags int privateResolveFlags, int userId) {
synchronized (mLock) {
- return mActivities.queryIntent(intent, resolvedType, flags, userId);
+ return mActivities.queryIntent(
+ intent, resolvedType, flags, privateResolveFlags, userId);
}
}
@@ -368,7 +371,7 @@
@Nullable
List<ResolveInfo> queryReceivers(Intent intent, String resolvedType, int flags, int userId) {
synchronized (mLock) {
- return mReceivers.queryIntent(intent, resolvedType, flags, userId);
+ return mReceivers.queryIntent(intent, resolvedType, flags, 0, userId);
}
}
@@ -1154,11 +1157,12 @@
}
List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
- int userId) {
+ int privateResolveFlags, int userId) {
if (!sUserManager.exists(userId)) {
return null;
}
mFlags = flags;
+ mPrivateResolveFlags = privateResolveFlags;
return super.queryIntent(intent, resolvedType,
(flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
userId);
@@ -1388,6 +1392,11 @@
}
return null;
}
+ final boolean matchNonBrowserOnly =
+ (mPrivateResolveFlags & PackageManagerInternal.RESOLVE_NON_BROWSER_ONLY) != 0;
+ if (matchNonBrowserOnly && info.handleAllWebDataURI()) {
+ return null;
+ }
final ResolveInfo res = new ResolveInfo();
res.activityInfo = ai;
if ((mFlags & PackageManager.GET_RESOLVED_FILTER) != 0) {
@@ -1465,6 +1474,7 @@
private final ArrayMap<ComponentName, ParsedActivity> mActivities =
new ArrayMap<>();
private int mFlags;
+ private int mPrivateResolveFlags;
}
// Both receivers and activities share a class, but point to different get methods
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index ad70345..7cfe499 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -179,12 +179,15 @@
import android.content.pm.PackageManager.ModuleInfoFlags;
import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageManagerInternal.PackageListObserver;
+import android.content.pm.PackageManagerInternal.PrivateResolveFlags;
import android.content.pm.PackageParser;
import android.content.pm.PackageParser.PackageLite;
import android.content.pm.PackageParser.PackageParserException;
import android.content.pm.PackageParser.ParseFlags;
import android.content.pm.PackageParser.SigningDetails;
import android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion;
+import android.content.pm.PackagePartitions;
+import android.content.pm.PackagePartitions.SystemPartition;
import android.content.pm.PackageStats;
import android.content.pm.PackageUserState;
import android.content.pm.ParceledListSlice;
@@ -305,6 +308,7 @@
import com.android.internal.app.ResolverActivity;
import com.android.internal.content.NativeLibraryHelper;
import com.android.internal.content.PackageHelper;
+import com.android.internal.content.om.OverlayConfig;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.os.SomeArgs;
import com.android.internal.os.Zygote;
@@ -792,22 +796,12 @@
* specificity (the more generic, the earlier in the list a partition appears).
*/
@VisibleForTesting(visibility = Visibility.PRIVATE)
- public static final List<SystemPartition> SYSTEM_PARTITIONS = Collections.unmodifiableList(
- Arrays.asList(
- new SystemPartition(Environment.getRootDirectory(), 0 /* scanFlag */,
- false /* hasOverlays */),
- new SystemPartition(Environment.getVendorDirectory(), SCAN_AS_VENDOR,
- true /* hasOverlays */),
- new SystemPartition(Environment.getOdmDirectory(), SCAN_AS_ODM,
- true /* hasOverlays */),
- new SystemPartition(Environment.getOemDirectory(), SCAN_AS_OEM,
- true /* hasOverlays */),
- new SystemPartition(Environment.getProductDirectory(), SCAN_AS_PRODUCT,
- true /* hasOverlays */),
- new SystemPartition(Environment.getSystemExtDirectory(), SCAN_AS_SYSTEM_EXT,
- true /* hasOverlays */)));
+ public static final List<ScanPartition> SYSTEM_PARTITIONS = Collections.unmodifiableList(
+ PackagePartitions.getOrderedPartitions(ScanPartition::new));
- private final List<SystemPartition> mDirsToScanAsSystem;
+ private final List<ScanPartition> mDirsToScanAsSystem;
+
+ private final OverlayConfig mOverlayConfig;
/**
* Unit tests will instantiate, extend and/or mock to mock dependencies / behaviors.
@@ -2588,66 +2582,44 @@
}
}
- @VisibleForTesting(visibility = Visibility.PRIVATE)
- public static class SystemPartition {
- public final File folder;
+ @VisibleForTesting
+ public static class ScanPartition extends SystemPartition {
+ @ScanFlags
public final int scanFlag;
- public final File appFolder;
- @Nullable
- public final File privAppFolder;
- @Nullable
- public final File overlayFolder;
-
- private static boolean shouldScanPrivApps(@ScanFlags int scanFlags) {
- if ((scanFlags & SCAN_AS_OEM) != 0) {
- return false;
- }
- if (scanFlags == 0) { // /system partition
- return true;
- }
- if ((scanFlags
- & (SCAN_AS_VENDOR | SCAN_AS_ODM | SCAN_AS_PRODUCT | SCAN_AS_SYSTEM_EXT)) != 0) {
- return true;
- }
- if ((scanFlags & SCAN_AS_APK_IN_APEX) != 0) {
- return true;
- }
- return false;
+ public ScanPartition(@NonNull SystemPartition partition) {
+ super(partition);
+ scanFlag = scanFlagForPartition(partition);
}
- private SystemPartition(File folder, int scanFlag, boolean hasOverlays) {
- this.folder = folder;
- this.scanFlag = scanFlag;
- this.appFolder = toCanonical(new File(folder, "app"));
- this.privAppFolder = shouldScanPrivApps(scanFlag)
- ? toCanonical(new File(folder, "priv-app"))
- : null;
- this.overlayFolder = hasOverlays ? toCanonical(new File(folder, "overlay")) : null;
+ /**
+ * Creates a partition containing the same folders as the original partition but with a
+ * different root folder. The new partition will include the scan flags of the original
+ * partition along with any specified additional scan flags.
+ */
+ public ScanPartition(@NonNull File folder, @NonNull ScanPartition original,
+ @ScanFlags int additionalScanFlag) {
+ super(folder, original);
+ this.scanFlag = original.scanFlag | additionalScanFlag;
}
- public boolean containsPrivApp(File scanFile) {
- return FileUtils.contains(privAppFolder, scanFile);
- }
-
- public boolean containsApp(File scanFile) {
- return FileUtils.contains(appFolder, scanFile);
- }
-
- public boolean containsPath(String path) {
- return path.startsWith(folder.getPath() + "/");
- }
-
- public boolean containsPrivPath(String path) {
- return privAppFolder != null && path.startsWith(privAppFolder.getPath() + "/");
- }
-
- private static File toCanonical(File dir) {
- try {
- return dir.getCanonicalFile();
- } catch (IOException e) {
- // failed to look up canonical path, continue with original one
- return dir;
+ private static int scanFlagForPartition(PackagePartitions.SystemPartition partition) {
+ switch (partition.type) {
+ case PackagePartitions.PARTITION_SYSTEM:
+ return 0;
+ case PackagePartitions.PARTITION_VENDOR:
+ return SCAN_AS_VENDOR;
+ case PackagePartitions.PARTITION_ODM:
+ return SCAN_AS_ODM;
+ case PackagePartitions.PARTITION_OEM:
+ return SCAN_AS_OEM;
+ case PackagePartitions.PARTITION_PRODUCT:
+ return SCAN_AS_PRODUCT;
+ case PackagePartitions.PARTITION_SYSTEM_EXT:
+ return SCAN_AS_SYSTEM_EXT;
+ default:
+ throw new IllegalStateException("Unable to determine scan flag for "
+ + partition.folder);
}
}
}
@@ -2751,7 +2723,7 @@
mDirsToScanAsSystem = new ArrayList<>();
mDirsToScanAsSystem.addAll(SYSTEM_PARTITIONS);
mDirsToScanAsSystem.addAll(mApexManager.getActiveApexInfos().stream()
- .map(ai -> resolveApexToSystemPartition(ai))
+ .map(PackageManagerService::resolveApexToScanPartition)
.filter(Objects::nonNull).collect(Collectors.toList()));
Slog.d(TAG,
"Directories scanned as system partitions: [" + mDirsToScanAsSystem.stream().map(
@@ -2900,11 +2872,11 @@
// For security and version matching reason, only consider overlay packages if they
// reside in the right directory.
for (int i = mDirsToScanAsSystem.size() - 1; i >= 0; i--) {
- final SystemPartition partition = mDirsToScanAsSystem.get(i);
- if (partition.overlayFolder == null) {
+ final ScanPartition partition = mDirsToScanAsSystem.get(i);
+ if (partition.getOverlayFolder() == null) {
continue;
}
- scanDirTracedLI(partition.overlayFolder, systemParseFlags,
+ scanDirTracedLI(partition.getOverlayFolder(), systemParseFlags,
systemScanFlags | partition.scanFlag, 0,
packageParser, executorService);
}
@@ -2917,17 +2889,20 @@
"Failed to load frameworks package; check log for warnings");
}
for (int i = 0, size = mDirsToScanAsSystem.size(); i < size; i++) {
- final SystemPartition partition = mDirsToScanAsSystem.get(i);
- if (partition.privAppFolder != null) {
- scanDirTracedLI(partition.privAppFolder, systemParseFlags,
+ final ScanPartition partition = mDirsToScanAsSystem.get(i);
+ if (partition.getPrivAppFolder() != null) {
+ scanDirTracedLI(partition.getPrivAppFolder(), systemParseFlags,
systemScanFlags | SCAN_AS_PRIVILEGED | partition.scanFlag, 0,
packageParser, executorService);
}
- scanDirTracedLI(partition.appFolder, systemParseFlags,
+ scanDirTracedLI(partition.getAppFolder(), systemParseFlags,
systemScanFlags | partition.scanFlag, 0,
packageParser, executorService);
}
+ // Parse overlay configuration files to set default enable state, mutability, and
+ // priority of system overlays.
+ mOverlayConfig = OverlayConfig.initializeSystemInstance(mPmInternal::forEachPackage);
// Prune any system packages that no longer exist.
final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<>();
@@ -3105,7 +3080,7 @@
@ParseFlags int reparseFlags = 0;
@ScanFlags int rescanFlags = 0;
for (int i1 = 0, size = mDirsToScanAsSystem.size(); i1 < size; i1++) {
- SystemPartition partition = mDirsToScanAsSystem.get(i1);
+ final ScanPartition partition = mDirsToScanAsSystem.get(i1);
if (partition.containsPrivApp(scanFile)) {
reparseFlags = systemParseFlags;
rescanFlags = systemScanFlags | SCAN_AS_PRIVILEGED
@@ -6128,8 +6103,8 @@
@Override
public ResolveInfo resolveIntent(Intent intent, String resolvedType,
int flags, int userId) {
- return resolveIntentInternal(intent, resolvedType, flags, userId, false,
- Binder.getCallingUid());
+ return resolveIntentInternal(intent, resolvedType, flags, 0 /*privateResolveFlags*/,
+ userId, false, Binder.getCallingUid());
}
/**
@@ -6137,8 +6112,9 @@
* However, if {@code resolveForStart} is {@code true}, all instant apps are visible
* since we need to allow the system to start any installed application.
*/
- private ResolveInfo resolveIntentInternal(Intent intent, String resolvedType,
- int flags, int userId, boolean resolveForStart, int filterCallingUid) {
+ private ResolveInfo resolveIntentInternal(Intent intent, String resolvedType, int flags,
+ @PrivateResolveFlags int privateResolveFlags, int userId, boolean resolveForStart,
+ int filterCallingUid) {
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveIntent");
@@ -6150,11 +6126,13 @@
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "queryIntentActivities");
final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType,
- flags, filterCallingUid, userId, resolveForStart, true /*allowDynamicSplits*/);
+ flags, privateResolveFlags, filterCallingUid, userId, resolveForStart,
+ true /*allowDynamicSplits*/);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
final ResolveInfo bestChoice =
- chooseBestActivity(intent, resolvedType, flags, query, userId);
+ chooseBestActivity(
+ intent, resolvedType, flags, privateResolveFlags, query, userId);
return bestChoice;
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
@@ -6312,7 +6290,7 @@
}
private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
- int flags, List<ResolveInfo> query, int userId) {
+ int flags, int privateResolveFlags, List<ResolveInfo> query, int userId) {
if (query != null) {
final int N = query.size();
if (N == 1) {
@@ -6354,6 +6332,10 @@
}
}
}
+ if ((privateResolveFlags
+ & PackageManagerInternal.RESOLVE_NON_RESOLVER_ONLY) != 0) {
+ return null;
+ }
ri = new ResolveInfo(mResolveInfo);
ri.activityInfo = new ActivityInfo(ri.activityInfo);
ri.activityInfo.labelRes = ResolverActivity.getLabelRes(intent.getAction());
@@ -6767,13 +6749,13 @@
private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
String resolvedType, int flags, int userId) {
return queryIntentActivitiesInternal(
- intent, resolvedType, flags, Binder.getCallingUid(), userId,
- false /*resolveForStart*/, true /*allowDynamicSplits*/);
+ intent, resolvedType, flags, 0 /*privateResolveFlags*/, Binder.getCallingUid(),
+ userId, false /*resolveForStart*/, true /*allowDynamicSplits*/);
}
private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
- String resolvedType, int flags, int filterCallingUid, int userId,
- boolean resolveForStart, boolean allowDynamicSplits) {
+ String resolvedType, int flags, @PrivateResolveFlags int privateResolveFlags,
+ int filterCallingUid, int userId, boolean resolveForStart, boolean allowDynamicSplits) {
if (!mUserManager.exists(userId)) return Collections.emptyList();
final String instantAppPkgName = getInstantAppPackageName(filterCallingUid);
mPermissionManager.enforceCrossUserPermission(Binder.getCallingUid(), userId,
@@ -6858,7 +6840,7 @@
// Check for results in the current profile.
result = filterIfNotSystemUser(mComponentResolver.queryActivities(
- intent, resolvedType, flags, userId), userId);
+ intent, resolvedType, flags, privateResolveFlags, userId), userId);
addInstant = isInstantAppResolutionAllowed(intent, result, userId,
false /*skipPackageCheck*/);
// Check for cross profile results.
@@ -6957,7 +6939,7 @@
| PackageManager.GET_RESOLVED_FILTER
| PackageManager.MATCH_INSTANT
| PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY,
- userId);
+ 0, userId);
for (int i = instantApps.size() - 1; i >= 0; --i) {
final ResolveInfo info = instantApps.get(i);
final String packageName = info.activityInfo.packageName;
@@ -7061,7 +7043,7 @@
return null;
}
List<ResolveInfo> resultTargetUser = mComponentResolver.queryActivities(intent,
- resolvedType, flags, parentUserId);
+ resolvedType, flags, 0, parentUserId);
if (resultTargetUser == null || resultTargetUser.isEmpty()) {
return null;
@@ -7246,8 +7228,9 @@
failureActivityIntent.setPackage(packageName);
// IMPORTANT: disallow dynamic splits to avoid an infinite loop
final List<ResolveInfo> result = queryIntentActivitiesInternal(
- failureActivityIntent, null /*resolvedType*/, 0 /*flags*/, filterCallingUid, userId,
- false /*resolveForStart*/, false /*allowDynamicSplits*/);
+ failureActivityIntent, null /*resolvedType*/, 0 /*flags*/,
+ 0 /*privateResolveFlags*/, filterCallingUid, userId, false /*resolveForStart*/,
+ false /*allowDynamicSplits*/);
final int NR = result.size();
if (NR > 0) {
for (int i = 0; i < NR; i++) {
@@ -7502,7 +7485,7 @@
String resolvedType, int flags, int sourceUserId) {
int targetUserId = filter.getTargetUserId();
List<ResolveInfo> resultTargetUser = mComponentResolver.queryActivities(intent,
- resolvedType, flags, targetUserId);
+ resolvedType, flags, 0, targetUserId);
if (resultTargetUser != null && isUserEnabled(targetUserId)) {
// If all the matches in the target profile are suspended, return null.
for (int i = resultTargetUser.size() - 1; i >= 0; i--) {
@@ -11570,50 +11553,17 @@
// We are scanning a system overlay. This can be the first scan of the
// system/vendor/oem partition, or an update to the system overlay.
if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
- // This must be an update to a system overlay.
- final PackageSetting previousPkg = assertNotNull(
- mSettings.getPackageLPr(pkg.getPackageName()),
- "previous package state not present");
-
- // previousPkg.pkg may be null: the package will be not be scanned if the
- // package manager knows there is a newer version on /data.
- // TODO[b/79435695]: Find a better way to keep track of the "static"
- // property for RROs instead of having to parse packages on /system
- AndroidPackage ppkg = previousPkg.pkg;
- if (ppkg == null) {
- try {
- final PackageParser pp = new PackageParser();
- // TODO(b/135203078): Do we really need to parse here? Maybe use
- // a shortened path?
- ppkg = pp.parseParsedPackage(previousPkg.codePath,
- parseFlags | PackageParser.PARSE_IS_SYSTEM_DIR,
- false)
- .hideAsFinal();
- } catch (PackageParserException e) {
- Slog.w(TAG, "failed to parse " + previousPkg.codePath, e);
- }
- }
-
- // Static overlays cannot be updated.
- if (ppkg != null && ppkg.isOverlayIsStatic()) {
+ // This must be an update to a system overlay. Immutable overlays cannot be
+ // upgraded.
+ Objects.requireNonNull(mOverlayConfig,
+ "Parsing non-system dir before overlay configs are initialized");
+ if (!mOverlayConfig.isMutable(pkg.getPackageName())) {
throw new PackageManagerException("Overlay "
+ pkg.getPackageName()
+ " is static and cannot be upgraded.");
- // Non-static overlays cannot be converted to static overlays.
- } else if (pkg.isOverlayIsStatic()) {
- throw new PackageManagerException("Overlay "
- + pkg.getPackageName()
- + " cannot be upgraded into a static overlay.");
}
}
} else {
- // The overlay is a non-system overlay. Non-system overlays cannot be static.
- if (pkg.isOverlayIsStatic()) {
- throw new PackageManagerException("Overlay "
- + pkg.getPackageName()
- + " is static but not pre-installed.");
- }
-
// A non-preloaded overlay packages must have targetSdkVersion >= Q, or be
// signed with the platform certificate. Check this in increasing order of
// computational cost.
@@ -17971,14 +17921,13 @@
}
}
- private static @Nullable SystemPartition resolveApexToSystemPartition(
+ private static @Nullable ScanPartition resolveApexToScanPartition(
ApexManager.ActiveApexInfo apexInfo) {
for (int i = 0, size = SYSTEM_PARTITIONS.size(); i < size; i++) {
- SystemPartition sp = SYSTEM_PARTITIONS.get(i);
+ ScanPartition sp = SYSTEM_PARTITIONS.get(i);
if (apexInfo.preInstalledApexPath.getAbsolutePath().startsWith(
sp.folder.getAbsolutePath())) {
- return new SystemPartition(apexInfo.apexDirectory,
- sp.scanFlag | SCAN_AS_APK_IN_APEX, false /* hasOverlays */);
+ return new ScanPartition(apexInfo.apexDirectory, sp, SCAN_AS_APK_IN_APEX);
}
}
return null;
@@ -18079,7 +18028,7 @@
| PackageParser.PARSE_IS_SYSTEM_DIR;
@ScanFlags int scanFlags = SCAN_AS_SYSTEM;
for (int i = 0, size = mDirsToScanAsSystem.size(); i < size; i++) {
- SystemPartition partition = mDirsToScanAsSystem.get(i);
+ ScanPartition partition = mDirsToScanAsSystem.get(i);
if (partition.containsPath(codePathString)) {
scanFlags |= partition.scanFlag;
if (partition.containsPrivPath(codePathString)) {
@@ -23324,7 +23273,7 @@
public List<ResolveInfo> queryIntentActivities(
Intent intent, String resolvedType, int flags, int filterCallingUid, int userId) {
return PackageManagerService.this
- .queryIntentActivitiesInternal(intent, resolvedType, flags, filterCallingUid,
+ .queryIntentActivitiesInternal(intent, resolvedType, flags, 0, filterCallingUid,
userId, false /*resolveForStart*/, true /*allowDynamicSplits*/);
}
@@ -23610,9 +23559,11 @@
@Override
public ResolveInfo resolveIntent(Intent intent, String resolvedType,
- int flags, int userId, boolean resolveForStart, int filterCallingUid) {
+ int flags, int privateResolveFlags, int userId, boolean resolveForStart,
+ int filterCallingUid) {
return resolveIntentInternal(
- intent, resolvedType, flags, userId, resolveForStart, filterCallingUid);
+ intent, resolvedType, flags, privateResolveFlags, userId, resolveForStart,
+ filterCallingUid);
}
@Override
diff --git a/services/core/java/com/android/server/pm/TEST_MAPPING b/services/core/java/com/android/server/pm/TEST_MAPPING
index 81c7471..97f9548 100644
--- a/services/core/java/com/android/server/pm/TEST_MAPPING
+++ b/services/core/java/com/android/server/pm/TEST_MAPPING
@@ -13,6 +13,9 @@
"name": "AppEnumerationTests"
},
{
+ "name": "CtsMatchFlagTestCases"
+ },
+ {
"name": "FrameworksServicesTests",
"options": [
{
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index b61a2ce..4cc4851 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -1723,10 +1723,9 @@
// The snapshot of home is only used once because it won't be updated while screen
// is on (see {@link TaskSnapshotController#screenTurningOff}).
mWmService.mTaskSnapshotController.removeSnapshotCache(task.mTaskId);
- // TODO(b/9684093): Use more general condition to specify the case.
- if (mDisplayContent.mAppTransition
- .getAppTransition() != WindowManager.TRANSIT_KEYGUARD_GOING_AWAY) {
- // Only use snapshot of home as starting window when unlocking.
+ if ((mDisplayContent.mAppTransition.getTransitFlags()
+ & WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION) == 0) {
+ // Only use snapshot of home as starting window when unlocking directly.
return false;
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index a582f21..7720f7f 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -108,6 +108,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.content.res.Configuration;
@@ -755,6 +756,14 @@
|| (intent.getFlags() & Intent.FLAG_ACTIVITY_MATCH_EXTERNAL) != 0) {
modifiedFlags |= PackageManager.MATCH_INSTANT;
}
+ int privateResolveFlags = 0;
+ if (intent.isWebIntent()
+ && (intent.getFlags() & Intent.FLAG_ACTIVITY_REQUIRE_NON_BROWSER) != 0) {
+ privateResolveFlags |= PackageManagerInternal.RESOLVE_NON_BROWSER_ONLY;
+ }
+ if ((intent.getFlags() & Intent.FLAG_ACTIVITY_REQUIRE_DEFAULT) != 0) {
+ privateResolveFlags |= PackageManagerInternal.RESOLVE_NON_RESOLVER_ONLY;
+ }
// In order to allow cross-profile lookup, we clear the calling identity here.
// Note the binder identity won't affect the result, but filterCallingUid will.
@@ -764,7 +773,8 @@
final long token = Binder.clearCallingIdentity();
try {
return mService.getPackageManagerInternalLocked().resolveIntent(
- intent, resolvedType, modifiedFlags, userId, true, filterCallingUid);
+ intent, resolvedType, modifiedFlags, privateResolveFlags, userId, true,
+ filterCallingUid);
} finally {
Binder.restoreCallingIdentity(token);
}
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index a96e3a61..e443fe4 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -1183,6 +1183,11 @@
if (transit == TRANSIT_PREVIEW_DONE) {
if (win.hasAppShownWindows()) {
+ if (win.isActivityTypeHome()) {
+ // Dismiss the starting window as soon as possible to avoid the crossfade out
+ // with old content because home is easier to have different UI states.
+ return ANIMATION_NONE;
+ }
if (DEBUG_ANIM) Slog.i(TAG, "**** STARTING EXIT");
return R.anim.app_starting_exit;
}
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 10d6823..d8091ed 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -559,8 +559,10 @@
}
});
// Allow taking snapshot of home when turning screen off to reduce the delay of
- // unlocking/waking to home.
- snapshotTasks(mTmpTasks, true /* allowSnapshotHome */);
+ // waking from secure lock to home.
+ final boolean allowSnapshotHome =
+ mService.mPolicy.isKeyguardSecure(mService.mCurrentUserId);
+ snapshotTasks(mTmpTasks, allowSnapshotHome);
}
} finally {
listener.onScreenOff();
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 68504bd..2a7d551 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1169,9 +1169,10 @@
mAnimator = new WindowAnimator(this);
mRoot = new RootWindowContainer(this);
- mUseBLAST = DeviceConfig.getBoolean(
+ mUseBLAST = SystemProperties.getBoolean(
+ String.join(".", "persist.device_config",
DeviceConfig.NAMESPACE_WINDOW_MANAGER_NATIVE_BOOT,
- WM_USE_BLAST_ADAPTER_FLAG, false);
+ WM_USE_BLAST_ADAPTER_FLAG), false);
mWindowPlacerLocked = new WindowSurfacePlacer(this);
mTaskSnapshotController = new TaskSnapshotController(this);
diff --git a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
index 407f67e..44f4ccf 100644
--- a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
@@ -24,6 +24,7 @@
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertThrows;
+import android.app.compat.ChangeIdStateCache;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
@@ -74,6 +75,7 @@
// Assume userdebug/eng non-final build
when(mBuildClassifier.isDebuggableBuild()).thenReturn(true);
when(mBuildClassifier.isFinalBuild()).thenReturn(false);
+ ChangeIdStateCache.disable();
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java b/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java
index 4a686ee..53b90f2 100644
--- a/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java
+++ b/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java
@@ -62,6 +62,7 @@
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
+ android.app.compat.ChangeIdStateCache.disable();
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mPackageManager.getPackageUid(eq(PACKAGE_NAME), eq(0))).thenThrow(
new PackageManager.NameNotFoundException());
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java
new file mode 100644
index 0000000..c4fea77
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java
@@ -0,0 +1,188 @@
+/*
+ * 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.server.om;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.content.om.OverlayInfo;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceImplTestsBase {
+
+ private static final String OVERLAY = "com.dummy.overlay";
+ private static final String TARGET = "com.dummy.target";
+ private static final int USER = 0;
+
+ private static final String OVERLAY2 = OVERLAY + "2";
+
+ @Test
+ public void testUpdateOverlaysForUser() {
+ final OverlayManagerServiceImpl impl = getImpl();
+ installTargetPackage(TARGET, USER);
+ installTargetPackage("some.other.target", USER);
+ installOverlayPackage(OVERLAY, TARGET, USER);
+
+ // do nothing, expect no change
+ final List<String> a = impl.updateOverlaysForUser(USER);
+ assertEquals(1, a.size());
+ assertTrue(a.contains(TARGET));
+
+ // upgrade overlay, keep target
+ beginUpgradeOverlayPackage(OVERLAY, USER);
+ endUpgradeOverlayPackage(OVERLAY, TARGET, USER);
+
+ final List<String> b = impl.updateOverlaysForUser(USER);
+ assertEquals(1, b.size());
+ assertTrue(b.contains(TARGET));
+
+ // do nothing, expect no change
+ final List<String> c = impl.updateOverlaysForUser(USER);
+ assertEquals(1, c.size());
+ assertTrue(c.contains(TARGET));
+
+ // upgrade overlay, switch to new target
+ addOverlayPackage(OVERLAY, "some.other.target", USER, true, false, 0);
+ final List<String> d = impl.updateOverlaysForUser(USER);
+ assertEquals(2, d.size());
+ assertTrue(d.containsAll(Arrays.asList(TARGET, "some.other.target")));
+
+ // do nothing, expect no change
+ final List<String> f = impl.updateOverlaysForUser(USER);
+ assertEquals(1, f.size());
+ assertTrue(f.contains("some.other.target"));
+ }
+
+ @Test
+ public void testImmutableEnabledChange() {
+ final OverlayManagerServiceImpl impl = getImpl();
+ installTargetPackage(TARGET, USER);
+
+ addOverlayPackage(OVERLAY, TARGET, USER, false, false, 0);
+ impl.updateOverlaysForUser(USER);
+ final OverlayInfo o1 = impl.getOverlayInfo(OVERLAY, USER);
+ assertNotNull(o1);
+ assertFalse(o1.isEnabled());
+ assertFalse(o1.isMutable);
+
+ addOverlayPackage(OVERLAY, TARGET, USER, false, true, 0);
+ impl.updateOverlaysForUser(USER);
+ final OverlayInfo o2 = impl.getOverlayInfo(OVERLAY, USER);
+ assertNotNull(o2);
+ assertTrue(o2.isEnabled());
+ assertFalse(o2.isMutable);
+
+ addOverlayPackage(OVERLAY, TARGET, USER, false, false, 0);
+ impl.updateOverlaysForUser(USER);
+ final OverlayInfo o3 = impl.getOverlayInfo(OVERLAY, USER);
+ assertNotNull(o3);
+ assertFalse(o3.isEnabled());
+ assertFalse(o3.isMutable);
+ }
+
+ @Test
+ public void testMutableEnabledChangeHasNoEffect() {
+ final OverlayManagerServiceImpl impl = getImpl();
+ installTargetPackage(TARGET, USER);
+
+ addOverlayPackage(OVERLAY, TARGET, USER, true, false, 0);
+ impl.updateOverlaysForUser(USER);
+ final OverlayInfo o1 = impl.getOverlayInfo(OVERLAY, USER);
+ assertNotNull(o1);
+ assertFalse(o1.isEnabled());
+ assertTrue(o1.isMutable);
+
+ addOverlayPackage(OVERLAY, TARGET, USER, true, true, 0);
+ impl.updateOverlaysForUser(USER);
+ final OverlayInfo o2 = impl.getOverlayInfo(OVERLAY, USER);
+ assertNotNull(o2);
+ assertFalse(o2.isEnabled());
+ assertTrue(o2.isMutable);
+
+ addOverlayPackage(OVERLAY, TARGET, USER, true, false, 0);
+ impl.updateOverlaysForUser(USER);
+ final OverlayInfo o3 = impl.getOverlayInfo(OVERLAY, USER);
+ assertNotNull(o3);
+ assertFalse(o3.isEnabled());
+ assertTrue(o3.isMutable);
+ }
+
+ @Test
+ public void testMutabilityChange() {
+ final OverlayManagerServiceImpl impl = getImpl();
+ installTargetPackage(TARGET, USER);
+
+ addOverlayPackage(OVERLAY, TARGET, USER, false, true, 0);
+ impl.updateOverlaysForUser(USER);
+ final OverlayInfo o1 = impl.getOverlayInfo(OVERLAY, USER);
+ assertNotNull(o1);
+ assertTrue(o1.isEnabled());
+ assertFalse(o1.isMutable);
+
+ addOverlayPackage(OVERLAY, TARGET, USER, true, false, 0);
+ impl.updateOverlaysForUser(USER);
+ final OverlayInfo o2 = impl.getOverlayInfo(OVERLAY, USER);
+ assertNotNull(o2);
+ assertFalse(o2.isEnabled());
+ assertTrue(o2.isMutable);
+
+ addOverlayPackage(OVERLAY, TARGET, USER, false, false, 0);
+ impl.updateOverlaysForUser(USER);
+ final OverlayInfo o3 = impl.getOverlayInfo(OVERLAY, USER);
+ assertNotNull(o3);
+ assertFalse(o3.isEnabled());
+ assertFalse(o3.isMutable);
+ }
+
+ @Test
+ public void testPriorityChange() {
+ final OverlayManagerServiceImpl impl = getImpl();
+ installTargetPackage(TARGET, USER);
+
+ addOverlayPackage(OVERLAY, TARGET, USER, false, true, 0);
+ addOverlayPackage(OVERLAY2, TARGET, USER, false, true, 1);
+ impl.updateOverlaysForUser(USER);
+
+ final OverlayInfo o1 = impl.getOverlayInfo(OVERLAY, USER);
+ final OverlayInfo o2 = impl.getOverlayInfo(OVERLAY2, USER);
+ assertNotNull(o1);
+ assertNotNull(o2);
+ assertEquals(0, o1.priority);
+ assertEquals(1, o2.priority);
+
+ addOverlayPackage(OVERLAY, TARGET, USER, false, true, 1);
+ addOverlayPackage(OVERLAY2, TARGET, USER, false, true, 0);
+ impl.updateOverlaysForUser(USER);
+
+ final OverlayInfo o3 = impl.getOverlayInfo(OVERLAY, USER);
+ final OverlayInfo o4 = impl.getOverlayInfo(OVERLAY2, USER);
+ assertNotNull(o3);
+ assertNotNull(o4);
+ assertEquals(1, o3.priority);
+ assertEquals(0, o4.priority);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java
index c566dfc..a428a97 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java
@@ -24,6 +24,9 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import android.annotation.NonNull;
import android.content.om.OverlayInfo;
@@ -33,6 +36,8 @@
import androidx.test.runner.AndroidJUnit4;
+import com.android.internal.content.om.OverlayConfig;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -45,10 +50,7 @@
import java.util.Set;
@RunWith(AndroidJUnit4.class)
-public class OverlayManagerServiceImplTests {
- private OverlayManagerServiceImpl mImpl;
- private DummyDeviceState mState;
- private DummyListener mListener;
+public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTestsBase {
private static final String OVERLAY = "com.dummy.overlay";
private static final String TARGET = "com.dummy.target";
@@ -61,25 +63,14 @@
private static final String OVERLAY3 = OVERLAY + "3";
private static final int USER3 = USER2 + 1;
-
- @Before
- public void setUp() throws Exception {
- mState = new DummyDeviceState();
- mListener = new DummyListener();
- DummyPackageManagerHelper pmh = new DummyPackageManagerHelper(mState);
- mImpl = new OverlayManagerServiceImpl(pmh,
- new DummyIdmapManager(mState, pmh),
- new OverlayManagerSettings(),
- new String[0],
- mListener);
- }
-
// tests: basics
@Test
public void testGetOverlayInfo() throws Exception {
- installOverlayPackage(OVERLAY, TARGET, USER, false);
- final OverlayInfo oi = mImpl.getOverlayInfo(OVERLAY, USER);
+ installOverlayPackage(OVERLAY, TARGET, USER);
+
+ final OverlayManagerServiceImpl impl = getImpl();
+ final OverlayInfo oi = impl.getOverlayInfo(OVERLAY, USER);
assertNotNull(oi);
assertEquals(oi.packageName, OVERLAY);
assertEquals(oi.targetPackageName, TARGET);
@@ -88,87 +79,91 @@
@Test
public void testGetOverlayInfosForTarget() throws Exception {
- installOverlayPackage(OVERLAY, TARGET, USER, false);
- installOverlayPackage(OVERLAY2, TARGET, USER, false);
+ installOverlayPackage(OVERLAY, TARGET, USER);
+ installOverlayPackage(OVERLAY2, TARGET, USER);
+ installOverlayPackage(OVERLAY3, TARGET, USER2);
- installOverlayPackage(OVERLAY3, TARGET, USER2, false);
-
- final List<OverlayInfo> ois = mImpl.getOverlayInfosForTarget(TARGET, USER);
+ final OverlayManagerServiceImpl impl = getImpl();
+ final List<OverlayInfo> ois = impl.getOverlayInfosForTarget(TARGET, USER);
assertEquals(ois.size(), 2);
- assertTrue(ois.contains(mImpl.getOverlayInfo(OVERLAY, USER)));
- assertTrue(ois.contains(mImpl.getOverlayInfo(OVERLAY2, USER)));
+ assertTrue(ois.contains(impl.getOverlayInfo(OVERLAY, USER)));
+ assertTrue(ois.contains(impl.getOverlayInfo(OVERLAY2, USER)));
- final List<OverlayInfo> ois2 = mImpl.getOverlayInfosForTarget(TARGET, USER2);
+ final List<OverlayInfo> ois2 = impl.getOverlayInfosForTarget(TARGET, USER2);
assertEquals(ois2.size(), 1);
- assertTrue(ois2.contains(mImpl.getOverlayInfo(OVERLAY3, USER2)));
+ assertTrue(ois2.contains(impl.getOverlayInfo(OVERLAY3, USER2)));
- final List<OverlayInfo> ois3 = mImpl.getOverlayInfosForTarget(TARGET, USER3);
+ final List<OverlayInfo> ois3 = impl.getOverlayInfosForTarget(TARGET, USER3);
assertNotNull(ois3);
assertEquals(ois3.size(), 0);
- final List<OverlayInfo> ois4 = mImpl.getOverlayInfosForTarget("no.such.overlay", USER);
+ final List<OverlayInfo> ois4 = impl.getOverlayInfosForTarget("no.such.overlay", USER);
assertNotNull(ois4);
assertEquals(ois4.size(), 0);
}
@Test
public void testGetOverlayInfosForUser() throws Exception {
- installOverlayPackage(OVERLAY, TARGET, USER, false);
- installOverlayPackage(OVERLAY2, TARGET, USER, false);
- installOverlayPackage(OVERLAY3, TARGET2, USER, false);
+ installTargetPackage(TARGET, USER);
+ installOverlayPackage(OVERLAY, TARGET, USER);
+ installOverlayPackage(OVERLAY2, TARGET, USER);
+ installOverlayPackage(OVERLAY3, TARGET2, USER);
- final Map<String, List<OverlayInfo>> everything = mImpl.getOverlaysForUser(USER);
+ final OverlayManagerServiceImpl impl = getImpl();
+ final Map<String, List<OverlayInfo>> everything = impl.getOverlaysForUser(USER);
assertEquals(everything.size(), 2);
final List<OverlayInfo> ois = everything.get(TARGET);
assertNotNull(ois);
assertEquals(ois.size(), 2);
- assertTrue(ois.contains(mImpl.getOverlayInfo(OVERLAY, USER)));
- assertTrue(ois.contains(mImpl.getOverlayInfo(OVERLAY2, USER)));
+ assertTrue(ois.contains(impl.getOverlayInfo(OVERLAY, USER)));
+ assertTrue(ois.contains(impl.getOverlayInfo(OVERLAY2, USER)));
final List<OverlayInfo> ois2 = everything.get(TARGET2);
assertNotNull(ois2);
assertEquals(ois2.size(), 1);
- assertTrue(ois2.contains(mImpl.getOverlayInfo(OVERLAY3, USER)));
+ assertTrue(ois2.contains(impl.getOverlayInfo(OVERLAY3, USER)));
- final Map<String, List<OverlayInfo>> everything2 = mImpl.getOverlaysForUser(USER2);
+ final Map<String, List<OverlayInfo>> everything2 = impl.getOverlaysForUser(USER2);
assertNotNull(everything2);
assertEquals(everything2.size(), 0);
}
@Test
public void testPriority() throws Exception {
- installOverlayPackage(OVERLAY, TARGET, USER, false);
- installOverlayPackage(OVERLAY2, TARGET, USER, false);
- installOverlayPackage(OVERLAY3, TARGET, USER, false);
+ installOverlayPackage(OVERLAY, TARGET, USER);
+ installOverlayPackage(OVERLAY2, TARGET, USER);
+ installOverlayPackage(OVERLAY3, TARGET, USER);
- final OverlayInfo o1 = mImpl.getOverlayInfo(OVERLAY, USER);
- final OverlayInfo o2 = mImpl.getOverlayInfo(OVERLAY2, USER);
- final OverlayInfo o3 = mImpl.getOverlayInfo(OVERLAY3, USER);
+ final OverlayManagerServiceImpl impl = getImpl();
+ final OverlayInfo o1 = impl.getOverlayInfo(OVERLAY, USER);
+ final OverlayInfo o2 = impl.getOverlayInfo(OVERLAY2, USER);
+ final OverlayInfo o3 = impl.getOverlayInfo(OVERLAY3, USER);
assertOverlayInfoList(TARGET, USER, o1, o2, o3);
- assertTrue(mImpl.setLowestPriority(OVERLAY3, USER));
+ assertTrue(impl.setLowestPriority(OVERLAY3, USER));
assertOverlayInfoList(TARGET, USER, o3, o1, o2);
- assertTrue(mImpl.setHighestPriority(OVERLAY3, USER));
+ assertTrue(impl.setHighestPriority(OVERLAY3, USER));
assertOverlayInfoList(TARGET, USER, o1, o2, o3);
- assertTrue(mImpl.setPriority(OVERLAY, OVERLAY2, USER));
+ assertTrue(impl.setPriority(OVERLAY, OVERLAY2, USER));
assertOverlayInfoList(TARGET, USER, o2, o1, o3);
}
@Test
public void testOverlayInfoStateTransitions() throws Exception {
- assertNull(mImpl.getOverlayInfo(OVERLAY, USER));
+ final OverlayManagerServiceImpl impl = getImpl();
+ assertNull(impl.getOverlayInfo(OVERLAY, USER));
- installOverlayPackage(OVERLAY, TARGET, USER, true);
+ installOverlayPackage(OVERLAY, TARGET, USER);
assertState(STATE_MISSING_TARGET, OVERLAY, USER);
installTargetPackage(TARGET, USER);
assertState(STATE_DISABLED, OVERLAY, USER);
- mImpl.setEnabled(OVERLAY, true, USER);
+ impl.setEnabled(OVERLAY, true, USER);
assertState(STATE_ENABLED, OVERLAY, USER);
// target upgrades do not change the state of the overlay
@@ -186,319 +181,48 @@
}
@Test
- public void testUpdateOverlaysForUser() throws Exception {
- installTargetPackage(TARGET, USER);
- installTargetPackage("some.other.target", USER);
- installOverlayPackage(OVERLAY, TARGET, USER, true);
-
- // do nothing, expect no change
- List<String> a = mImpl.updateOverlaysForUser(USER);
- assertEquals(1, a.size());
- assertTrue(a.contains(TARGET));
-
- // upgrade overlay, keep target
- upgradeOverlayPackage(OVERLAY, TARGET, USER, true);
- List<String> b = mImpl.updateOverlaysForUser(USER);
- assertEquals(1, b.size());
- assertTrue(b.contains(TARGET));
-
- // do nothing, expect no change
- List<String> c = mImpl.updateOverlaysForUser(USER);
- assertEquals(1, c.size());
- assertTrue(c.contains(TARGET));
-
- // upgrade overlay, switch to new target
- upgradeOverlayPackage(OVERLAY, "some.other.target", USER, true);
- List<String> d = mImpl.updateOverlaysForUser(USER);
- assertEquals(2, d.size());
- assertTrue(d.containsAll(Arrays.asList(TARGET, "some.other.target")));
-
- // do nothing, expect no change
- List<String> e = mImpl.updateOverlaysForUser(USER);
- assertEquals(1, e.size());
- assertTrue(e.contains("some.other.target"));
- }
-
- @Test
public void testOnOverlayPackageUpgraded() throws Exception {
+ final OverlayManagerServiceImpl impl = getImpl();
+ final DummyListener listener = getListener();
installTargetPackage(TARGET, USER);
- installOverlayPackage(OVERLAY, TARGET, USER, true);
- mImpl.onOverlayPackageReplacing(OVERLAY, USER);
- mListener.count = 0;
- mImpl.onOverlayPackageReplaced(OVERLAY, USER);
- assertEquals(1, mListener.count);
+ installOverlayPackage(OVERLAY, TARGET, USER);
+ impl.onOverlayPackageReplacing(OVERLAY, USER);
+ listener.count = 0;
+ impl.onOverlayPackageReplaced(OVERLAY, USER);
+ assertEquals(1, listener.count);
// upgrade to a version where the overlay has changed its target
- upgradeOverlayPackage(OVERLAY, "some.other.target", USER, true);
- mImpl.onOverlayPackageReplacing(OVERLAY, USER);
- mListener.count = 0;
- mImpl.onOverlayPackageReplaced(OVERLAY, USER);
+ beginUpgradeOverlayPackage(OVERLAY, USER);
+ listener.count = 0;
+ endUpgradeOverlayPackage(OVERLAY, "some.other.target", USER);
// expect once for the old target package, once for the new target package
- assertEquals(2, mListener.count);
+ assertEquals(2, listener.count);
- upgradeOverlayPackage(OVERLAY, "some.other.target", USER, true);
- mImpl.onOverlayPackageReplacing(OVERLAY, USER);
- mListener.count = 0;
- mImpl.onOverlayPackageReplaced(OVERLAY, USER);
- assertEquals(1, mListener.count);
+ beginUpgradeOverlayPackage(OVERLAY, USER);
+ listener.count = 0;
+ endUpgradeOverlayPackage(OVERLAY, "some.other.target", USER);
+ assertEquals(1, listener.count);
}
// tests: listener interface
@Test
public void testListener() throws Exception {
- installOverlayPackage(OVERLAY, TARGET, USER, true);
- assertEquals(1, mListener.count);
- mListener.count = 0;
+ final OverlayManagerServiceImpl impl = getImpl();
+ final DummyListener listener = getListener();
+ installOverlayPackage(OVERLAY, TARGET, USER);
+ assertEquals(1, listener.count);
+ listener.count = 0;
installTargetPackage(TARGET, USER);
- assertEquals(1, mListener.count);
- mListener.count = 0;
+ assertEquals(1, listener.count);
+ listener.count = 0;
- mImpl.setEnabled(OVERLAY, true, USER);
- assertEquals(1, mListener.count);
- mListener.count = 0;
+ impl.setEnabled(OVERLAY, true, USER);
+ assertEquals(1, listener.count);
+ listener.count = 0;
- mImpl.setEnabled(OVERLAY, true, USER);
- assertEquals(0, mListener.count);
- }
-
- // helper methods
-
- private void assertState(int expected, final String overlayPackageName, int userId) {
- int actual = mImpl.getOverlayInfo(OVERLAY, USER).state;
- String msg = String.format("expected %s but was %s:",
- OverlayInfo.stateToString(expected), OverlayInfo.stateToString(actual));
- assertEquals(msg, expected, actual);
- }
-
- private void assertOverlayInfoList(final String targetPackageName, int userId,
- OverlayInfo... overlayInfos) {
- final List<OverlayInfo> expected =
- mImpl.getOverlayInfosForTarget(targetPackageName, userId);
- final List<OverlayInfo> actual = Arrays.asList(overlayInfos);
- assertEquals(expected, actual);
- }
-
- private void installTargetPackage(String packageName, int userId) {
- if (mState.select(packageName, userId) != null) {
- throw new IllegalStateException("package already installed");
- }
- mState.add(packageName, null, userId, false);
- mImpl.onTargetPackageAdded(packageName, userId);
- }
-
- private void beginUpgradeTargetPackage(String packageName, int userId) {
- if (mState.select(packageName, userId) == null) {
- throw new IllegalStateException("package not installed");
- }
- mState.add(packageName, null, userId, false);
- mImpl.onTargetPackageReplacing(packageName, userId);
- }
-
- private void endUpgradeTargetPackage(String packageName, int userId) {
- if (mState.select(packageName, userId) == null) {
- throw new IllegalStateException("package not installed");
- }
- mState.add(packageName, null, userId, false);
- mImpl.onTargetPackageReplaced(packageName, userId);
- }
-
- private void uninstallTargetPackage(String packageName, int userId) {
- if (mState.select(packageName, userId) == null) {
- throw new IllegalStateException("package not installed");
- }
- mState.remove(packageName, userId);
- mImpl.onTargetPackageRemoved(packageName, userId);
- }
-
- private void installOverlayPackage(String packageName, String targetPackageName, int userId,
- boolean canCreateIdmap) {
- if (mState.select(packageName, userId) != null) {
- throw new IllegalStateException("package already installed");
- }
- mState.add(packageName, targetPackageName, userId, canCreateIdmap);
- mImpl.onOverlayPackageAdded(packageName, userId);
- }
-
- private void upgradeOverlayPackage(String packageName, String targetPackageName, int userId,
- boolean canCreateIdmap) {
- DummyDeviceState.Package pkg = mState.select(packageName, userId);
- if (pkg == null) {
- throw new IllegalStateException("package not installed, cannot upgrade");
- }
- pkg.targetPackageName = targetPackageName;
- pkg.canCreateIdmap = canCreateIdmap;
- }
-
- private void uninstallOverlayPackage(String packageName, int userId) {
- // implement this when adding support for downloadable overlays
- throw new IllegalArgumentException("not implemented");
- }
-
- private static final class DummyDeviceState {
- private List<Package> mPackages = new ArrayList<>();
-
- public void add(String packageName, String targetPackageName, int userId,
- boolean canCreateIdmap) {
- remove(packageName, userId);
- Package pkg = new Package();
- pkg.packageName = packageName;
- pkg.targetPackageName = targetPackageName;
- pkg.userId = userId;
- pkg.canCreateIdmap = canCreateIdmap;
- mPackages.add(pkg);
- }
-
- public void remove(String packageName, int userId) {
- final Iterator<Package> iter = mPackages.iterator();
- while (iter.hasNext()) {
- final Package pkg = iter.next();
- if (pkg.packageName.equals(packageName) && pkg.userId == userId) {
- iter.remove();
- return;
- }
- }
- }
-
- public List<Package> select(int userId) {
- List<Package> out = new ArrayList<>();
- final int packageCount = mPackages.size();
- for (int i = 0; i < packageCount; i++) {
- final Package pkg = mPackages.get(i);
- if (pkg.userId == userId) {
- out.add(pkg);
- }
- }
- return out;
- }
-
- public Package select(String packageName, int userId) {
- final int packageCount = mPackages.size();
- for (int i = 0; i < packageCount; i++) {
- final Package pkg = mPackages.get(i);
- if (pkg.packageName.equals(packageName) && pkg.userId == userId) {
- return pkg;
- }
- }
- return null;
- }
-
- private static final class Package {
- public String packageName;
- public int userId;
- public String targetPackageName;
- public boolean canCreateIdmap;
- }
- }
-
- private static final class DummyPackageManagerHelper implements
- OverlayManagerServiceImpl.PackageManagerHelper {
- private final DummyDeviceState mState;
-
- DummyPackageManagerHelper(DummyDeviceState state) {
- mState = state;
- }
-
- @Override
- public PackageInfo getPackageInfo(@NonNull String packageName, int userId) {
- final DummyDeviceState.Package pkg = mState.select(packageName, userId);
- if (pkg == null) {
- return null;
- }
- ApplicationInfo ai = new ApplicationInfo();
- ai.sourceDir = String.format("%s/%s/base.apk",
- pkg.targetPackageName == null ? "/system/app/" : "/vendor/overlay/",
- pkg.packageName);
- PackageInfo pi = new PackageInfo();
- pi.applicationInfo = ai;
- pi.packageName = pkg.packageName;
- pi.overlayTarget = pkg.targetPackageName;
- pi.overlayCategory = "dummy-category-" + pkg.targetPackageName;
- return pi;
- }
-
- @Override
- public boolean signaturesMatching(@NonNull String packageName1,
- @NonNull String packageName2, int userId) {
- return false;
- }
-
- @Override
- public List<PackageInfo> getOverlayPackages(int userId) {
- List<PackageInfo> out = new ArrayList<>();
- final List<DummyDeviceState.Package> packages = mState.select(userId);
- final int packageCount = packages.size();
- for (int i = 0; i < packageCount; i++) {
- final DummyDeviceState.Package pkg = packages.get(i);
- if (pkg.targetPackageName != null) {
- out.add(getPackageInfo(pkg.packageName, pkg.userId));
- }
- }
- return out;
- }
- }
-
- private static class DummyIdmapManager extends IdmapManager {
- private final DummyDeviceState mState;
- private Set<String> mIdmapFiles = new ArraySet<>();
-
- DummyIdmapManager(DummyDeviceState state, DummyPackageManagerHelper packageManagerHelper) {
- super(packageManagerHelper);
- mState = state;
- }
-
- @Override
- boolean createIdmap(@NonNull final PackageInfo targetPackage,
- @NonNull final PackageInfo overlayPackage, int userId) {
- final DummyDeviceState.Package t = mState.select(targetPackage.packageName, userId);
- if (t == null) {
- return false;
- }
- final DummyDeviceState.Package o = mState.select(overlayPackage.packageName, userId);
- if (o == null) {
- return false;
- }
- if (!o.canCreateIdmap) {
- return false;
- }
- final String key = createKey(overlayPackage.packageName, userId);
- mIdmapFiles.add(key);
- return true;
- }
-
- @Override
- boolean removeIdmap(@NonNull final OverlayInfo oi, final int userId) {
- final String key = createKey(oi.packageName, oi.userId);
- if (!mIdmapFiles.contains(key)) {
- return false;
- }
- mIdmapFiles.remove(key);
- return true;
- }
-
- @Override
- boolean idmapExists(@NonNull final OverlayInfo oi) {
- final String key = createKey(oi.packageName, oi.userId);
- return mIdmapFiles.contains(key);
- }
-
- @Override
- boolean idmapExists(@NonNull final PackageInfo overlayPackage, final int userId) {
- final String key = createKey(overlayPackage.packageName, userId);
- return mIdmapFiles.contains(key);
- }
-
- private String createKey(@NonNull final String packageName, final int userId) {
- return String.format("%s:%d", packageName, userId);
- }
- }
-
- private static class DummyListener implements OverlayManagerServiceImpl.OverlayChangeListener {
- public int count;
-
- public void onOverlaysChanged(@NonNull String targetPackage, int userId) {
- count++;
- }
+ impl.setEnabled(OVERLAY, true, USER);
+ assertEquals(0, listener.count);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java
new file mode 100644
index 0000000..a753aac
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java
@@ -0,0 +1,385 @@
+/*
+ * 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.server.om;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.annotation.NonNull;
+import android.content.om.OverlayInfo;
+import android.content.om.OverlayInfo.State;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.util.ArraySet;
+
+import com.android.internal.content.om.OverlayConfig;
+
+import org.junit.Before;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/** Base class for creating {@link OverlayManagerServiceImplTests} tests. */
+class OverlayManagerServiceImplTestsBase {
+ private OverlayManagerServiceImpl mImpl;
+ private DummyDeviceState mState;
+ private DummyListener mListener;
+
+ @Before
+ public void setUp() {
+ mState = new DummyDeviceState();
+ mListener = new DummyListener();
+ final DummyPackageManagerHelper pmh = new DummyPackageManagerHelper(mState);
+
+ mImpl = new OverlayManagerServiceImpl(pmh,
+ new DummyIdmapManager(mState, pmh),
+ new OverlayManagerSettings(),
+ mState.mOverlayConfig,
+ new String[0],
+ mListener);
+ }
+
+ public OverlayManagerServiceImpl getImpl() {
+ return mImpl;
+ }
+
+ public DummyListener getListener() {
+ return mListener;
+ }
+
+ void assertState(@State int expected, final String overlayPackageName, int userId) {
+ final OverlayInfo info = mImpl.getOverlayInfo(overlayPackageName, userId);
+ if (info == null) {
+ throw new IllegalStateException("package not installed");
+ }
+
+ final String msg = String.format("expected %s but was %s:",
+ OverlayInfo.stateToString(expected), OverlayInfo.stateToString(info.state));
+ assertEquals(msg, expected, info.state);
+ }
+
+ void assertOverlayInfoList(final String targetPackageName, int userId,
+ OverlayInfo... overlayInfos) {
+ final List<OverlayInfo> expected =
+ mImpl.getOverlayInfosForTarget(targetPackageName, userId);
+ final List<OverlayInfo> actual = Arrays.asList(overlayInfos);
+ assertEquals(expected, actual);
+ }
+
+ /**
+ * Creates an overlay configured through {@link OverlayConfig}.
+ *
+ * @throws IllegalStateException if the package is already installed
+ */
+ void addOverlayPackage(String packageName, String targetPackageName, int userId,
+ boolean mutable, boolean enabled, int priority) {
+ mState.addOverlay(packageName, targetPackageName, userId, mutable, enabled, priority);
+ }
+
+ /**
+ * Adds the target package to the device.
+ *
+ * This corresponds to when the OMS receives the
+ * {@link android.content.Intent#ACTION_PACKAGE_ADDED} broadcast.
+ *
+ * @throws IllegalStateException if the package is not currently installed
+ */
+ void installTargetPackage(String packageName, int userId) {
+ if (mState.select(packageName, userId) != null) {
+ throw new IllegalStateException("package already installed");
+ }
+ mState.addTarget(packageName, userId);
+ mImpl.onTargetPackageAdded(packageName, userId);
+ }
+
+ /**
+ * Begins upgrading the target package.
+ *
+ * This corresponds to when the OMS receives the
+ * {@link android.content.Intent#ACTION_PACKAGE_REMOVED} broadcast with the
+ * {@link android.content.Intent#EXTRA_REPLACING} extra.
+ *
+ * @throws IllegalStateException if the package is not currently installed
+ */
+ void beginUpgradeTargetPackage(String packageName, int userId) {
+ if (mState.select(packageName, userId) == null) {
+ throw new IllegalStateException("package not installed");
+ }
+ mImpl.onTargetPackageReplacing(packageName, userId);
+ }
+
+ /**
+ * Ends upgrading the target package.
+ *
+ * This corresponds to when the OMS receives the
+ * {@link android.content.Intent#ACTION_PACKAGE_ADDED} broadcast with the
+ * {@link android.content.Intent#EXTRA_REPLACING} extra.
+ *
+ * @throws IllegalStateException if the package is not currently installed
+ */
+ void endUpgradeTargetPackage(String packageName, int userId) {
+ if (mState.select(packageName, userId) == null) {
+ throw new IllegalStateException("package not installed");
+ }
+ mState.addTarget(packageName, userId);
+ mImpl.onTargetPackageReplaced(packageName, userId);
+ }
+
+ /**
+ * Removes the target package from the device.
+ *
+ * This corresponds to when the OMS receives the
+ * {@link android.content.Intent#ACTION_PACKAGE_REMOVED} broadcast.
+ *
+ * @throws IllegalStateException if the package is not currently installed
+ */
+ void uninstallTargetPackage(String packageName, int userId) {
+ if (mState.select(packageName, userId) == null) {
+ throw new IllegalStateException("package not installed");
+ }
+ mState.remove(packageName, userId);
+ mImpl.onTargetPackageRemoved(packageName, userId);
+ }
+
+ /**
+ * Adds the overlay package to the device.
+ *
+ * This corresponds to when the OMS receives the
+ * {@link android.content.Intent#ACTION_PACKAGE_ADDED} broadcast.
+ *
+ * @throws IllegalStateException if the package is already installed
+ */
+ void installOverlayPackage(String packageName, String targetPackageName, int userId) {
+ if (mState.select(packageName, userId) != null) {
+ throw new IllegalStateException("package already installed");
+ }
+ mState.addOverlay(packageName, targetPackageName, userId);
+ mImpl.onOverlayPackageAdded(packageName, userId);
+ }
+
+ /**
+ * Begins upgrading the overlay package.
+ *
+ * This corresponds to when the OMS receives the
+ * {@link android.content.Intent#ACTION_PACKAGE_REMOVED} broadcast with the
+ * {@link android.content.Intent#EXTRA_REPLACING} extra.
+ *
+ * @throws IllegalStateException if the package is not currently installed
+ */
+ void beginUpgradeOverlayPackage(String packageName, int userId) {
+ if (mState.select(packageName, userId) == null) {
+ throw new IllegalStateException("package not installed, cannot upgrade");
+ }
+
+ mImpl.onOverlayPackageReplacing(packageName, userId);
+ }
+
+ /**
+ * Ends upgrading the overlay package, potentially changing its target package.
+ *
+ * This corresponds to when the OMS receives the
+ * {@link android.content.Intent#ACTION_PACKAGE_ADDED} broadcast with the
+ * {@link android.content.Intent#EXTRA_REPLACING} extra.
+ *
+ * @throws IllegalStateException if the package is not currently installed
+ */
+ void endUpgradeOverlayPackage(String packageName, String targetPackageName, int userId) {
+ if (mState.select(packageName, userId) == null) {
+ throw new IllegalStateException("package not installed, cannot upgrade");
+ }
+
+ mState.addOverlay(packageName, targetPackageName, userId);
+ mImpl.onOverlayPackageReplaced(packageName, userId);
+ }
+
+ private static final class DummyDeviceState {
+ private List<Package> mPackages = new ArrayList<>();
+ private OverlayConfig mOverlayConfig = mock(OverlayConfig.class);
+
+ /** Adds a non-overlay to the device. */
+ public void addTarget(String packageName, int userId) {
+ remove(packageName, userId);
+ mPackages.add(new Package(packageName, userId, null, false, false, 0));
+ }
+
+ /** Adds an overlay to the device. */
+ public void addOverlay(String packageName, String targetPackageName, int userId) {
+ addOverlay(packageName, targetPackageName, userId, true, false, OverlayConfig.DEFAULT_PRIORITY);
+ }
+
+ /** Adds a configured overlay to the device. */
+ public void addOverlay(String packageName, String targetPackageName, int userId,
+ boolean mutable, boolean enabled, int priority) {
+ remove(packageName, userId);
+ mPackages.add(new Package(packageName, userId, targetPackageName, mutable, enabled,
+ priority));
+ when(mOverlayConfig.getPriority(packageName)).thenReturn(priority);
+ when(mOverlayConfig.isEnabled(packageName)).thenReturn(enabled);
+ when(mOverlayConfig.isMutable(packageName)).thenReturn(mutable);
+ }
+
+ /** Remove a package from the device. */
+ public void remove(String packageName, int userId) {
+ final Iterator<Package> iter = mPackages.iterator();
+ while (iter.hasNext()) {
+ final Package pkg = iter.next();
+ if (pkg.packageName.equals(packageName) && pkg.userId == userId) {
+ iter.remove();
+ return;
+ }
+ }
+ }
+
+ /** Retrieves all packages on device for a particular user. */
+ public List<Package> select(int userId) {
+ return mPackages.stream().filter(p -> p.userId == userId).collect(Collectors.toList());
+ }
+
+ /** Retrieves the package with the specified package name for a particular user. */
+ public Package select(String packageName, int userId) {
+ return mPackages.stream().filter(
+ p -> p.packageName.equals(packageName) && p.userId == userId)
+ .findFirst().orElse(null);
+ }
+
+ private static final class Package {
+ public final String packageName;
+ public final int userId;
+ public final String targetPackageName;
+ public final boolean mutable;
+ public final boolean enabled;
+ public final int priority;
+
+ private Package(String packageName, int userId, String targetPackageName,
+ boolean mutable, boolean enabled, int priority) {
+ this.packageName = packageName;
+ this.userId = userId;
+ this.targetPackageName = targetPackageName;
+ this.mutable = mutable;
+ this.enabled = enabled;
+ this.priority = priority;
+ }
+ }
+ }
+
+ static final class DummyPackageManagerHelper implements
+ OverlayManagerServiceImpl.PackageManagerHelper {
+ private final DummyDeviceState mState;
+
+ private DummyPackageManagerHelper(DummyDeviceState state) {
+ mState = state;
+ }
+
+ @Override
+ public PackageInfo getPackageInfo(@NonNull String packageName, int userId) {
+ final DummyDeviceState.Package pkg = mState.select(packageName, userId);
+ if (pkg == null) {
+ return null;
+ }
+ final ApplicationInfo ai = new ApplicationInfo();
+ ai.sourceDir = String.format("%s/%s/base.apk",
+ pkg.targetPackageName == null ? "/system/app/" : "/vendor/overlay/",
+ pkg.packageName);
+ PackageInfo pi = new PackageInfo();
+ pi.applicationInfo = ai;
+ pi.packageName = pkg.packageName;
+ pi.overlayTarget = pkg.targetPackageName;
+ pi.overlayCategory = "dummy-category-" + pkg.targetPackageName;
+ return pi;
+ }
+
+ @Override
+ public boolean signaturesMatching(@NonNull String packageName1,
+ @NonNull String packageName2, int userId) {
+ return false;
+ }
+
+ @Override
+ public List<PackageInfo> getOverlayPackages(int userId) {
+ return mState.select(userId).stream()
+ .filter(p -> p.targetPackageName != null)
+ .map(p -> getPackageInfo(p.packageName, p.userId))
+ .collect(Collectors.toList());
+ }
+ }
+
+ static class DummyIdmapManager extends IdmapManager {
+ private final DummyDeviceState mState;
+ private Set<String> mIdmapFiles = new ArraySet<>();
+
+ private DummyIdmapManager(DummyDeviceState state,
+ DummyPackageManagerHelper packageManagerHelper) {
+ super(packageManagerHelper);
+ mState = state;
+ }
+
+ @Override
+ boolean createIdmap(@NonNull final PackageInfo targetPackage,
+ @NonNull final PackageInfo overlayPackage, int userId) {
+ final DummyDeviceState.Package t = mState.select(targetPackage.packageName, userId);
+ if (t == null) {
+ return false;
+ }
+ final DummyDeviceState.Package o = mState.select(overlayPackage.packageName, userId);
+ if (o == null) {
+ return false;
+ }
+ final String key = createKey(overlayPackage.packageName, userId);
+ mIdmapFiles.add(key);
+ return true;
+ }
+
+ @Override
+ boolean removeIdmap(@NonNull final OverlayInfo oi, final int userId) {
+ final String key = createKey(oi.packageName, oi.userId);
+ if (!mIdmapFiles.contains(key)) {
+ return false;
+ }
+ mIdmapFiles.remove(key);
+ return true;
+ }
+
+ @Override
+ boolean idmapExists(@NonNull final OverlayInfo oi) {
+ final String key = createKey(oi.packageName, oi.userId);
+ return mIdmapFiles.contains(key);
+ }
+
+ @Override
+ boolean idmapExists(@NonNull final PackageInfo overlayPackage, final int userId) {
+ final String key = createKey(overlayPackage.packageName, userId);
+ return mIdmapFiles.contains(key);
+ }
+
+ private String createKey(@NonNull final String packageName, final int userId) {
+ return String.format("%s:%d", packageName, userId);
+ }
+ }
+
+ static class DummyListener implements OverlayManagerServiceImpl.OverlayChangeListener {
+ public int count;
+
+ public void onOverlaysChanged(@NonNull String targetPackage, int userId) {
+ count++;
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java
index 8ff8b6e..146f60a 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java
@@ -58,7 +58,7 @@
STATE_DISABLED,
0,
0,
- false);
+ true);
private static final OverlayInfo OVERLAY_B0 = new OverlayInfo(
"com.dummy.overlay_b",
@@ -69,7 +69,7 @@
STATE_DISABLED,
0,
0,
- false);
+ true);
private static final OverlayInfo OVERLAY_C0 = new OverlayInfo(
"com.dummy.overlay_c",
@@ -80,7 +80,7 @@
STATE_DISABLED,
0,
0,
- false);
+ true);
private static final OverlayInfo OVERLAY_A1 = new OverlayInfo(
"com.dummy.overlay_a",
@@ -91,7 +91,7 @@
STATE_DISABLED,
1,
0,
- false);
+ true);
private static final OverlayInfo OVERLAY_B1 = new OverlayInfo(
"com.dummy.overlay_b",
@@ -102,7 +102,7 @@
STATE_DISABLED,
1,
0,
- false);
+ true);
@Before
public void setUp() throws Exception {
@@ -238,7 +238,7 @@
STATE_DISABLED,
0,
0,
- false);
+ true);
insert(otherTarget);
changed = mSettings.setPriority(OVERLAY_A0.packageName, otherTarget.packageName,
OVERLAY_A0.userId);
@@ -435,7 +435,7 @@
private void insert(OverlayInfo oi) throws Exception {
mSettings.init(oi.packageName, oi.userId, oi.targetPackageName, null, oi.baseCodePath,
- false, 0, oi.category);
+ true, false,0, oi.category);
mSettings.setState(oi.packageName, oi.userId, oi.state);
mSettings.setEnabled(oi.packageName, oi.userId, false);
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
index 85840e1..5c15322 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
@@ -118,15 +118,15 @@
String[] partitions = { "system", "vendor", "odm", "oem", "product", "system_ext" };
String[] appdir = { "app", "priv-app" };
for (int i = 0; i < partitions.length; i++) {
- final PackageManagerService.SystemPartition systemPartition =
+ final PackageManagerService.ScanPartition scanPartition =
PackageManagerService.SYSTEM_PARTITIONS.get(i);
for (int j = 0; j < appdir.length; j++) {
String canonical = new File("/" + partitions[i]).getCanonicalPath();
String path = String.format("%s/%s/A.apk", canonical, appdir[j]);
- Assert.assertEquals(j == 1 && i != 3, systemPartition.containsPrivPath(path));
+ Assert.assertEquals(j == 1 && i != 3, scanPartition.containsPrivPath(path));
- final int scanFlag = systemPartition.scanFlag;
+ final int scanFlag = scanPartition.scanFlag;
Assert.assertEquals(i == 1, scanFlag == PackageManagerService.SCAN_AS_VENDOR);
Assert.assertEquals(i == 2, scanFlag == PackageManagerService.SCAN_AS_ODM);
Assert.assertEquals(i == 3, scanFlag == PackageManagerService.SCAN_AS_OEM);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index e5ffb4d..604fcd3 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -2902,21 +2902,21 @@
}
@Test
- public void testSetListenerAccess_doesNothingOnLowRam() throws Exception {
+ public void testSetListenerAccess_onLowRam() throws Exception {
when(mActivityManager.isLowRamDevice()).thenReturn(true);
ComponentName c = ComponentName.unflattenFromString("package/Component");
mBinderService.setNotificationListenerAccessGranted(c, true);
- verify(mListeners, never()).setPackageOrComponentEnabled(
+ verify(mListeners).setPackageOrComponentEnabled(
anyString(), anyInt(), anyBoolean(), anyBoolean());
- verify(mConditionProviders, never()).setPackageOrComponentEnabled(
+ verify(mConditionProviders).setPackageOrComponentEnabled(
anyString(), anyInt(), anyBoolean(), anyBoolean());
- verify(mAssistants, never()).setPackageOrComponentEnabled(
- any(), anyInt(), anyBoolean(), anyBoolean());
+ verify(mAssistants).migrateToXml();
+ verify(mAssistants).resetDefaultAssistantsIfNecessary();
}
@Test
- public void testSetAssistantAccess_doesNothingOnLowRam() throws Exception {
+ public void testSetAssistantAccess_onLowRam() throws Exception {
when(mActivityManager.isLowRamDevice()).thenReturn(true);
ComponentName c = ComponentName.unflattenFromString("package/Component");
List<UserInfo> uis = new ArrayList<>();
@@ -2927,26 +2927,28 @@
mBinderService.setNotificationAssistantAccessGranted(c, true);
- verify(mListeners, never()).setPackageOrComponentEnabled(
+ verify(mListeners).migrateToXml();
+ verify(mListeners).notifyNotificationChannelChanged(anyString(), any(), any(),
+ anyInt());
+ verify(mConditionProviders).setPackageOrComponentEnabled(
anyString(), anyInt(), anyBoolean(), anyBoolean());
- verify(mConditionProviders, never()).setPackageOrComponentEnabled(
- anyString(), anyInt(), anyBoolean(), anyBoolean());
- verify(mAssistants, never()).setPackageOrComponentEnabled(
- any(), anyInt(), anyBoolean(), anyBoolean());
+ verify(mAssistants).migrateToXml();
+ verify(mAssistants).resetDefaultAssistantsIfNecessary();
}
@Test
- public void testSetDndAccess_doesNothingOnLowRam() throws Exception {
+ public void testSetDndAccess_onLowRam() throws Exception {
when(mActivityManager.isLowRamDevice()).thenReturn(true);
ComponentName c = ComponentName.unflattenFromString("package/Component");
mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
- verify(mListeners, never()).setPackageOrComponentEnabled(
+ verify(mListeners).migrateToXml();
+ verify(mListeners).notifyNotificationChannelChanged(anyString(), any(), any(),
+ anyInt());
+ verify(mConditionProviders).setPackageOrComponentEnabled(
anyString(), anyInt(), anyBoolean(), anyBoolean());
- verify(mConditionProviders, never()).setPackageOrComponentEnabled(
- anyString(), anyInt(), anyBoolean(), anyBoolean());
- verify(mAssistants, never()).setPackageOrComponentEnabled(
- any(), anyInt(), anyBoolean(), anyBoolean());
+ verify(mAssistants).migrateToXml();
+ verify(mAssistants).resetDefaultAssistantsIfNecessary();
}
@Test
@@ -4288,68 +4290,13 @@
}
@Test
- public void testCanUseManagedServicesLowRamNoWatchNullPkg() {
- when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
- when(mActivityManager.isLowRamDevice()).thenReturn(true);
- when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
- .thenReturn(new String[] {"a", "b", "c"});
- when(mContext.getResources()).thenReturn(mResources);
-
- assertEquals(false, mService.canUseManagedServices(null, 0, null));
+ public void testCanUseManagedServicesNullPkg() {
+ assertEquals(true, mService.canUseManagedServices(null, 0, null));
}
- @Test
- public void testCanUseManagedServicesLowRamNoWatchValidPkg() {
- when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
- when(mActivityManager.isLowRamDevice()).thenReturn(true);
- when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
- .thenReturn(new String[] {"a", "b", "c"});
- when(mContext.getResources()).thenReturn(mResources);
-
- assertEquals(true, mService.canUseManagedServices("b", 0, null));
- }
@Test
- public void testCanUseManagedServicesLowRamNoWatchNoValidPkg() {
- when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
- when(mActivityManager.isLowRamDevice()).thenReturn(true);
- when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
- .thenReturn(new String[] {"a", "b", "c"});
- when(mContext.getResources()).thenReturn(mResources);
-
- assertEquals(false, mService.canUseManagedServices("d", 0, null));
- }
-
- @Test
- public void testCanUseManagedServicesLowRamWatchNoValidPkg() {
- when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
- when(mActivityManager.isLowRamDevice()).thenReturn(true);
- when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
- .thenReturn(new String[] {"a", "b", "c"});
- when(mContext.getResources()).thenReturn(mResources);
-
- assertEquals(true, mService.canUseManagedServices("d", 0, null));
- }
-
- @Test
- public void testCanUseManagedServicesNoLowRamNoWatchValidPkg() {
- when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
- when(mActivityManager.isLowRamDevice()).thenReturn(false);
- when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
- .thenReturn(new String[] {"a", "b", "c"});
- when(mContext.getResources()).thenReturn(mResources);
-
- assertEquals(true, mService.canUseManagedServices("d", 0 , null));
- }
-
- @Test
- public void testCanUseManagedServicesNoLowRamWatchValidPkg() {
- when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
- when(mActivityManager.isLowRamDevice()).thenReturn(false);
- when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
- .thenReturn(new String[] {"a", "b", "c"});
- when(mContext.getResources()).thenReturn(mResources);
-
+ public void testCanUseManagedServicesNoValidPkg() {
assertEquals(true, mService.canUseManagedServices("d", 0, null));
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationTest.java
index 0ea53fa..d765042 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationTest.java
@@ -22,9 +22,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.app.ActivityManager;
@@ -32,15 +30,12 @@
import android.app.PendingIntent;
import android.app.Person;
import android.app.RemoteInput;
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Typeface;
import android.graphics.drawable.Icon;
import android.net.Uri;
-import android.os.Build;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.style.StyleSpan;
@@ -74,91 +69,13 @@
}
@Test
- public void testStripsExtendersInLowRamModeNoWhitelistNoTv() {
+ public void testDoesNotStripsExtenders() {
Notification.Builder nb = new Notification.Builder(mContext, "channel");
nb.extend(new Notification.CarExtender().setColor(Color.RED));
nb.extend(new Notification.TvExtender().setChannelId("different channel"));
nb.extend(new Notification.WearableExtender().setDismissalId("dismiss"));
Notification before = nb.build();
-
- // No whitelist
- Context context = spy(getContext());
- when(context.getResources()).thenReturn(mResources);
- when(mResources.getStringArray(anyInt())).thenReturn(new String[0]);
-
- Notification after = Notification.Builder.maybeCloneStrippedForDelivery(before, true,
- context);
-
- assertEquals("different channel", new Notification.TvExtender(before).getChannelId());
- assertNull(new Notification.TvExtender(after).getChannelId());
-
- assertEquals(Color.RED, new Notification.CarExtender(before).getColor());
- assertEquals(Notification.COLOR_DEFAULT, new Notification.CarExtender(after).getColor());
-
- assertEquals("dismiss", new Notification.WearableExtender(before).getDismissalId());
- assertNull(new Notification.WearableExtender(after).getDismissalId());
- }
-
- @Test
- public void testStripsExtendersInLowRamModeHasWhitelist() {
- Notification.Builder nb = new Notification.Builder(mContext, "channel");
- nb.extend(new Notification.CarExtender().setColor(Color.RED));
- nb.extend(new Notification.TvExtender().setChannelId("different channel"));
- nb.extend(new Notification.WearableExtender().setDismissalId("dismiss"));
- Notification before = nb.build();
-
- // Has whitelist
- Context context = spy(mContext);
- when(context.getResources()).thenReturn(mResources);
- when(mResources.getStringArray(anyInt())).thenReturn(new String[1]);
-
- Notification after = Notification.Builder.maybeCloneStrippedForDelivery(before, true,
- context);
-
- assertEquals("different channel", new Notification.TvExtender(before).getChannelId());
- assertEquals("different channel", new Notification.TvExtender(after).getChannelId());
-
- assertEquals(Color.RED, new Notification.CarExtender(before).getColor());
- assertEquals(Color.RED, new Notification.CarExtender(after).getColor());
-
- assertEquals("dismiss", new Notification.WearableExtender(before).getDismissalId());
- assertEquals("dismiss", new Notification.WearableExtender(after).getDismissalId());
- }
-
- @Test
- public void testStripsRemoteViewsInLowRamMode() {
- Context context = spy(mContext);
- ApplicationInfo ai = new ApplicationInfo();
- ai.targetSdkVersion = Build.VERSION_CODES.M;
- when(context.getApplicationInfo()).thenReturn(ai);
-
- final Notification.BigTextStyle style = new Notification.BigTextStyle()
- .bigText("hello")
- .setSummaryText("And the summary");
- Notification before = new Notification.Builder(context, "channel")
- .setContentText("hi")
- .setStyle(style)
- .build();
-
- Notification after = Notification.Builder.maybeCloneStrippedForDelivery(before, true,
- mContext);
- assertNotNull(before.contentView);
- assertNotNull(before.bigContentView);
- assertNotNull(before.headsUpContentView);
- assertNull(after.contentView);
- assertNull(after.bigContentView);
- assertNull(after.headsUpContentView);
- }
-
- @Test
- public void testDoesNotStripsExtendersInNormalRamMode() {
- Notification.Builder nb = new Notification.Builder(mContext, "channel");
- nb.extend(new Notification.CarExtender().setColor(Color.RED));
- nb.extend(new Notification.TvExtender().setChannelId("different channel"));
- nb.extend(new Notification.WearableExtender().setDismissalId("dismiss"));
- Notification before = nb.build();
- Notification after = Notification.Builder.maybeCloneStrippedForDelivery(before, false,
- mContext);
+ Notification after = Notification.Builder.maybeCloneStrippedForDelivery(before);
assertTrue(before == after);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index fa182d6..c110a0c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -372,7 +372,7 @@
doReturn(mMockPackageManager).when(mService).getPackageManagerInternalLocked();
doReturn(false).when(mMockPackageManager).isInstantAppInstallerComponent(any());
doReturn(null).when(mMockPackageManager).resolveIntent(any(), any(), anyInt(), anyInt(),
- anyBoolean(), anyInt());
+ anyInt(), anyBoolean(), anyInt());
// Never review permissions
doReturn(false).when(mMockPackageManager).isPermissionsReviewRequired(any(), anyInt());
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
index 6dc1e0e..c074e6e 100644
--- a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
@@ -248,10 +248,10 @@
public int hour;
public int monthDay;
- /** Month [0-11] */
- public int month;
+ /** Month in the range 1(Jan) - 12(Dec). */
+ public int monthOrdinal;
- /** Full year. For example, 1970. */
+ /** Full year in the range 1996 - 2095. */
public int year;
private ZoneId mZoneId;
@@ -269,7 +269,7 @@
ts.year = year >= 96 ? year + 1900 : year + 2000;
int month = IccUtils.cdmaBcdByteToInt(data[1]);
if (month < 1 || month > 12) return null;
- ts.month = month - 1;
+ ts.monthOrdinal = month;
int day = IccUtils.cdmaBcdByteToInt(data[2]);
if (day < 1 || day > 31) return null;
ts.monthDay = day;
@@ -292,7 +292,7 @@
int year = localDateTime.getYear();
if (year < 1996 || year > 2095) return null;
ts.year = year;
- ts.month = localDateTime.getMonthValue();
+ ts.monthOrdinal = localDateTime.getMonthValue();
ts.monthDay = localDateTime.getDayOfMonth();
ts.hour = localDateTime.getHour();
ts.minute = localDateTime.getMinute();
@@ -304,7 +304,7 @@
int year = this.year % 100; // 00 - 99
ByteArrayOutputStream outStream = new ByteArrayOutputStream(6);
outStream.write((((year / 10) & 0x0F) << 4) | ((year % 10) & 0x0F));
- outStream.write((((month / 10) << 4) & 0xF0) | ((month % 10) & 0x0F));
+ outStream.write((((monthOrdinal / 10) << 4) & 0xF0) | ((monthOrdinal % 10) & 0x0F));
outStream.write((((monthDay / 10) << 4) & 0xF0) | ((monthDay % 10) & 0x0F));
outStream.write((((hour / 10) << 4) & 0xF0) | ((hour % 10) & 0x0F));
outStream.write((((minute / 10) << 4) & 0xF0) | ((minute % 10) & 0x0F));
@@ -314,7 +314,7 @@
public long toMillis() {
LocalDateTime localDateTime =
- LocalDateTime.of(year, month + 1, monthDay, hour, minute, second);
+ LocalDateTime.of(year, monthOrdinal, monthDay, hour, minute, second);
Instant instant = localDateTime.toInstant(mZoneId.getRules().getOffset(localDateTime));
return instant.toEpochMilli();
}
@@ -325,7 +325,7 @@
StringBuilder builder = new StringBuilder();
builder.append("TimeStamp ");
builder.append("{ year=" + year);
- builder.append(", month=" + month);
+ builder.append(", month=" + monthOrdinal);
builder.append(", day=" + monthDay);
builder.append(", hour=" + hour);
builder.append(", minute=" + minute);
diff --git a/tools/stats_log_api_gen/Android.bp b/tools/stats_log_api_gen/Android.bp
index e566d27..d5031d7 100644
--- a/tools/stats_log_api_gen/Android.bp
+++ b/tools/stats_log_api_gen/Android.bp
@@ -121,9 +121,8 @@
shared_libs: [
"liblog",
"libcutils",
+ "libstatssocket",
],
- static_libs: ["libstatssocket"],
-
apex_available: [
"//apex_available:platform",
//TODO(b/149781190): Remove this once statsd no longer depends on libstatslog