Snap for 7035108 from 10012754a8c868b3654df02923ef49e3d46ff3d1 to mainline-release
Change-Id: Icf775476a6ce453f4f2ed407c9aa46b6dbfe0b35
diff --git a/init/lmkd_service.cpp b/init/lmkd_service.cpp
index dd1ab4d..c982925 100644
--- a/init/lmkd_service.cpp
+++ b/init/lmkd_service.cpp
@@ -79,7 +79,7 @@
}
static void RegisterServices(pid_t exclude_pid) {
- for (const auto& service : ServiceList::GetInstance().services()) {
+ for (const auto& service : ServiceList::GetInstance()) {
auto svc = service.get();
if (svc->oom_score_adjust() != DEFAULT_OOM_SCORE_ADJUST) {
// skip if process is excluded or not yet forked (pid==0)
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 23a07aa..a4fb08e 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -85,12 +85,11 @@
static const std::set<std::string> kDebuggingServices{"tombstoned", "logd", "adbd", "console"};
-static std::vector<Service*> GetDebuggingServices(bool only_post_data) {
- std::vector<Service*> ret;
- ret.reserve(kDebuggingServices.size());
+static std::set<std::string> GetPostDataDebuggingServices() {
+ std::set<std::string> ret;
for (const auto& s : ServiceList::GetInstance()) {
- if (kDebuggingServices.count(s->name()) && (!only_post_data || s->is_post_data())) {
- ret.push_back(s.get());
+ if (kDebuggingServices.count(s->name()) && s->is_post_data()) {
+ ret.insert(s->name());
}
}
return ret;
@@ -503,13 +502,18 @@
// Stops given services, waits for them to be stopped for |timeout| ms.
// If terminate is true, then SIGTERM is sent to services, otherwise SIGKILL is sent.
-static void StopServices(const std::vector<Service*>& services, std::chrono::milliseconds timeout,
+// Note that services are stopped in order given by |ServiceList::services_in_shutdown_order|
+// function.
+static void StopServices(const std::set<std::string>& services, std::chrono::milliseconds timeout,
bool terminate) {
LOG(INFO) << "Stopping " << services.size() << " services by sending "
<< (terminate ? "SIGTERM" : "SIGKILL");
std::vector<pid_t> pids;
pids.reserve(services.size());
- for (const auto& s : services) {
+ for (const auto& s : ServiceList::GetInstance().services_in_shutdown_order()) {
+ if (services.count(s->name()) == 0) {
+ continue;
+ }
if (s->pid() > 0) {
pids.push_back(s->pid());
}
@@ -529,12 +533,12 @@
// Like StopServices, but also logs all the services that failed to stop after the provided timeout.
// Returns number of violators.
-static int StopServicesAndLogViolations(const std::vector<Service*>& services,
+static int StopServicesAndLogViolations(const std::set<std::string>& services,
std::chrono::milliseconds timeout, bool terminate) {
StopServices(services, timeout, terminate);
int still_running = 0;
- for (const auto& s : services) {
- if (s->IsRunning()) {
+ for (const auto& s : ServiceList::GetInstance()) {
+ if (s->IsRunning() && services.count(s->name())) {
LOG(ERROR) << "[service-misbehaving] : service '" << s->name() << "' is still running "
<< timeout.count() << "ms after receiving "
<< (terminate ? "SIGTERM" : "SIGKILL");
@@ -608,8 +612,7 @@
// watchdogd is a vendor specific component but should be alive to complete shutdown safely.
const std::set<std::string> to_starts{"watchdogd"};
- std::vector<Service*> stop_first;
- stop_first.reserve(ServiceList::GetInstance().services().size());
+ std::set<std::string> stop_first;
for (const auto& s : ServiceList::GetInstance()) {
if (kDebuggingServices.count(s->name())) {
// keep debugging tools until non critical ones are all gone.
@@ -627,7 +630,7 @@
<< "': " << result.error();
}
} else {
- stop_first.push_back(s.get());
+ stop_first.insert(s->name());
}
}
@@ -690,7 +693,7 @@
LOG(INFO) << "vold not running, skipping vold shutdown";
}
// logcat stopped here
- StopServices(GetDebuggingServices(false /* only_post_data */), 0ms, false /* SIGKILL */);
+ StopServices(kDebuggingServices, 0ms, false /* SIGKILL */);
// 4. sync, try umount, and optionally run fsck for user shutdown
{
Timer sync_timer;
@@ -779,17 +782,17 @@
sub_reason = "resetprop";
return Error() << "Failed to reset sys.powerctl property";
}
- std::vector<Service*> stop_first;
+ std::set<std::string> stop_first;
// Remember the services that were enabled. We will need to manually enable them again otherwise
// triggers like class_start won't restart them.
- std::vector<Service*> were_enabled;
- stop_first.reserve(ServiceList::GetInstance().services().size());
+ std::set<std::string> were_enabled;
for (const auto& s : ServiceList::GetInstance().services_in_shutdown_order()) {
if (s->is_post_data() && !kDebuggingServices.count(s->name())) {
- stop_first.push_back(s);
+ stop_first.insert(s->name());
}
+ // TODO(ioffe): we should also filter out temporary services here.
if (s->is_post_data() && s->IsEnabled()) {
- were_enabled.push_back(s);
+ were_enabled.insert(s->name());
}
}
{
@@ -817,8 +820,9 @@
sub_reason = "vold_reset";
return result;
}
- if (int r = StopServicesAndLogViolations(GetDebuggingServices(true /* only_post_data */),
- sigkill_timeout, false /* SIGKILL */);
+ const auto& debugging_services = GetPostDataDebuggingServices();
+ if (int r = StopServicesAndLogViolations(debugging_services, sigkill_timeout,
+ false /* SIGKILL */);
r > 0) {
sub_reason = "sigkill_debug";
// TODO(b/135984674): store information about offending services for debugging.
@@ -847,9 +851,11 @@
return false;
});
// Re-enable services
- for (const auto& s : were_enabled) {
- LOG(INFO) << "Re-enabling service '" << s->name() << "'";
- s->Enable();
+ for (const auto& s : ServiceList::GetInstance()) {
+ if (were_enabled.count(s->name())) {
+ LOG(INFO) << "Re-enabling service '" << s->name() << "'";
+ s->Enable();
+ }
}
ServiceList::GetInstance().ResetState();
LeaveShutdown();
diff --git a/init/service_list.h b/init/service_list.h
index 3b9018b..555da25 100644
--- a/init/service_list.h
+++ b/init/service_list.h
@@ -66,7 +66,6 @@
auto begin() const { return services_.begin(); }
auto end() const { return services_.end(); }
- const std::vector<std::unique_ptr<Service>>& services() const { return services_; }
const std::vector<Service*> services_in_shutdown_order() const;
void MarkPostData();
diff --git a/init/test_utils/service_utils.cpp b/init/test_utils/service_utils.cpp
index ae68679..6426ed9 100644
--- a/init/test_utils/service_utils.cpp
+++ b/init/test_utils/service_utils.cpp
@@ -44,7 +44,7 @@
}
ServiceInterfacesMap result;
- for (const auto& service : service_list.services()) {
+ for (const auto& service : service_list) {
// Create an entry for all services, including services that may not
// have any declared interfaces.
result[service->name()] = service->interfaces();
diff --git a/libstats/pull/Android.bp b/libstats/pull/Android.bp
deleted file mode 100644
index a8b4a4f..0000000
--- a/libstats/pull/Android.bp
+++ /dev/null
@@ -1,110 +0,0 @@
-//
-// 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.
-//
-
-// ==========================================================
-// Native library to register a pull atom callback with statsd
-// ==========================================================
-cc_defaults {
- name: "libstatspull_defaults",
- srcs: [
- "stats_pull_atom_callback.cpp",
- ],
- cflags: [
- "-Wall",
- "-Werror",
- ],
- export_include_dirs: ["include"],
- shared_libs: [
- "libbinder_ndk",
- "liblog",
- "libstatssocket",
- ],
- static_libs: [
- "libutils",
- "statsd-aidl-ndk_platform",
- ],
-}
-cc_library_shared {
- name: "libstatspull",
- defaults: [
- "libstatspull_defaults"
- ],
- // enumerate stable entry points for APEX use
- stubs: {
- symbol_file: "libstatspull.map.txt",
- versions: [
- "30",
- ],
- },
- apex_available: [
- "com.android.os.statsd",
- "test_com.android.os.statsd",
- ],
-
- stl: "libc++_static",
-
- // TODO(b/151102177): Enable it when the build error is fixed.
- header_abi_checker: {
- enabled: false,
- },
-}
-
-// ONLY USE IN TESTS.
-cc_library_static {
- name: "libstatspull_private",
- defaults: [
- "libstatspull_defaults",
- ],
- visibility: [
- "//frameworks/base/apex/statsd/tests/libstatspull",
- ],
-}
-
-// Note: These unit tests only test PullAtomMetadata.
-// For full E2E tests of libstatspull, use LibStatsPullTests
-cc_test {
- name: "libstatspull_test",
- srcs: [
- "tests/pull_atom_metadata_test.cpp",
- ],
- shared_libs: [
- "libstatspull",
- "libstatssocket",
- ],
- test_suites: ["general-tests", "mts"],
- test_config: "libstatspull_test.xml",
-
- //TODO(b/153588990): Remove when the build system properly separates
- //32bit and 64bit architectures.
- compile_multilib: "both",
- multilib: {
- lib64: {
- suffix: "64",
- },
- lib32: {
- suffix: "32",
- },
- },
- cflags: [
- "-Wall",
- "-Werror",
- "-Wno-missing-field-initializers",
- "-Wno-unused-variable",
- "-Wno-unused-function",
- "-Wno-unused-parameter",
- ],
- require_root: true,
-}
diff --git a/libstats/pull/OWNERS b/libstats/pull/OWNERS
deleted file mode 100644
index 7855774..0000000
--- a/libstats/pull/OWNERS
+++ /dev/null
@@ -1,7 +0,0 @@
-joeo@google.com
-muhammadq@google.com
-ruchirr@google.com
-singhtejinder@google.com
-tsaichristine@google.com
-yaochen@google.com
-yro@google.com
diff --git a/libstats/pull/TEST_MAPPING b/libstats/pull/TEST_MAPPING
deleted file mode 100644
index 76f4f02..0000000
--- a/libstats/pull/TEST_MAPPING
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "presubmit" : [
- {
- "name" : "libstatspull_test"
- }
- ]
-}
\ No newline at end of file
diff --git a/libstats/pull/include/stats_pull_atom_callback.h b/libstats/pull/include/stats_pull_atom_callback.h
deleted file mode 100644
index 17df584..0000000
--- a/libstats/pull/include/stats_pull_atom_callback.h
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * 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.
- */
-#pragma once
-
-#include <stats_event.h>
-
-#include <stdbool.h>
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Opaque struct representing the metadata for registering an AStatsManager_PullAtomCallback.
- */
-struct AStatsManager_PullAtomMetadata;
-typedef struct AStatsManager_PullAtomMetadata AStatsManager_PullAtomMetadata;
-
-/**
- * Allocate and initialize new PullAtomMetadata.
- *
- * Must call AStatsManager_PullAtomMetadata_release to free the memory.
- */
-AStatsManager_PullAtomMetadata* AStatsManager_PullAtomMetadata_obtain();
-
-/**
- * Frees the memory held by this PullAtomMetadata
- *
- * After calling this, the PullAtomMetadata must not be used or modified in any way.
- */
-void AStatsManager_PullAtomMetadata_release(AStatsManager_PullAtomMetadata* metadata);
-
-/**
- * Set the cool down time of the pull in milliseconds. If two successive pulls are issued
- * within the cool down, a cached version of the first will be used for the second. The minimum
- * allowed cool down is one second.
- */
-void AStatsManager_PullAtomMetadata_setCoolDownMillis(AStatsManager_PullAtomMetadata* metadata,
- int64_t cool_down_millis);
-
-/**
- * Get the cool down time of the pull in milliseconds.
- */
-int64_t AStatsManager_PullAtomMetadata_getCoolDownMillis(AStatsManager_PullAtomMetadata* metadata);
-
-/**
- * Set the maximum time the pull can take in milliseconds.
- * The maximum allowed timeout is 10 seconds.
- */
-void AStatsManager_PullAtomMetadata_setTimeoutMillis(AStatsManager_PullAtomMetadata* metadata,
- int64_t timeout_millis);
-
-/**
- * Get the maximum time the pull can take in milliseconds.
- */
-int64_t AStatsManager_PullAtomMetadata_getTimeoutMillis(AStatsManager_PullAtomMetadata* metadata);
-
-/**
- * Set the additive fields of this pulled atom.
- *
- * This is only applicable for atoms which have a uid field. When tasks are run in
- * isolated processes, the data will be attributed to the host uid. Additive fields
- * will be combined when the non-additive fields are the same.
- */
-void AStatsManager_PullAtomMetadata_setAdditiveFields(AStatsManager_PullAtomMetadata* metadata,
- int32_t* additive_fields, int32_t num_fields);
-
-/**
- * Get the number of additive fields for this pulled atom. This is intended to be called before
- * AStatsManager_PullAtomMetadata_getAdditiveFields to determine the size of the array.
- */
-int32_t AStatsManager_PullAtomMetadata_getNumAdditiveFields(
- AStatsManager_PullAtomMetadata* metadata);
-
-/**
- * Get the additive fields of this pulled atom.
- *
- * \param fields an output parameter containing the additive fields for this PullAtomMetadata.
- * Fields is an array and it is assumed that it is at least as large as the number of
- * additive fields, which can be obtained by calling
- * AStatsManager_PullAtomMetadata_getNumAdditiveFields.
- */
-void AStatsManager_PullAtomMetadata_getAdditiveFields(AStatsManager_PullAtomMetadata* metadata,
- int32_t* fields);
-
-/**
- * Return codes for the result of a pull.
- */
-typedef int32_t AStatsManager_PullAtomCallbackReturn;
-enum {
- // Value indicating that this pull was successful and that the result should be used.
- AStatsManager_PULL_SUCCESS = 0,
- // Value indicating that this pull was unsuccessful and that the result should not be used.
- AStatsManager_PULL_SKIP = 1,
-};
-
-/**
- * Opaque struct representing a list of AStatsEvent objects.
- */
-struct AStatsEventList;
-typedef struct AStatsEventList AStatsEventList;
-
-/**
- * Appends and returns an AStatsEvent to the end of the AStatsEventList.
- *
- * If an AStatsEvent is obtained in this manner, the memory is internally managed and
- * AStatsEvent_release does not need to be called. The lifetime of the AStatsEvent is that of the
- * AStatsEventList.
- *
- * The AStatsEvent does still need to be built by calling AStatsEvent_build.
- */
-AStatsEvent* AStatsEventList_addStatsEvent(AStatsEventList* pull_data);
-
-/**
- * Callback interface for pulling atoms requested by the stats service.
- *
- * \param atom_tag the tag of the atom to pull.
- * \param data an output parameter in which the caller should fill the results of the pull. This
- * param cannot be NULL and it's lifetime is as long as the execution of the callback.
- * It must not be accessed or modified after returning from the callback.
- * \param cookie the opaque pointer passed in AStatsManager_registerPullAtomCallback.
- * \return AStatsManager_PULL_SUCCESS if the pull was successful, or AStatsManager_PULL_SKIP if not.
- */
-typedef AStatsManager_PullAtomCallbackReturn (*AStatsManager_PullAtomCallback)(
- int32_t atom_tag, AStatsEventList* data, void* cookie);
-/**
- * Sets a callback for an atom when that atom is to be pulled. The stats service will
- * invoke the callback when the stats service determines that this atom needs to be
- * pulled.
- *
- * Requires the REGISTER_STATS_PULL_ATOM permission.
- *
- * \param atom_tag The tag of the atom for this pull atom callback.
- * \param metadata Optional metadata specifying the timeout, cool down time, and
- * additive fields for mapping isolated to host uids.
- * This param is nullable, in which case defaults will be used.
- * \param callback The callback to be invoked when the stats service pulls the atom.
- * \param cookie A pointer that will be passed back to the callback.
- * It has no meaning to statsd.
- */
-void AStatsManager_setPullAtomCallback(int32_t atom_tag, AStatsManager_PullAtomMetadata* metadata,
- AStatsManager_PullAtomCallback callback, void* cookie);
-
-/**
- * Clears a callback for an atom when that atom is to be pulled. Note that any ongoing
- * pulls will still occur.
- *
- * Requires the REGISTER_STATS_PULL_ATOM permission.
- *
- * \param atomTag The tag of the atom of which to unregister
- */
-void AStatsManager_clearPullAtomCallback(int32_t atom_tag);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libstats/pull/libstatspull.map.txt b/libstats/pull/libstatspull.map.txt
deleted file mode 100644
index e0e851a..0000000
--- a/libstats/pull/libstatspull.map.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-LIBSTATSPULL {
- global:
- AStatsManager_PullAtomMetadata_obtain; # apex # introduced=30
- AStatsManager_PullAtomMetadata_release; # apex # introduced=30
- AStatsManager_PullAtomMetadata_setCoolDownMillis; # apex # introduced=30
- AStatsManager_PullAtomMetadata_getCoolDownMillis; # apex # introduced=30
- AStatsManager_PullAtomMetadata_setTimeoutMillis; # apex # introduced=30
- AStatsManager_PullAtomMetadata_getTimeoutMillis; # apex # introduced=30
- AStatsManager_PullAtomMetadata_setAdditiveFields; # apex # introduced=30
- AStatsManager_PullAtomMetadata_getNumAdditiveFields; # apex # introduced=30
- AStatsManager_PullAtomMetadata_getAdditiveFields; # apex # introduced=30
- AStatsEventList_addStatsEvent; # apex # introduced=30
- AStatsManager_setPullAtomCallback; # apex # introduced=30
- AStatsManager_clearPullAtomCallback; # apex # introduced=30
- local:
- *;
-};
diff --git a/libstats/pull/libstatspull_test.xml b/libstats/pull/libstatspull_test.xml
deleted file mode 100644
index 233fc1f..0000000
--- a/libstats/pull/libstatspull_test.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<configuration description="Runs libstatspull_test.">
- <option name="test-suite-tag" value="apct" />
- <option name="test-suite-tag" value="apct-native" />
- <option name="test-suite-tag" value="mts" />
-
- <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
-
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
- <option name="cleanup" value="true" />
- <option name="push" value="libstatspull_test->/data/local/tmp/libstatspull_test" />
- <option name="append-bitness" value="true" />
- </target_preparer>
-
- <test class="com.android.tradefed.testtype.GTest" >
- <option name="native-test-device-path" value="/data/local/tmp" />
- <option name="module-name" value="libstatspull_test" />
- </test>
-
- <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
- <option name="mainline-module-package-name" value="com.google.android.os.statsd" />
- </object>
-</configuration>
diff --git a/libstats/pull/stats_pull_atom_callback.cpp b/libstats/pull/stats_pull_atom_callback.cpp
deleted file mode 100644
index 478cae7..0000000
--- a/libstats/pull/stats_pull_atom_callback.cpp
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * 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.
- */
-
-#include <map>
-#include <thread>
-#include <vector>
-
-#include <stats_event.h>
-#include <stats_pull_atom_callback.h>
-
-#include <aidl/android/os/BnPullAtomCallback.h>
-#include <aidl/android/os/IPullAtomResultReceiver.h>
-#include <aidl/android/os/IStatsd.h>
-#include <aidl/android/util/StatsEventParcel.h>
-#include <android/binder_auto_utils.h>
-#include <android/binder_ibinder.h>
-#include <android/binder_manager.h>
-
-using Status = ::ndk::ScopedAStatus;
-using aidl::android::os::BnPullAtomCallback;
-using aidl::android::os::IPullAtomResultReceiver;
-using aidl::android::os::IStatsd;
-using aidl::android::util::StatsEventParcel;
-using ::ndk::SharedRefBase;
-
-struct AStatsEventList {
- std::vector<AStatsEvent*> data;
-};
-
-AStatsEvent* AStatsEventList_addStatsEvent(AStatsEventList* pull_data) {
- AStatsEvent* event = AStatsEvent_obtain();
- pull_data->data.push_back(event);
- return event;
-}
-
-static const int64_t DEFAULT_COOL_DOWN_MILLIS = 1000LL; // 1 second.
-static const int64_t DEFAULT_TIMEOUT_MILLIS = 2000LL; // 2 seconds.
-
-struct AStatsManager_PullAtomMetadata {
- int64_t cool_down_millis;
- int64_t timeout_millis;
- std::vector<int32_t> additive_fields;
-};
-
-AStatsManager_PullAtomMetadata* AStatsManager_PullAtomMetadata_obtain() {
- AStatsManager_PullAtomMetadata* metadata = new AStatsManager_PullAtomMetadata();
- metadata->cool_down_millis = DEFAULT_COOL_DOWN_MILLIS;
- metadata->timeout_millis = DEFAULT_TIMEOUT_MILLIS;
- metadata->additive_fields = std::vector<int32_t>();
- return metadata;
-}
-
-void AStatsManager_PullAtomMetadata_release(AStatsManager_PullAtomMetadata* metadata) {
- delete metadata;
-}
-
-void AStatsManager_PullAtomMetadata_setCoolDownMillis(AStatsManager_PullAtomMetadata* metadata,
- int64_t cool_down_millis) {
- metadata->cool_down_millis = cool_down_millis;
-}
-
-int64_t AStatsManager_PullAtomMetadata_getCoolDownMillis(AStatsManager_PullAtomMetadata* metadata) {
- return metadata->cool_down_millis;
-}
-
-void AStatsManager_PullAtomMetadata_setTimeoutMillis(AStatsManager_PullAtomMetadata* metadata,
- int64_t timeout_millis) {
- metadata->timeout_millis = timeout_millis;
-}
-
-int64_t AStatsManager_PullAtomMetadata_getTimeoutMillis(AStatsManager_PullAtomMetadata* metadata) {
- return metadata->timeout_millis;
-}
-
-void AStatsManager_PullAtomMetadata_setAdditiveFields(AStatsManager_PullAtomMetadata* metadata,
- int32_t* additive_fields,
- int32_t num_fields) {
- metadata->additive_fields.assign(additive_fields, additive_fields + num_fields);
-}
-
-int32_t AStatsManager_PullAtomMetadata_getNumAdditiveFields(
- AStatsManager_PullAtomMetadata* metadata) {
- return metadata->additive_fields.size();
-}
-
-void AStatsManager_PullAtomMetadata_getAdditiveFields(AStatsManager_PullAtomMetadata* metadata,
- int32_t* fields) {
- std::copy(metadata->additive_fields.begin(), metadata->additive_fields.end(), fields);
-}
-
-class StatsPullAtomCallbackInternal : public BnPullAtomCallback {
- public:
- StatsPullAtomCallbackInternal(const AStatsManager_PullAtomCallback callback, void* cookie,
- const int64_t coolDownMillis, const int64_t timeoutMillis,
- const std::vector<int32_t> additiveFields)
- : mCallback(callback),
- mCookie(cookie),
- mCoolDownMillis(coolDownMillis),
- mTimeoutMillis(timeoutMillis),
- mAdditiveFields(additiveFields) {}
-
- Status onPullAtom(int32_t atomTag,
- const std::shared_ptr<IPullAtomResultReceiver>& resultReceiver) override {
- AStatsEventList statsEventList;
- int successInt = mCallback(atomTag, &statsEventList, mCookie);
- bool success = successInt == AStatsManager_PULL_SUCCESS;
-
- // Convert stats_events into StatsEventParcels.
- std::vector<StatsEventParcel> parcels;
- for (int i = 0; i < statsEventList.data.size(); i++) {
- size_t size;
- uint8_t* buffer = AStatsEvent_getBuffer(statsEventList.data[i], &size);
-
- StatsEventParcel p;
- // vector.assign() creates a copy, but this is inevitable unless
- // stats_event.h/c uses a vector as opposed to a buffer.
- p.buffer.assign(buffer, buffer + size);
- parcels.push_back(std::move(p));
- }
-
- Status status = resultReceiver->pullFinished(atomTag, success, parcels);
- if (!status.isOk()) {
- std::vector<StatsEventParcel> emptyParcels;
- resultReceiver->pullFinished(atomTag, /*success=*/false, emptyParcels);
- }
- for (int i = 0; i < statsEventList.data.size(); i++) {
- AStatsEvent_release(statsEventList.data[i]);
- }
- return Status::ok();
- }
-
- int64_t getCoolDownMillis() const { return mCoolDownMillis; }
- int64_t getTimeoutMillis() const { return mTimeoutMillis; }
- const std::vector<int32_t>& getAdditiveFields() const { return mAdditiveFields; }
-
- private:
- const AStatsManager_PullAtomCallback mCallback;
- void* mCookie;
- const int64_t mCoolDownMillis;
- const int64_t mTimeoutMillis;
- const std::vector<int32_t> mAdditiveFields;
-};
-
-static std::mutex pullAtomMutex;
-static std::shared_ptr<IStatsd> sStatsd = nullptr;
-
-static std::map<int32_t, std::shared_ptr<StatsPullAtomCallbackInternal>> mPullers;
-static std::shared_ptr<IStatsd> getStatsService();
-
-static void binderDied(void* /*cookie*/) {
- {
- std::lock_guard<std::mutex> lock(pullAtomMutex);
- sStatsd = nullptr;
- }
-
- std::shared_ptr<IStatsd> statsService = getStatsService();
- if (statsService == nullptr) {
- return;
- }
-
- // Since we do not want to make an IPC with the lock held, we first create a
- // copy of the data with the lock held before iterating through the map.
- std::map<int32_t, std::shared_ptr<StatsPullAtomCallbackInternal>> pullersCopy;
- {
- std::lock_guard<std::mutex> lock(pullAtomMutex);
- pullersCopy = mPullers;
- }
- for (const auto& it : pullersCopy) {
- statsService->registerNativePullAtomCallback(it.first, it.second->getCoolDownMillis(),
- it.second->getTimeoutMillis(),
- it.second->getAdditiveFields(), it.second);
- }
-}
-
-static ::ndk::ScopedAIBinder_DeathRecipient sDeathRecipient(
- AIBinder_DeathRecipient_new(binderDied));
-
-static std::shared_ptr<IStatsd> getStatsService() {
- std::lock_guard<std::mutex> lock(pullAtomMutex);
- if (!sStatsd) {
- // Fetch statsd
- ::ndk::SpAIBinder binder(AServiceManager_getService("stats"));
- sStatsd = IStatsd::fromBinder(binder);
- if (sStatsd) {
- AIBinder_linkToDeath(binder.get(), sDeathRecipient.get(), /*cookie=*/nullptr);
- }
- }
- return sStatsd;
-}
-
-void registerStatsPullAtomCallbackBlocking(int32_t atomTag,
- std::shared_ptr<StatsPullAtomCallbackInternal> cb) {
- const std::shared_ptr<IStatsd> statsService = getStatsService();
- if (statsService == nullptr) {
- // Statsd not available
- return;
- }
-
- statsService->registerNativePullAtomCallback(
- atomTag, cb->getCoolDownMillis(), cb->getTimeoutMillis(), cb->getAdditiveFields(), cb);
-}
-
-void unregisterStatsPullAtomCallbackBlocking(int32_t atomTag) {
- const std::shared_ptr<IStatsd> statsService = getStatsService();
- if (statsService == nullptr) {
- // Statsd not available
- return;
- }
-
- statsService->unregisterNativePullAtomCallback(atomTag);
-}
-
-void AStatsManager_setPullAtomCallback(int32_t atom_tag, AStatsManager_PullAtomMetadata* metadata,
- AStatsManager_PullAtomCallback callback, void* cookie) {
- int64_t coolDownMillis =
- metadata == nullptr ? DEFAULT_COOL_DOWN_MILLIS : metadata->cool_down_millis;
- int64_t timeoutMillis = metadata == nullptr ? DEFAULT_TIMEOUT_MILLIS : metadata->timeout_millis;
-
- std::vector<int32_t> additiveFields;
- if (metadata != nullptr) {
- additiveFields = metadata->additive_fields;
- }
-
- std::shared_ptr<StatsPullAtomCallbackInternal> callbackBinder =
- SharedRefBase::make<StatsPullAtomCallbackInternal>(callback, cookie, coolDownMillis,
- timeoutMillis, additiveFields);
-
- {
- std::lock_guard<std::mutex> lg(pullAtomMutex);
- // Always add to the map. If statsd is dead, we will add them when it comes back.
- mPullers[atom_tag] = callbackBinder;
- }
-
- std::thread registerThread(registerStatsPullAtomCallbackBlocking, atom_tag, callbackBinder);
- registerThread.detach();
-}
-
-void AStatsManager_clearPullAtomCallback(int32_t atom_tag) {
- {
- std::lock_guard<std::mutex> lg(pullAtomMutex);
- // Always remove the puller from our map.
- // If statsd is down, we will not register it when it comes back.
- mPullers.erase(atom_tag);
- }
- std::thread unregisterThread(unregisterStatsPullAtomCallbackBlocking, atom_tag);
- unregisterThread.detach();
-}
diff --git a/libstats/pull/tests/pull_atom_metadata_test.cpp b/libstats/pull/tests/pull_atom_metadata_test.cpp
deleted file mode 100644
index abc8e47..0000000
--- a/libstats/pull/tests/pull_atom_metadata_test.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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 <gtest/gtest.h>
-
-#include <stats_pull_atom_callback.h>
-
-namespace {
-
-static const int64_t DEFAULT_COOL_DOWN_MILLIS = 1000LL; // 1 second.
-static const int64_t DEFAULT_TIMEOUT_MILLIS = 2000LL; // 2 seconds.
-
-} // anonymous namespace
-
-TEST(AStatsManager_PullAtomMetadataTest, TestEmpty) {
- AStatsManager_PullAtomMetadata* metadata = AStatsManager_PullAtomMetadata_obtain();
- EXPECT_EQ(AStatsManager_PullAtomMetadata_getCoolDownMillis(metadata), DEFAULT_COOL_DOWN_MILLIS);
- EXPECT_EQ(AStatsManager_PullAtomMetadata_getTimeoutMillis(metadata), DEFAULT_TIMEOUT_MILLIS);
- EXPECT_EQ(AStatsManager_PullAtomMetadata_getNumAdditiveFields(metadata), 0);
- AStatsManager_PullAtomMetadata_release(metadata);
-}
-
-TEST(AStatsManager_PullAtomMetadataTest, TestSetTimeoutMillis) {
- int64_t timeoutMillis = 500;
- AStatsManager_PullAtomMetadata* metadata = AStatsManager_PullAtomMetadata_obtain();
- AStatsManager_PullAtomMetadata_setTimeoutMillis(metadata, timeoutMillis);
- EXPECT_EQ(AStatsManager_PullAtomMetadata_getCoolDownMillis(metadata), DEFAULT_COOL_DOWN_MILLIS);
- EXPECT_EQ(AStatsManager_PullAtomMetadata_getTimeoutMillis(metadata), timeoutMillis);
- EXPECT_EQ(AStatsManager_PullAtomMetadata_getNumAdditiveFields(metadata), 0);
- AStatsManager_PullAtomMetadata_release(metadata);
-}
-
-TEST(AStatsManager_PullAtomMetadataTest, TestSetCoolDownMillis) {
- int64_t coolDownMillis = 10000;
- AStatsManager_PullAtomMetadata* metadata = AStatsManager_PullAtomMetadata_obtain();
- AStatsManager_PullAtomMetadata_setCoolDownMillis(metadata, coolDownMillis);
- EXPECT_EQ(AStatsManager_PullAtomMetadata_getCoolDownMillis(metadata), coolDownMillis);
- EXPECT_EQ(AStatsManager_PullAtomMetadata_getTimeoutMillis(metadata), DEFAULT_TIMEOUT_MILLIS);
- EXPECT_EQ(AStatsManager_PullAtomMetadata_getNumAdditiveFields(metadata), 0);
- AStatsManager_PullAtomMetadata_release(metadata);
-}
-
-TEST(AStatsManager_PullAtomMetadataTest, TestSetAdditiveFields) {
- const int numFields = 3;
- int inputFields[numFields] = {2, 4, 6};
- AStatsManager_PullAtomMetadata* metadata = AStatsManager_PullAtomMetadata_obtain();
- AStatsManager_PullAtomMetadata_setAdditiveFields(metadata, inputFields, numFields);
- EXPECT_EQ(AStatsManager_PullAtomMetadata_getCoolDownMillis(metadata), DEFAULT_COOL_DOWN_MILLIS);
- EXPECT_EQ(AStatsManager_PullAtomMetadata_getTimeoutMillis(metadata), DEFAULT_TIMEOUT_MILLIS);
- EXPECT_EQ(AStatsManager_PullAtomMetadata_getNumAdditiveFields(metadata), numFields);
- int outputFields[numFields];
- AStatsManager_PullAtomMetadata_getAdditiveFields(metadata, outputFields);
- for (int i = 0; i < numFields; i++) {
- EXPECT_EQ(inputFields[i], outputFields[i]);
- }
- AStatsManager_PullAtomMetadata_release(metadata);
-}
-
-TEST(AStatsManager_PullAtomMetadataTest, TestSetAllElements) {
- int64_t timeoutMillis = 500;
- int64_t coolDownMillis = 10000;
- const int numFields = 3;
- int inputFields[numFields] = {2, 4, 6};
-
- AStatsManager_PullAtomMetadata* metadata = AStatsManager_PullAtomMetadata_obtain();
- AStatsManager_PullAtomMetadata_setTimeoutMillis(metadata, timeoutMillis);
- AStatsManager_PullAtomMetadata_setCoolDownMillis(metadata, coolDownMillis);
- AStatsManager_PullAtomMetadata_setAdditiveFields(metadata, inputFields, numFields);
-
- EXPECT_EQ(AStatsManager_PullAtomMetadata_getCoolDownMillis(metadata), coolDownMillis);
- EXPECT_EQ(AStatsManager_PullAtomMetadata_getTimeoutMillis(metadata), timeoutMillis);
- EXPECT_EQ(AStatsManager_PullAtomMetadata_getNumAdditiveFields(metadata), numFields);
- int outputFields[numFields];
- AStatsManager_PullAtomMetadata_getAdditiveFields(metadata, outputFields);
- for (int i = 0; i < numFields; i++) {
- EXPECT_EQ(inputFields[i], outputFields[i]);
- }
- AStatsManager_PullAtomMetadata_release(metadata);
-}
diff --git a/libstats/socket/Android.bp b/libstats/socket/Android.bp
deleted file mode 100644
index bf79ea2..0000000
--- a/libstats/socket/Android.bp
+++ /dev/null
@@ -1,124 +0,0 @@
-//
-// Copyright (C) 2018 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-// =========================================================================
-// Native library to write stats log to statsd socket on Android R and later
-// =========================================================================
-cc_defaults {
- name: "libstatssocket_defaults",
- srcs: [
- "stats_buffer_writer.c",
- "stats_event.c",
- "stats_socket.c",
- "statsd_writer.c",
- ],
- export_include_dirs: ["include"],
- static_libs: [
- "libcutils", // does not expose a stable C API
- ],
- cflags: [
- "-Wall",
- "-Werror",
- ],
-}
-
-cc_library {
- name: "libstatssocket",
- defaults: [
- "libstatssocket_defaults",
- ],
- host_supported: true,
- target: {
- // On android, libstatssocket should only be linked as a shared lib
- android: {
- static: {
- enabled: false,
- },
- },
- host: {
- shared: {
- enabled: false,
- },
- },
- },
- stl: "libc++_static",
-
- // enumerate stable entry points for APEX use
- stubs: {
- symbol_file: "libstatssocket.map.txt",
- versions: [
- "30",
- ],
- },
- apex_available: [
- "com.android.os.statsd",
- "test_com.android.os.statsd",
- ],
-}
-
-//TODO (b/149842105): Figure out if there is a better solution for this.
-cc_test_library {
- name: "libstatssocket_private",
- defaults: [
- "libstatssocket_defaults",
- ],
- visibility: [
- "//frameworks/base/apex/statsd/tests/libstatspull",
- "//frameworks/base/cmds/statsd",
- ],
-}
-
-cc_library_headers {
- name: "libstatssocket_headers",
- export_include_dirs: ["include"],
- host_supported: true,
- apex_available: ["com.android.resolv"],
- min_sdk_version: "29",
-}
-
-cc_test {
- name: "libstatssocket_test",
- srcs: [
- "tests/stats_event_test.cpp",
- "tests/stats_writer_test.cpp",
- ],
- cflags: [
- "-Wall",
- "-Werror",
- ],
- static_libs: [
- "libgmock",
- "libstatssocket_private",
- ],
- shared_libs: [
- "libcutils",
- "libutils",
- ],
- test_suites: ["device-tests", "mts"],
- test_config: "libstatssocket_test.xml",
- //TODO(b/153588990): Remove when the build system properly separates.
- //32bit and 64bit architectures.
- compile_multilib: "both",
- multilib: {
- lib64: {
- suffix: "64",
- },
- lib32: {
- suffix: "32",
- },
- },
- require_root: true,
-}
diff --git a/libstats/socket/TEST_MAPPING b/libstats/socket/TEST_MAPPING
deleted file mode 100644
index 0224998..0000000
--- a/libstats/socket/TEST_MAPPING
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "presubmit" : [
- {
- "name" : "libstatssocket_test"
- }
- ]
-}
\ No newline at end of file
diff --git a/libstats/socket/include/stats_buffer_writer.h b/libstats/socket/include/stats_buffer_writer.h
deleted file mode 100644
index 5b41f0e..0000000
--- a/libstats/socket/include/stats_buffer_writer.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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.
- */
-
-#pragma once
-
-#include <stddef.h>
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif // __CPLUSPLUS
-void stats_log_close();
-int stats_log_is_closed();
-int write_buffer_to_statsd(void* buffer, size_t size, uint32_t atomId);
-#ifdef __cplusplus
-}
-#endif // __CPLUSPLUS
diff --git a/libstats/socket/include/stats_event.h b/libstats/socket/include/stats_event.h
deleted file mode 100644
index 3d3baf9..0000000
--- a/libstats/socket/include/stats_event.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef ANDROID_STATS_LOG_STATS_EVENT_H
-#define ANDROID_STATS_LOG_STATS_EVENT_H
-
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-
-/*
- * Functionality to build and store the buffer sent over the statsd socket.
- * This code defines and encapsulates the socket protocol.
- *
- * Usage:
- * AStatsEvent* event = AStatsEvent_obtain();
- *
- * AStatsEvent_setAtomId(event, atomId);
- * AStatsEvent_addBoolAnnotation(event, 5, false); // atom-level annotation
- * AStatsEvent_writeInt32(event, 24);
- * AStatsEvent_addBoolAnnotation(event, 1, true); // annotation for preceding atom field
- * AStatsEvent_addInt32Annotation(event, 2, 128);
- * AStatsEvent_writeFloat(event, 2.0);
- *
- * AStatsEvent_write(event);
- * AStatsEvent_release(event);
- *
- * Note that calls to add atom fields and annotations should be made in the
- * order that they are defined in the atom.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif // __CPLUSPLUS
-
-/**
- * Opaque struct use to represent a StatsEvent. It builds and stores the data that is sent to
- * statsd.
- */
-struct AStatsEvent;
-typedef struct AStatsEvent AStatsEvent;
-
-/**
- * Returns a new AStatsEvent. If you call this function, you must call AStatsEvent_release to free
- * the allocated memory.
- */
-AStatsEvent* AStatsEvent_obtain();
-
-/**
- * Builds and finalizes the AStatsEvent for a pulled event.
- * This should only be called for pulled AStatsEvents.
- *
- * After this function, the StatsEvent must not be modified in any way other than calling release or
- * write.
- *
- * Build can be called multiple times without error.
- * If the event has been built before, this function is a no-op.
- */
-void AStatsEvent_build(AStatsEvent* event);
-
-/**
- * Writes the StatsEvent to the stats log.
- *
- * After calling this, AStatsEvent_release must be called,
- * and is the only function that can be safely called.
- */
-int AStatsEvent_write(AStatsEvent* event);
-
-/**
- * Frees the memory held by this StatsEvent.
- *
- * After calling this, the StatsEvent must not be used or modified in any way.
- */
-void AStatsEvent_release(AStatsEvent* event);
-
-/**
- * Sets the atom id for this StatsEvent.
- *
- * This function should be called immediately after AStatsEvent_obtain. It may
- * be called additional times as well, but subsequent calls will have no effect.
- **/
-void AStatsEvent_setAtomId(AStatsEvent* event, uint32_t atomId);
-
-/**
- * Writes an int32_t field to this StatsEvent.
- **/
-void AStatsEvent_writeInt32(AStatsEvent* event, int32_t value);
-
-/**
- * Writes an int64_t field to this StatsEvent.
- **/
-void AStatsEvent_writeInt64(AStatsEvent* event, int64_t value);
-
-/**
- * Writes a float field to this StatsEvent.
- **/
-void AStatsEvent_writeFloat(AStatsEvent* event, float value);
-
-/**
- * Write a bool field to this StatsEvent.
- **/
-void AStatsEvent_writeBool(AStatsEvent* event, bool value);
-
-/**
- * Write a byte array field to this StatsEvent.
- **/
-void AStatsEvent_writeByteArray(AStatsEvent* event, const uint8_t* buf, size_t numBytes);
-
-/**
- * Write a string field to this StatsEvent.
- *
- * The string must be null-terminated.
- **/
-void AStatsEvent_writeString(AStatsEvent* event, const char* value);
-
-/**
- * Write an attribution chain field to this StatsEvent.
- *
- * The sizes of uids and tags must be equal. The AttributionNode at position i is
- * made up of uids[i] and tags[i].
- *
- * \param uids array of uids in the attribution chain.
- * \param tags array of tags in the attribution chain. Each tag must be null-terminated.
- * \param numNodes the number of AttributionNodes in the attribution chain. This is the length of
- * the uids and the tags.
- **/
-void AStatsEvent_writeAttributionChain(AStatsEvent* event, const uint32_t* uids,
- const char* const* tags, uint8_t numNodes);
-
-/**
- * Write a bool annotation for the previous field written.
- **/
-void AStatsEvent_addBoolAnnotation(AStatsEvent* event, uint8_t annotationId, bool value);
-
-/**
- * Write an integer annotation for the previous field written.
- **/
-void AStatsEvent_addInt32Annotation(AStatsEvent* event, uint8_t annotationId, int32_t value);
-
-// Internal/test APIs. Should not be exposed outside of the APEX.
-void AStatsEvent_overwriteTimestamp(AStatsEvent* event, uint64_t timestampNs);
-uint32_t AStatsEvent_getAtomId(AStatsEvent* event);
-// Size is an output parameter.
-uint8_t* AStatsEvent_getBuffer(AStatsEvent* event, size_t* size);
-uint32_t AStatsEvent_getErrors(AStatsEvent* event);
-
-#ifdef __cplusplus
-}
-#endif // __CPLUSPLUS
-
-#endif // ANDROID_STATS_LOG_STATS_EVENT_H
diff --git a/libstats/socket/include/stats_socket.h b/libstats/socket/include/stats_socket.h
deleted file mode 100644
index 5a75fc0..0000000
--- a/libstats/socket/include/stats_socket.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-/**
- * Helpers to manage the statsd socket.
- **/
-
-#ifdef __cplusplus
-extern "C" {
-#endif // __CPLUSPLUS
-
-/**
- * Closes the statsd socket file descriptor.
- **/
-void AStatsSocket_close();
-#ifdef __cplusplus
-}
-#endif // __CPLUSPLUS
diff --git a/libstats/socket/libstatssocket.map.txt b/libstats/socket/libstatssocket.map.txt
deleted file mode 100644
index 5c13904..0000000
--- a/libstats/socket/libstatssocket.map.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-LIBSTATSSOCKET {
- global:
- AStatsEvent_obtain; # apex # introduced=30
- AStatsEvent_build; # apex # introduced=30
- AStatsEvent_write; # apex # introduced=30
- AStatsEvent_release; # apex # introduced=30
- AStatsEvent_setAtomId; # apex # introduced=30
- AStatsEvent_writeInt32; # apex # introduced=30
- AStatsEvent_writeInt64; # apex # introduced=30
- AStatsEvent_writeFloat; # apex # introduced=30
- AStatsEvent_writeBool; # apex # introduced=30
- AStatsEvent_writeByteArray; # apex # introduced=30
- AStatsEvent_writeString; # apex # introduced=30
- AStatsEvent_writeAttributionChain; # apex # introduced=30
- AStatsEvent_addBoolAnnotation; # apex # introduced=30
- AStatsEvent_addInt32Annotation; # apex # introduced=30
- AStatsSocket_close; # apex # introduced=30
- local:
- *;
-};
diff --git a/libstats/socket/libstatssocket_test.xml b/libstats/socket/libstatssocket_test.xml
deleted file mode 100644
index d2694d1..0000000
--- a/libstats/socket/libstatssocket_test.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<configuration description="Runs libstatssocket_test.">
- <option name="test-suite-tag" value="apct" />
- <option name="test-suite-tag" value="apct-native" />
- <option name="test-suite-tag" value="mts" />
-
- <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
-
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
- <option name="cleanup" value="true" />
- <option name="push" value="libstatssocket_test->/data/local/tmp/libstatssocket_test" />
- <option name="append-bitness" value="true" />
- </target_preparer>
-
- <test class="com.android.tradefed.testtype.GTest" >
- <option name="native-test-device-path" value="/data/local/tmp" />
- <option name="module-name" value="libstatssocket_test" />
- </test>
-
- <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
- <option name="mainline-module-package-name" value="com.google.android.os.statsd" />
- </object>
-</configuration>
-
diff --git a/libstats/socket/stats_buffer_writer.c b/libstats/socket/stats_buffer_writer.c
deleted file mode 100644
index 549acdc..0000000
--- a/libstats/socket/stats_buffer_writer.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * 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.
- */
-
-#include "include/stats_buffer_writer.h"
-#ifdef __ANDROID__
-#include <cutils/properties.h>
-#endif
-#include <errno.h>
-#include <sys/time.h>
-#include <sys/uio.h>
-#include "statsd_writer.h"
-
-static const uint32_t kStatsEventTag = 1937006964;
-
-extern struct android_log_transport_write statsdLoggerWrite;
-
-static int __write_to_statsd_init(struct iovec* vec, size_t nr);
-static int (*__write_to_statsd)(struct iovec* vec, size_t nr) = __write_to_statsd_init;
-
-void note_log_drop(int error, int atomId) {
- statsdLoggerWrite.noteDrop(error, atomId);
-}
-
-void stats_log_close() {
- statsd_writer_init_lock();
- __write_to_statsd = __write_to_statsd_init;
- if (statsdLoggerWrite.close) {
- (*statsdLoggerWrite.close)();
- }
- statsd_writer_init_unlock();
-}
-
-int stats_log_is_closed() {
- return statsdLoggerWrite.isClosed && (*statsdLoggerWrite.isClosed)();
-}
-
-int write_buffer_to_statsd(void* buffer, size_t size, uint32_t atomId) {
- int ret = 1;
-
- struct iovec vecs[2];
- vecs[0].iov_base = (void*)&kStatsEventTag;
- vecs[0].iov_len = sizeof(kStatsEventTag);
- vecs[1].iov_base = buffer;
- vecs[1].iov_len = size;
-
- ret = __write_to_statsd(vecs, 2);
-
- if (ret < 0) {
- note_log_drop(ret, atomId);
- }
-
- return ret;
-}
-
-static int __write_to_stats_daemon(struct iovec* vec, size_t nr) {
- int save_errno;
- struct timespec ts;
- size_t len, i;
-
- for (len = i = 0; i < nr; ++i) {
- len += vec[i].iov_len;
- }
- if (!len) {
- return -EINVAL;
- }
-
- save_errno = errno;
-#if defined(__ANDROID__)
- clock_gettime(CLOCK_REALTIME, &ts);
-#else
- struct timeval tv;
- gettimeofday(&tv, NULL);
- ts.tv_sec = tv.tv_sec;
- ts.tv_nsec = tv.tv_usec * 1000;
-#endif
-
- int ret = (int)(*statsdLoggerWrite.write)(&ts, vec, nr);
- errno = save_errno;
- return ret;
-}
-
-static int __write_to_statsd_initialize_locked() {
- if (!statsdLoggerWrite.open || ((*statsdLoggerWrite.open)() < 0)) {
- if (statsdLoggerWrite.close) {
- (*statsdLoggerWrite.close)();
- return -ENODEV;
- }
- }
- return 1;
-}
-
-static int __write_to_statsd_init(struct iovec* vec, size_t nr) {
- int ret, save_errno = errno;
-
- statsd_writer_init_lock();
-
- if (__write_to_statsd == __write_to_statsd_init) {
- ret = __write_to_statsd_initialize_locked();
- if (ret < 0) {
- statsd_writer_init_unlock();
- errno = save_errno;
- return ret;
- }
-
- __write_to_statsd = __write_to_stats_daemon;
- }
-
- statsd_writer_init_unlock();
-
- ret = __write_to_statsd(vec, nr);
- errno = save_errno;
- return ret;
-}
diff --git a/libstats/socket/stats_event.c b/libstats/socket/stats_event.c
deleted file mode 100644
index dcd34aa..0000000
--- a/libstats/socket/stats_event.c
+++ /dev/null
@@ -1,356 +0,0 @@
-/*
- * 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.
- */
-
-#include "include/stats_event.h"
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include "stats_buffer_writer.h"
-
-#define LOGGER_ENTRY_MAX_PAYLOAD 4068
-// Max payload size is 4 bytes less as 4 bytes are reserved for stats_eventTag.
-// See android_util_Stats_Log.cpp
-#define MAX_PUSH_EVENT_PAYLOAD (LOGGER_ENTRY_MAX_PAYLOAD - 4)
-
-#define MAX_PULL_EVENT_PAYLOAD (50 * 1024) // 50 KB
-
-/* POSITIONS */
-#define POS_NUM_ELEMENTS 1
-#define POS_TIMESTAMP (POS_NUM_ELEMENTS + sizeof(uint8_t))
-#define POS_ATOM_ID (POS_TIMESTAMP + sizeof(uint8_t) + sizeof(uint64_t))
-
-/* LIMITS */
-#define MAX_ANNOTATION_COUNT 15
-#define MAX_BYTE_VALUE 127 // parsing side requires that lengths fit in 7 bits
-
-/* ERRORS */
-#define ERROR_NO_TIMESTAMP 0x1
-#define ERROR_NO_ATOM_ID 0x2
-#define ERROR_OVERFLOW 0x4
-#define ERROR_ATTRIBUTION_CHAIN_TOO_LONG 0x8
-#define ERROR_TOO_MANY_KEY_VALUE_PAIRS 0x10
-#define ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD 0x20
-#define ERROR_INVALID_ANNOTATION_ID 0x40
-#define ERROR_ANNOTATION_ID_TOO_LARGE 0x80
-#define ERROR_TOO_MANY_ANNOTATIONS 0x100
-#define ERROR_TOO_MANY_FIELDS 0x200
-#define ERROR_INVALID_VALUE_TYPE 0x400
-#define ERROR_STRING_NOT_NULL_TERMINATED 0x800
-#define ERROR_ATOM_ID_INVALID_POSITION 0x2000
-
-/* TYPE IDS */
-#define INT32_TYPE 0x00
-#define INT64_TYPE 0x01
-#define STRING_TYPE 0x02
-#define LIST_TYPE 0x03
-#define FLOAT_TYPE 0x04
-#define BOOL_TYPE 0x05
-#define BYTE_ARRAY_TYPE 0x06
-#define OBJECT_TYPE 0x07
-#define KEY_VALUE_PAIRS_TYPE 0x08
-#define ATTRIBUTION_CHAIN_TYPE 0x09
-#define ERROR_TYPE 0x0F
-
-// The AStatsEvent struct holds the serialized encoding of an event
-// within a buf. Also includes other required fields.
-struct AStatsEvent {
- uint8_t* buf;
- // Location of last field within the buf. Here, field denotes either a
- // metadata field (e.g. timestamp) or an atom field.
- size_t lastFieldPos;
- // Number of valid bytes within the buffer.
- size_t numBytesWritten;
- uint32_t numElements;
- uint32_t atomId;
- uint32_t errors;
- bool built;
- size_t bufSize;
-};
-
-static int64_t get_elapsed_realtime_ns() {
- struct timespec t;
- t.tv_sec = t.tv_nsec = 0;
- clock_gettime(CLOCK_BOOTTIME, &t);
- return (int64_t)t.tv_sec * 1000000000LL + t.tv_nsec;
-}
-
-AStatsEvent* AStatsEvent_obtain() {
- AStatsEvent* event = malloc(sizeof(AStatsEvent));
- event->lastFieldPos = 0;
- event->numBytesWritten = 2; // reserve first 2 bytes for root event type and number of elements
- event->numElements = 0;
- event->atomId = 0;
- event->errors = 0;
- event->built = false;
- event->bufSize = MAX_PUSH_EVENT_PAYLOAD;
- event->buf = (uint8_t*)calloc(event->bufSize, 1);
-
- event->buf[0] = OBJECT_TYPE;
- AStatsEvent_writeInt64(event, get_elapsed_realtime_ns()); // write the timestamp
-
- return event;
-}
-
-void AStatsEvent_release(AStatsEvent* event) {
- free(event->buf);
- free(event);
-}
-
-void AStatsEvent_setAtomId(AStatsEvent* event, uint32_t atomId) {
- if (event->atomId != 0) return;
- if (event->numElements != 1) {
- event->errors |= ERROR_ATOM_ID_INVALID_POSITION;
- return;
- }
-
- event->atomId = atomId;
- AStatsEvent_writeInt32(event, atomId);
-}
-
-// Overwrites the timestamp populated in AStatsEvent_obtain with a custom
-// timestamp. Should only be called from test code.
-void AStatsEvent_overwriteTimestamp(AStatsEvent* event, uint64_t timestampNs) {
- memcpy(&event->buf[POS_TIMESTAMP + sizeof(uint8_t)], ×tampNs, sizeof(timestampNs));
- // Do not increment numElements because we already accounted for the timestamp
- // within AStatsEvent_obtain.
-}
-
-// Side-effect: modifies event->errors if the buffer would overflow
-static bool overflows(AStatsEvent* event, size_t size) {
- const size_t totalBytesNeeded = event->numBytesWritten + size;
- if (totalBytesNeeded > MAX_PULL_EVENT_PAYLOAD) {
- event->errors |= ERROR_OVERFLOW;
- return true;
- }
-
- // Expand buffer if needed.
- if (event->bufSize < MAX_PULL_EVENT_PAYLOAD && totalBytesNeeded > event->bufSize) {
- do {
- event->bufSize *= 2;
- } while (event->bufSize <= totalBytesNeeded);
-
- if (event->bufSize > MAX_PULL_EVENT_PAYLOAD) {
- event->bufSize = MAX_PULL_EVENT_PAYLOAD;
- }
-
- event->buf = (uint8_t*)realloc(event->buf, event->bufSize);
- }
- return false;
-}
-
-// Side-effect: all append functions increment event->numBytesWritten if there is
-// sufficient space within the buffer to place the value
-static void append_byte(AStatsEvent* event, uint8_t value) {
- if (!overflows(event, sizeof(value))) {
- event->buf[event->numBytesWritten] = value;
- event->numBytesWritten += sizeof(value);
- }
-}
-
-static void append_bool(AStatsEvent* event, bool value) {
- append_byte(event, (uint8_t)value);
-}
-
-static void append_int32(AStatsEvent* event, int32_t value) {
- if (!overflows(event, sizeof(value))) {
- memcpy(&event->buf[event->numBytesWritten], &value, sizeof(value));
- event->numBytesWritten += sizeof(value);
- }
-}
-
-static void append_int64(AStatsEvent* event, int64_t value) {
- if (!overflows(event, sizeof(value))) {
- memcpy(&event->buf[event->numBytesWritten], &value, sizeof(value));
- event->numBytesWritten += sizeof(value);
- }
-}
-
-static void append_float(AStatsEvent* event, float value) {
- if (!overflows(event, sizeof(value))) {
- memcpy(&event->buf[event->numBytesWritten], &value, sizeof(value));
- event->numBytesWritten += sizeof(float);
- }
-}
-
-static void append_byte_array(AStatsEvent* event, const uint8_t* buf, size_t size) {
- if (!overflows(event, size)) {
- memcpy(&event->buf[event->numBytesWritten], buf, size);
- event->numBytesWritten += size;
- }
-}
-
-// Side-effect: modifies event->errors if buf is not properly null-terminated
-static void append_string(AStatsEvent* event, const char* buf) {
- size_t size = strnlen(buf, MAX_PULL_EVENT_PAYLOAD);
- if (size == MAX_PULL_EVENT_PAYLOAD) {
- event->errors |= ERROR_STRING_NOT_NULL_TERMINATED;
- return;
- }
-
- append_int32(event, size);
- append_byte_array(event, (uint8_t*)buf, size);
-}
-
-static void start_field(AStatsEvent* event, uint8_t typeId) {
- event->lastFieldPos = event->numBytesWritten;
- append_byte(event, typeId);
- event->numElements++;
-}
-
-void AStatsEvent_writeInt32(AStatsEvent* event, int32_t value) {
- start_field(event, INT32_TYPE);
- append_int32(event, value);
-}
-
-void AStatsEvent_writeInt64(AStatsEvent* event, int64_t value) {
- start_field(event, INT64_TYPE);
- append_int64(event, value);
-}
-
-void AStatsEvent_writeFloat(AStatsEvent* event, float value) {
- start_field(event, FLOAT_TYPE);
- append_float(event, value);
-}
-
-void AStatsEvent_writeBool(AStatsEvent* event, bool value) {
- start_field(event, BOOL_TYPE);
- append_bool(event, value);
-}
-
-void AStatsEvent_writeByteArray(AStatsEvent* event, const uint8_t* buf, size_t numBytes) {
- start_field(event, BYTE_ARRAY_TYPE);
- if (buf == NULL) {
- numBytes = 0;
- }
- append_int32(event, numBytes);
- if (numBytes > 0) {
- append_byte_array(event, buf, numBytes);
- }
-}
-
-// Value is assumed to be encoded using UTF8
-void AStatsEvent_writeString(AStatsEvent* event, const char* value) {
- start_field(event, STRING_TYPE);
- append_string(event, value == NULL ? "" : value);
-}
-
-// Tags are assumed to be encoded using UTF8
-void AStatsEvent_writeAttributionChain(AStatsEvent* event, const uint32_t* uids,
- const char* const* tags, uint8_t numNodes) {
- if (numNodes > MAX_BYTE_VALUE) {
- event->errors |= ERROR_ATTRIBUTION_CHAIN_TOO_LONG;
- return;
- }
-
- start_field(event, ATTRIBUTION_CHAIN_TYPE);
- append_byte(event, numNodes);
-
- for (uint8_t i = 0; i < numNodes; i++) {
- append_int32(event, uids[i]);
- append_string(event, tags[i] == NULL ? "" : tags[i]);
- }
-}
-
-// Side-effect: modifies event->errors if field has too many annotations
-static void increment_annotation_count(AStatsEvent* event) {
- uint8_t fieldType = event->buf[event->lastFieldPos] & 0x0F;
- uint32_t oldAnnotationCount = (event->buf[event->lastFieldPos] & 0xF0) >> 4;
- uint32_t newAnnotationCount = oldAnnotationCount + 1;
-
- if (newAnnotationCount > MAX_ANNOTATION_COUNT) {
- event->errors |= ERROR_TOO_MANY_ANNOTATIONS;
- return;
- }
-
- event->buf[event->lastFieldPos] = (((uint8_t)newAnnotationCount << 4) & 0xF0) | fieldType;
-}
-
-void AStatsEvent_addBoolAnnotation(AStatsEvent* event, uint8_t annotationId, bool value) {
- if (event->numElements < 2) {
- event->errors |= ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD;
- return;
- } else if (annotationId > MAX_BYTE_VALUE) {
- event->errors |= ERROR_ANNOTATION_ID_TOO_LARGE;
- return;
- }
-
- append_byte(event, annotationId);
- append_byte(event, BOOL_TYPE);
- append_bool(event, value);
- increment_annotation_count(event);
-}
-
-void AStatsEvent_addInt32Annotation(AStatsEvent* event, uint8_t annotationId, int32_t value) {
- if (event->numElements < 2) {
- event->errors |= ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD;
- return;
- } else if (annotationId > MAX_BYTE_VALUE) {
- event->errors |= ERROR_ANNOTATION_ID_TOO_LARGE;
- return;
- }
-
- append_byte(event, annotationId);
- append_byte(event, INT32_TYPE);
- append_int32(event, value);
- increment_annotation_count(event);
-}
-
-uint32_t AStatsEvent_getAtomId(AStatsEvent* event) {
- return event->atomId;
-}
-
-uint8_t* AStatsEvent_getBuffer(AStatsEvent* event, size_t* size) {
- if (size) *size = event->numBytesWritten;
- return event->buf;
-}
-
-uint32_t AStatsEvent_getErrors(AStatsEvent* event) {
- return event->errors;
-}
-
-static void build_internal(AStatsEvent* event, const bool push) {
- if (event->numElements > MAX_BYTE_VALUE) event->errors |= ERROR_TOO_MANY_FIELDS;
- if (0 == event->atomId) event->errors |= ERROR_NO_ATOM_ID;
- if (push && event->numBytesWritten > MAX_PUSH_EVENT_PAYLOAD) event->errors |= ERROR_OVERFLOW;
-
- // If there are errors, rewrite buffer.
- if (event->errors) {
- // Discard everything after the atom id (including atom-level
- // annotations). This leaves only two elements (timestamp and atom id).
- event->numElements = 2;
- // Reset number of atom-level annotations to 0.
- event->buf[POS_ATOM_ID] = INT32_TYPE;
- // Now, write errors to the buffer immediately after the atom id.
- event->numBytesWritten = POS_ATOM_ID + sizeof(uint8_t) + sizeof(uint32_t);
- start_field(event, ERROR_TYPE);
- append_int32(event, event->errors);
- }
-
- event->buf[POS_NUM_ELEMENTS] = event->numElements;
-}
-
-void AStatsEvent_build(AStatsEvent* event) {
- if (event->built) return;
-
- build_internal(event, false /* push */);
-
- event->built = true;
-}
-
-int AStatsEvent_write(AStatsEvent* event) {
- build_internal(event, true /* push */);
- return write_buffer_to_statsd(event->buf, event->numBytesWritten, event->atomId);
-}
diff --git a/libstats/socket/stats_socket.c b/libstats/socket/stats_socket.c
deleted file mode 100644
index 09f8967..0000000
--- a/libstats/socket/stats_socket.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * 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 "include/stats_socket.h"
-#include "stats_buffer_writer.h"
-
-void AStatsSocket_close() {
- stats_log_close();
-}
diff --git a/libstats/socket/statsd_writer.c b/libstats/socket/statsd_writer.c
deleted file mode 100644
index 73b7a7e..0000000
--- a/libstats/socket/statsd_writer.c
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * Copyright (C) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include "statsd_writer.h"
-
-#include <cutils/fs.h>
-#include <cutils/sockets.h>
-#include <cutils/threads.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <poll.h>
-#include <private/android_filesystem_config.h>
-#include <private/android_logger.h>
-#include <stdarg.h>
-#include <stdatomic.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <sys/un.h>
-#include <time.h>
-#include <unistd.h>
-
-static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER;
-static atomic_int dropped = 0;
-static atomic_int log_error = 0;
-static atomic_int atom_tag = 0;
-
-void statsd_writer_init_lock() {
- /*
- * If we trigger a signal handler in the middle of locked activity and the
- * signal handler logs a message, we could get into a deadlock state.
- */
- pthread_mutex_lock(&log_init_lock);
-}
-
-int statd_writer_trylock() {
- return pthread_mutex_trylock(&log_init_lock);
-}
-
-void statsd_writer_init_unlock() {
- pthread_mutex_unlock(&log_init_lock);
-}
-
-static int statsdAvailable();
-static int statsdOpen();
-static void statsdClose();
-static int statsdWrite(struct timespec* ts, struct iovec* vec, size_t nr);
-static void statsdNoteDrop();
-static int statsdIsClosed();
-
-struct android_log_transport_write statsdLoggerWrite = {
- .name = "statsd",
- .sock = -EBADF,
- .available = statsdAvailable,
- .open = statsdOpen,
- .close = statsdClose,
- .write = statsdWrite,
- .noteDrop = statsdNoteDrop,
- .isClosed = statsdIsClosed,
-};
-
-/* log_init_lock assumed */
-static int statsdOpen() {
- int i, ret = 0;
-
- i = atomic_load(&statsdLoggerWrite.sock);
- if (i < 0) {
- int flags = SOCK_DGRAM;
-#ifdef SOCK_CLOEXEC
- flags |= SOCK_CLOEXEC;
-#endif
-#ifdef SOCK_NONBLOCK
- flags |= SOCK_NONBLOCK;
-#endif
- int sock = TEMP_FAILURE_RETRY(socket(PF_UNIX, flags, 0));
- if (sock < 0) {
- ret = -errno;
- } else {
- int sndbuf = 1 * 1024 * 1024; // set max send buffer size 1MB
- socklen_t bufLen = sizeof(sndbuf);
- // SO_RCVBUF does not have an effect on unix domain socket, but SO_SNDBUF does.
- // Proceed to connect even setsockopt fails.
- setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sndbuf, bufLen);
- struct sockaddr_un un;
- memset(&un, 0, sizeof(struct sockaddr_un));
- un.sun_family = AF_UNIX;
- strcpy(un.sun_path, "/dev/socket/statsdw");
-
- if (TEMP_FAILURE_RETRY(
- connect(sock, (struct sockaddr*)&un, sizeof(struct sockaddr_un))) < 0) {
- ret = -errno;
- switch (ret) {
- case -ENOTCONN:
- case -ECONNREFUSED:
- case -ENOENT:
- i = atomic_exchange(&statsdLoggerWrite.sock, ret);
- /* FALLTHRU */
- default:
- break;
- }
- close(sock);
- } else {
- ret = atomic_exchange(&statsdLoggerWrite.sock, sock);
- if ((ret >= 0) && (ret != sock)) {
- close(ret);
- }
- ret = 0;
- }
- }
- }
-
- return ret;
-}
-
-static void __statsdClose(int negative_errno) {
- int sock = atomic_exchange(&statsdLoggerWrite.sock, negative_errno);
- if (sock >= 0) {
- close(sock);
- }
-}
-
-static void statsdClose() {
- __statsdClose(-EBADF);
-}
-
-static int statsdAvailable() {
- if (atomic_load(&statsdLoggerWrite.sock) < 0) {
- if (access("/dev/socket/statsdw", W_OK) == 0) {
- return 0;
- }
- return -EBADF;
- }
- return 1;
-}
-
-static void statsdNoteDrop(int error, int tag) {
- atomic_fetch_add_explicit(&dropped, 1, memory_order_relaxed);
- atomic_exchange_explicit(&log_error, error, memory_order_relaxed);
- atomic_exchange_explicit(&atom_tag, tag, memory_order_relaxed);
-}
-
-static int statsdIsClosed() {
- if (atomic_load(&statsdLoggerWrite.sock) < 0) {
- return 1;
- }
- return 0;
-}
-
-static int statsdWrite(struct timespec* ts, struct iovec* vec, size_t nr) {
- ssize_t ret;
- int sock;
- static const unsigned headerLength = 1;
- struct iovec newVec[nr + headerLength];
- android_log_header_t header;
- size_t i, payloadSize;
-
- sock = atomic_load(&statsdLoggerWrite.sock);
- if (sock < 0) switch (sock) {
- case -ENOTCONN:
- case -ECONNREFUSED:
- case -ENOENT:
- break;
- default:
- return -EBADF;
- }
- /*
- * struct {
- * // what we provide to socket
- * android_log_header_t header;
- * // caller provides
- * union {
- * struct {
- * char prio;
- * char payload[];
- * } string;
- * struct {
- * uint32_t tag
- * char payload[];
- * } binary;
- * };
- * };
- */
-
- header.tid = gettid();
- header.realtime.tv_sec = ts->tv_sec;
- header.realtime.tv_nsec = ts->tv_nsec;
-
- newVec[0].iov_base = (unsigned char*)&header;
- newVec[0].iov_len = sizeof(header);
-
- // If we dropped events before, try to tell statsd.
- if (sock >= 0) {
- int32_t snapshot = atomic_exchange_explicit(&dropped, 0, memory_order_relaxed);
- if (snapshot) {
- android_log_event_long_t buffer;
- header.id = LOG_ID_STATS;
- // store the last log error in the tag field. This tag field is not used by statsd.
- buffer.header.tag = atomic_load(&log_error);
- buffer.payload.type = EVENT_TYPE_LONG;
- // format:
- // |atom_tag|dropped_count|
- int64_t composed_long = atomic_load(&atom_tag);
- // Send 2 int32's via an int64.
- composed_long = ((composed_long << 32) | ((int64_t)snapshot));
- buffer.payload.data = composed_long;
-
- newVec[headerLength].iov_base = &buffer;
- newVec[headerLength].iov_len = sizeof(buffer);
-
- ret = TEMP_FAILURE_RETRY(writev(sock, newVec, 2));
- if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
- atomic_fetch_add_explicit(&dropped, snapshot, memory_order_relaxed);
- }
- }
- }
-
- header.id = LOG_ID_STATS;
-
- for (payloadSize = 0, i = headerLength; i < nr + headerLength; i++) {
- newVec[i].iov_base = vec[i - headerLength].iov_base;
- payloadSize += newVec[i].iov_len = vec[i - headerLength].iov_len;
-
- if (payloadSize > LOGGER_ENTRY_MAX_PAYLOAD) {
- newVec[i].iov_len -= payloadSize - LOGGER_ENTRY_MAX_PAYLOAD;
- if (newVec[i].iov_len) {
- ++i;
- }
- break;
- }
- }
-
- /*
- * The write below could be lost, but will never block.
- *
- * ENOTCONN occurs if statsd has died.
- * ENOENT occurs if statsd is not running and socket is missing.
- * ECONNREFUSED occurs if we can not reconnect to statsd.
- * EAGAIN occurs if statsd is overloaded.
- */
- if (sock < 0) {
- ret = sock;
- } else {
- ret = TEMP_FAILURE_RETRY(writev(sock, newVec, i));
- if (ret < 0) {
- ret = -errno;
- }
- }
- switch (ret) {
- case -ENOTCONN:
- case -ECONNREFUSED:
- case -ENOENT:
- if (statd_writer_trylock()) {
- return ret; /* in a signal handler? try again when less stressed
- */
- }
- __statsdClose(ret);
- ret = statsdOpen();
- statsd_writer_init_unlock();
-
- if (ret < 0) {
- return ret;
- }
-
- ret = TEMP_FAILURE_RETRY(writev(atomic_load(&statsdLoggerWrite.sock), newVec, i));
- if (ret < 0) {
- ret = -errno;
- }
- /* FALLTHRU */
- default:
- break;
- }
-
- if (ret > (ssize_t)sizeof(header)) {
- ret -= sizeof(header);
- }
-
- return ret;
-}
diff --git a/libstats/socket/statsd_writer.h b/libstats/socket/statsd_writer.h
deleted file mode 100644
index 562bda5..0000000
--- a/libstats/socket/statsd_writer.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_STATS_LOG_STATS_WRITER_H
-#define ANDROID_STATS_LOG_STATS_WRITER_H
-
-#include <pthread.h>
-#include <stdatomic.h>
-#include <sys/socket.h>
-
-/**
- * Internal lock should not be exposed. This is bad design.
- * TODO: rewrite it in c++ code and encapsulate the functionality in a
- * StatsdWriter class.
- */
-void statsd_writer_init_lock();
-int statsd_writer_init_trylock();
-void statsd_writer_init_unlock();
-
-struct android_log_transport_write {
- const char* name; /* human name to describe the transport */
- atomic_int sock;
- int (*available)(); /* Does not cause resources to be taken */
- int (*open)(); /* can be called multiple times, reusing current resources */
- void (*close)(); /* free up resources */
- /* write log to transport, returns number of bytes propagated, or -errno */
- int (*write)(struct timespec* ts, struct iovec* vec, size_t nr);
- /* note one log drop */
- void (*noteDrop)(int error, int tag);
- /* checks if the socket is closed */
- int (*isClosed)();
-};
-
-#endif // ANDROID_STATS_LOG_STATS_WRITER_H
diff --git a/libstats/socket/tests/stats_event_test.cpp b/libstats/socket/tests/stats_event_test.cpp
deleted file mode 100644
index 2f9ccdc..0000000
--- a/libstats/socket/tests/stats_event_test.cpp
+++ /dev/null
@@ -1,516 +0,0 @@
-/*
- * 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.
- */
-
-#include "stats_event.h"
-#include <gtest/gtest.h>
-#include <utils/SystemClock.h>
-
-// Keep in sync with stats_event.c. Consider moving to separate header file to avoid duplication.
-/* ERRORS */
-#define ERROR_NO_TIMESTAMP 0x1
-#define ERROR_NO_ATOM_ID 0x2
-#define ERROR_OVERFLOW 0x4
-#define ERROR_ATTRIBUTION_CHAIN_TOO_LONG 0x8
-#define ERROR_TOO_MANY_KEY_VALUE_PAIRS 0x10
-#define ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD 0x20
-#define ERROR_INVALID_ANNOTATION_ID 0x40
-#define ERROR_ANNOTATION_ID_TOO_LARGE 0x80
-#define ERROR_TOO_MANY_ANNOTATIONS 0x100
-#define ERROR_TOO_MANY_FIELDS 0x200
-#define ERROR_INVALID_VALUE_TYPE 0x400
-#define ERROR_STRING_NOT_NULL_TERMINATED 0x800
-#define ERROR_ATOM_ID_INVALID_POSITION 0x2000
-
-/* TYPE IDS */
-#define INT32_TYPE 0x00
-#define INT64_TYPE 0x01
-#define STRING_TYPE 0x02
-#define LIST_TYPE 0x03
-#define FLOAT_TYPE 0x04
-#define BOOL_TYPE 0x05
-#define BYTE_ARRAY_TYPE 0x06
-#define OBJECT_TYPE 0x07
-#define KEY_VALUE_PAIRS_TYPE 0x08
-#define ATTRIBUTION_CHAIN_TYPE 0x09
-#define ERROR_TYPE 0x0F
-
-using std::string;
-using std::vector;
-
-// Side-effect: this function moves the start of the buffer past the read value
-template <class T>
-T readNext(uint8_t** buffer) {
- T value;
- if ((reinterpret_cast<uintptr_t>(*buffer) % alignof(T)) == 0) {
- value = *(T*)(*buffer);
- } else {
- memcpy(&value, *buffer, sizeof(T));
- }
- *buffer += sizeof(T);
- return value;
-}
-
-void checkTypeHeader(uint8_t** buffer, uint8_t typeId, uint8_t numAnnotations = 0) {
- uint8_t typeHeader = (numAnnotations << 4) | typeId;
- EXPECT_EQ(readNext<uint8_t>(buffer), typeHeader);
-}
-
-template <class T>
-void checkScalar(uint8_t** buffer, T expectedValue) {
- EXPECT_EQ(readNext<T>(buffer), expectedValue);
-}
-
-void checkString(uint8_t** buffer, const string& expectedString) {
- uint32_t size = readNext<uint32_t>(buffer);
- string parsedString((char*)(*buffer), size);
- EXPECT_EQ(parsedString, expectedString);
- *buffer += size; // move buffer past string we just read
-}
-
-void checkByteArray(uint8_t** buffer, const vector<uint8_t>& expectedByteArray) {
- uint32_t size = readNext<uint32_t>(buffer);
- vector<uint8_t> parsedByteArray(*buffer, *buffer + size);
- EXPECT_EQ(parsedByteArray, expectedByteArray);
- *buffer += size; // move buffer past byte array we just read
-}
-
-template <class T>
-void checkAnnotation(uint8_t** buffer, uint8_t annotationId, uint8_t typeId, T annotationValue) {
- EXPECT_EQ(readNext<uint8_t>(buffer), annotationId);
- EXPECT_EQ(readNext<uint8_t>(buffer), typeId);
- checkScalar<T>(buffer, annotationValue);
-}
-
-void checkMetadata(uint8_t** buffer, uint8_t numElements, int64_t startTime, int64_t endTime,
- uint32_t atomId, uint8_t numAtomLevelAnnotations = 0) {
- // All events start with OBJECT_TYPE id.
- checkTypeHeader(buffer, OBJECT_TYPE);
-
- // We increment by 2 because the number of elements listed in the
- // serialization accounts for the timestamp and atom id as well.
- checkScalar(buffer, static_cast<uint8_t>(numElements + 2));
-
- // Check timestamp
- checkTypeHeader(buffer, INT64_TYPE);
- int64_t timestamp = readNext<int64_t>(buffer);
- EXPECT_GE(timestamp, startTime);
- EXPECT_LE(timestamp, endTime);
-
- // Check atom id
- checkTypeHeader(buffer, INT32_TYPE, numAtomLevelAnnotations);
- checkScalar(buffer, atomId);
-}
-
-TEST(StatsEventTest, TestScalars) {
- uint32_t atomId = 100;
- int32_t int32Value = -5;
- int64_t int64Value = -2 * android::elapsedRealtimeNano();
- float floatValue = 2.0;
- bool boolValue = false;
-
- int64_t startTime = android::elapsedRealtimeNano();
- AStatsEvent* event = AStatsEvent_obtain();
- AStatsEvent_setAtomId(event, atomId);
- AStatsEvent_writeInt32(event, int32Value);
- AStatsEvent_writeInt64(event, int64Value);
- AStatsEvent_writeFloat(event, floatValue);
- AStatsEvent_writeBool(event, boolValue);
- AStatsEvent_build(event);
- int64_t endTime = android::elapsedRealtimeNano();
-
- size_t bufferSize;
- uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
- uint8_t* bufferEnd = buffer + bufferSize;
-
- checkMetadata(&buffer, /*numElements=*/4, startTime, endTime, atomId);
-
- // check int32 element
- checkTypeHeader(&buffer, INT32_TYPE);
- checkScalar(&buffer, int32Value);
-
- // check int64 element
- checkTypeHeader(&buffer, INT64_TYPE);
- checkScalar(&buffer, int64Value);
-
- // check float element
- checkTypeHeader(&buffer, FLOAT_TYPE);
- checkScalar(&buffer, floatValue);
-
- // check bool element
- checkTypeHeader(&buffer, BOOL_TYPE);
- checkScalar(&buffer, boolValue);
-
- EXPECT_EQ(buffer, bufferEnd); // ensure that we have read the entire buffer
- EXPECT_EQ(AStatsEvent_getErrors(event), 0);
- AStatsEvent_release(event);
-}
-
-TEST(StatsEventTest, TestStrings) {
- uint32_t atomId = 100;
- string str = "test_string";
-
- int64_t startTime = android::elapsedRealtimeNano();
- AStatsEvent* event = AStatsEvent_obtain();
- AStatsEvent_setAtomId(event, atomId);
- AStatsEvent_writeString(event, str.c_str());
- AStatsEvent_build(event);
- int64_t endTime = android::elapsedRealtimeNano();
-
- size_t bufferSize;
- uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
- uint8_t* bufferEnd = buffer + bufferSize;
-
- checkMetadata(&buffer, /*numElements=*/1, startTime, endTime, atomId);
-
- checkTypeHeader(&buffer, STRING_TYPE);
- checkString(&buffer, str);
-
- EXPECT_EQ(buffer, bufferEnd); // ensure that we have read the entire buffer
- EXPECT_EQ(AStatsEvent_getErrors(event), 0);
- AStatsEvent_release(event);
-}
-
-TEST(StatsEventTest, TestNullString) {
- uint32_t atomId = 100;
- char* str = nullptr;
-
- int64_t startTime = android::elapsedRealtimeNano();
- AStatsEvent* event = AStatsEvent_obtain();
- AStatsEvent_setAtomId(event, atomId);
- AStatsEvent_writeString(event, str);
- AStatsEvent_build(event);
- int64_t endTime = android::elapsedRealtimeNano();
-
- size_t bufferSize;
- uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
- uint8_t* bufferEnd = buffer + bufferSize;
-
- checkMetadata(&buffer, /*numElements=*/1, startTime, endTime, atomId);
-
- checkTypeHeader(&buffer, STRING_TYPE);
- checkString(&buffer, "");
-
- EXPECT_EQ(buffer, bufferEnd); // ensure that we have read the entire buffer
- EXPECT_EQ(AStatsEvent_getErrors(event), 0);
- AStatsEvent_release(event);
-}
-
-TEST(StatsEventTest, TestByteArrays) {
- uint32_t atomId = 100;
- vector<uint8_t> message = {'b', 'y', 't', '\0', 'e', 's'};
-
- int64_t startTime = android::elapsedRealtimeNano();
- AStatsEvent* event = AStatsEvent_obtain();
- AStatsEvent_setAtomId(event, atomId);
- AStatsEvent_writeByteArray(event, message.data(), message.size());
- AStatsEvent_build(event);
- int64_t endTime = android::elapsedRealtimeNano();
-
- size_t bufferSize;
- uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
- uint8_t* bufferEnd = buffer + bufferSize;
-
- checkMetadata(&buffer, /*numElements=*/1, startTime, endTime, atomId);
-
- checkTypeHeader(&buffer, BYTE_ARRAY_TYPE);
- checkByteArray(&buffer, message);
-
- EXPECT_EQ(buffer, bufferEnd); // ensure that we have read the entire buffer
- EXPECT_EQ(AStatsEvent_getErrors(event), 0);
- AStatsEvent_release(event);
-}
-
-TEST(StatsEventTest, TestNullByteArrays) {
- uint32_t atomId = 100;
- uint8_t* buf = nullptr;
- vector<uint8_t> message;
-
- int64_t startTime = android::elapsedRealtimeNano();
- AStatsEvent* event = AStatsEvent_obtain();
- AStatsEvent_setAtomId(event, atomId);
- AStatsEvent_writeByteArray(event, buf, 2);
- AStatsEvent_build(event);
- int64_t endTime = android::elapsedRealtimeNano();
-
- size_t bufferSize;
- uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
- uint8_t* bufferEnd = buffer + bufferSize;
-
- checkMetadata(&buffer, /*numElements=*/1, startTime, endTime, atomId);
-
- checkTypeHeader(&buffer, BYTE_ARRAY_TYPE);
- checkByteArray(&buffer, message);
-
- EXPECT_EQ(buffer, bufferEnd); // ensure that we have read the entire buffer
- EXPECT_EQ(AStatsEvent_getErrors(event), 0);
- AStatsEvent_release(event);
-}
-
-TEST(StatsEventTest, TestAttributionChains) {
- uint32_t atomId = 100;
-
- uint8_t numNodes = 50;
- uint32_t uids[numNodes];
- vector<string> tags(numNodes); // storage that cTag elements point to
- const char* cTags[numNodes];
- for (int i = 0; i < (int)numNodes; i++) {
- uids[i] = i;
- if (0 == i) {
- tags.push_back("");
- cTags[i] = nullptr;
- } else {
- tags.push_back("test" + std::to_string(i));
- cTags[i] = tags[i].c_str();
- }
- }
-
- int64_t startTime = android::elapsedRealtimeNano();
- AStatsEvent* event = AStatsEvent_obtain();
- AStatsEvent_setAtomId(event, atomId);
- AStatsEvent_writeAttributionChain(event, uids, cTags, numNodes);
- AStatsEvent_build(event);
- int64_t endTime = android::elapsedRealtimeNano();
-
- size_t bufferSize;
- uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
- uint8_t* bufferEnd = buffer + bufferSize;
-
- checkMetadata(&buffer, /*numElements=*/1, startTime, endTime, atomId);
-
- checkTypeHeader(&buffer, ATTRIBUTION_CHAIN_TYPE);
- checkScalar(&buffer, numNodes);
- for (int i = 0; i < numNodes; i++) {
- checkScalar(&buffer, uids[i]);
- checkString(&buffer, tags[i]);
- }
-
- EXPECT_EQ(buffer, bufferEnd); // ensure that we have read the entire buffer
- EXPECT_EQ(AStatsEvent_getErrors(event), 0);
- AStatsEvent_release(event);
-}
-
-TEST(StatsEventTest, TestFieldAnnotations) {
- uint32_t atomId = 100;
-
- // first element information
- bool boolValue = false;
- uint8_t boolAnnotation1Id = 1;
- uint8_t boolAnnotation2Id = 2;
- bool boolAnnotation1Value = true;
- int32_t boolAnnotation2Value = 3;
-
- // second element information
- float floatValue = -5.0;
- uint8_t floatAnnotation1Id = 3;
- uint8_t floatAnnotation2Id = 4;
- int32_t floatAnnotation1Value = 8;
- bool floatAnnotation2Value = false;
-
- int64_t startTime = android::elapsedRealtimeNano();
- AStatsEvent* event = AStatsEvent_obtain();
- AStatsEvent_setAtomId(event, atomId);
- AStatsEvent_writeBool(event, boolValue);
- AStatsEvent_addBoolAnnotation(event, boolAnnotation1Id, boolAnnotation1Value);
- AStatsEvent_addInt32Annotation(event, boolAnnotation2Id, boolAnnotation2Value);
- AStatsEvent_writeFloat(event, floatValue);
- AStatsEvent_addInt32Annotation(event, floatAnnotation1Id, floatAnnotation1Value);
- AStatsEvent_addBoolAnnotation(event, floatAnnotation2Id, floatAnnotation2Value);
- AStatsEvent_build(event);
- int64_t endTime = android::elapsedRealtimeNano();
-
- size_t bufferSize;
- uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
- uint8_t* bufferEnd = buffer + bufferSize;
-
- checkMetadata(&buffer, /*numElements=*/2, startTime, endTime, atomId);
-
- // check first element
- checkTypeHeader(&buffer, BOOL_TYPE, /*numAnnotations=*/2);
- checkScalar(&buffer, boolValue);
- checkAnnotation(&buffer, boolAnnotation1Id, BOOL_TYPE, boolAnnotation1Value);
- checkAnnotation(&buffer, boolAnnotation2Id, INT32_TYPE, boolAnnotation2Value);
-
- // check second element
- checkTypeHeader(&buffer, FLOAT_TYPE, /*numAnnotations=*/2);
- checkScalar(&buffer, floatValue);
- checkAnnotation(&buffer, floatAnnotation1Id, INT32_TYPE, floatAnnotation1Value);
- checkAnnotation(&buffer, floatAnnotation2Id, BOOL_TYPE, floatAnnotation2Value);
-
- EXPECT_EQ(buffer, bufferEnd); // ensure that we have read the entire buffer
- EXPECT_EQ(AStatsEvent_getErrors(event), 0);
- AStatsEvent_release(event);
-}
-
-TEST(StatsEventTest, TestAtomLevelAnnotations) {
- uint32_t atomId = 100;
- // atom-level annotation information
- uint8_t boolAnnotationId = 1;
- uint8_t int32AnnotationId = 2;
- bool boolAnnotationValue = false;
- int32_t int32AnnotationValue = 5;
-
- float fieldValue = -3.5;
-
- int64_t startTime = android::elapsedRealtimeNano();
- AStatsEvent* event = AStatsEvent_obtain();
- AStatsEvent_setAtomId(event, atomId);
- AStatsEvent_addBoolAnnotation(event, boolAnnotationId, boolAnnotationValue);
- AStatsEvent_addInt32Annotation(event, int32AnnotationId, int32AnnotationValue);
- AStatsEvent_writeFloat(event, fieldValue);
- AStatsEvent_build(event);
- int64_t endTime = android::elapsedRealtimeNano();
-
- size_t bufferSize;
- uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
- uint8_t* bufferEnd = buffer + bufferSize;
-
- checkMetadata(&buffer, /*numElements=*/1, startTime, endTime, atomId,
- /*numAtomLevelAnnotations=*/2);
-
- // check atom-level annotations
- checkAnnotation(&buffer, boolAnnotationId, BOOL_TYPE, boolAnnotationValue);
- checkAnnotation(&buffer, int32AnnotationId, INT32_TYPE, int32AnnotationValue);
-
- // check first element
- checkTypeHeader(&buffer, FLOAT_TYPE);
- checkScalar(&buffer, fieldValue);
-
- EXPECT_EQ(buffer, bufferEnd); // ensure that we have read the entire buffer
- EXPECT_EQ(AStatsEvent_getErrors(event), 0);
- AStatsEvent_release(event);
-}
-
-TEST(StatsEventTest, TestNoAtomIdError) {
- AStatsEvent* event = AStatsEvent_obtain();
- // Don't set the atom id in order to trigger the error.
- AStatsEvent_build(event);
-
- uint32_t errors = AStatsEvent_getErrors(event);
- EXPECT_EQ(errors & ERROR_NO_ATOM_ID, ERROR_NO_ATOM_ID);
-
- AStatsEvent_release(event);
-}
-
-TEST(StatsEventTest, TestPushOverflowError) {
- const char* str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
- const int writeCount = 120; // Number of times to write str in the event.
-
- AStatsEvent* event = AStatsEvent_obtain();
- AStatsEvent_setAtomId(event, 100);
-
- // Add str to the event 120 times. Each str takes >35 bytes so this will
- // overflow the 4068 byte buffer.
- // We want to keep writeCount less than 127 to avoid hitting
- // ERROR_TOO_MANY_FIELDS.
- for (int i = 0; i < writeCount; i++) {
- AStatsEvent_writeString(event, str);
- }
- AStatsEvent_write(event);
-
- uint32_t errors = AStatsEvent_getErrors(event);
- EXPECT_EQ(errors & ERROR_OVERFLOW, ERROR_OVERFLOW);
-
- AStatsEvent_release(event);
-}
-
-TEST(StatsEventTest, TestPullOverflowError) {
- const uint32_t atomId = 10100;
- const vector<uint8_t> bytes(430 /* number of elements */, 1 /* value of each element */);
- const int writeCount = 120; // Number of times to write bytes in the event.
-
- AStatsEvent* event = AStatsEvent_obtain();
- AStatsEvent_setAtomId(event, atomId);
-
- // Add bytes to the event 120 times. Size of bytes is 430 so this will
- // overflow the 50 KB pulled event buffer.
- // We want to keep writeCount less than 127 to avoid hitting
- // ERROR_TOO_MANY_FIELDS.
- for (int i = 0; i < writeCount; i++) {
- AStatsEvent_writeByteArray(event, bytes.data(), bytes.size());
- }
- AStatsEvent_build(event);
-
- uint32_t errors = AStatsEvent_getErrors(event);
- EXPECT_EQ(errors & ERROR_OVERFLOW, ERROR_OVERFLOW);
-
- AStatsEvent_release(event);
-}
-
-TEST(StatsEventTest, TestLargePull) {
- const uint32_t atomId = 100;
- const string str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
- const int writeCount = 120; // Number of times to write str in the event.
- const int64_t startTime = android::elapsedRealtimeNano();
-
- AStatsEvent* event = AStatsEvent_obtain();
- AStatsEvent_setAtomId(event, atomId);
-
- // Add str to the event 120 times.
- // We want to keep writeCount less than 127 to avoid hitting
- // ERROR_TOO_MANY_FIELDS.
- for (int i = 0; i < writeCount; i++) {
- AStatsEvent_writeString(event, str.c_str());
- }
- AStatsEvent_build(event);
- int64_t endTime = android::elapsedRealtimeNano();
-
- size_t bufferSize;
- uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
- uint8_t* bufferEnd = buffer + bufferSize;
-
- checkMetadata(&buffer, writeCount, startTime, endTime, atomId);
-
- // Check all instances of str have been written.
- for (int i = 0; i < writeCount; i++) {
- checkTypeHeader(&buffer, STRING_TYPE);
- checkString(&buffer, str);
- }
-
- EXPECT_EQ(buffer, bufferEnd); // Ensure that we have read the entire buffer.
- EXPECT_EQ(AStatsEvent_getErrors(event), 0);
- AStatsEvent_release(event);
-}
-
-TEST(StatsEventTest, TestAtomIdInvalidPositionError) {
- AStatsEvent* event = AStatsEvent_obtain();
- AStatsEvent_writeInt32(event, 0);
- AStatsEvent_setAtomId(event, 100);
- AStatsEvent_writeBool(event, true);
- AStatsEvent_build(event);
-
- uint32_t errors = AStatsEvent_getErrors(event);
- EXPECT_EQ(errors & ERROR_ATOM_ID_INVALID_POSITION, ERROR_ATOM_ID_INVALID_POSITION);
-
- AStatsEvent_release(event);
-}
-
-TEST(StatsEventTest, TestOverwriteTimestamp) {
- uint32_t atomId = 100;
- int64_t expectedTimestamp = 0x123456789;
- AStatsEvent* event = AStatsEvent_obtain();
- AStatsEvent_setAtomId(event, atomId);
- AStatsEvent_overwriteTimestamp(event, expectedTimestamp);
- AStatsEvent_build(event);
-
- uint8_t* buffer = AStatsEvent_getBuffer(event, NULL);
-
- // Make sure that the timestamp is being overwritten.
- checkMetadata(&buffer, /*numElements=*/0, /*startTime=*/expectedTimestamp,
- /*endTime=*/expectedTimestamp, atomId);
-
- EXPECT_EQ(AStatsEvent_getErrors(event), 0);
- AStatsEvent_release(event);
-}
diff --git a/libstats/socket/tests/stats_writer_test.cpp b/libstats/socket/tests/stats_writer_test.cpp
deleted file mode 100644
index 749599f..0000000
--- a/libstats/socket/tests/stats_writer_test.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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 <gtest/gtest.h>
-#include "stats_buffer_writer.h"
-#include "stats_event.h"
-#include "stats_socket.h"
-
-TEST(StatsWriterTest, TestSocketClose) {
- AStatsEvent* event = AStatsEvent_obtain();
- AStatsEvent_setAtomId(event, 100);
- AStatsEvent_writeInt32(event, 5);
- int successResult = AStatsEvent_write(event);
- AStatsEvent_release(event);
-
- // In the case of a successful write, we return the number of bytes written.
- EXPECT_GT(successResult, 0);
- EXPECT_FALSE(stats_log_is_closed());
-
- AStatsSocket_close();
-
- EXPECT_TRUE(stats_log_is_closed());
-}
diff --git a/storaged/include/storaged.h b/storaged/include/storaged.h
index 6f92048..79b5d41 100644
--- a/storaged/include/storaged.h
+++ b/storaged/include/storaged.h
@@ -86,6 +86,7 @@
sp<android::hardware::health::V2_0::IHealth> health;
unique_ptr<storage_info_t> storage_info;
static const uint32_t current_version;
+ Mutex proto_lock;
unordered_map<userid_t, bool> proto_loaded;
void load_proto(userid_t user_id);
char* prepare_proto(userid_t user_id, StoragedProto* proto);
diff --git a/storaged/storaged.cpp b/storaged/storaged.cpp
index 573b8c5..b7aa89f 100644
--- a/storaged/storaged.cpp
+++ b/storaged/storaged.cpp
@@ -162,6 +162,8 @@
}
void storaged_t::add_user_ce(userid_t user_id) {
+ Mutex::Autolock _l(proto_lock);
+
if (!proto_loaded[user_id]) {
load_proto(user_id);
proto_loaded[user_id] = true;
@@ -169,6 +171,8 @@
}
void storaged_t::remove_user_ce(userid_t user_id) {
+ Mutex::Autolock _l(proto_lock);
+
proto_loaded[user_id] = false;
mUidm.clear_user_history(user_id);
RemoveFileIfExists(proto_path(user_id), nullptr);
@@ -298,6 +302,8 @@
}
void storaged_t::flush_protos(unordered_map<int, StoragedProto>* protos) {
+ Mutex::Autolock _l(proto_lock);
+
for (auto& it : *protos) {
/*
* Don't flush proto if we haven't attempted to load it from file.