diff options
author | Baligh Uddin <baligh@google.com> | 2020-12-10 13:37:57 +0000 |
---|---|---|
committer | Baligh Uddin <baligh@google.com> | 2020-12-10 19:10:43 +0000 |
commit | 10012754a8c868b3654df02923ef49e3d46ff3d1 (patch) | |
tree | 7700fb81d8a500b85ff1c7596ae7a6ae3d4ffcce | |
parent | 995db46b894f5cbc6ced417961b34cd2d15f538a (diff) | |
download | core-android11-mainline-os-statsd-release.tar.gz |
Migrate to packages/modules/StatsD/lib/*android-mainline-11.0.0_r44android-mainline-11.0.0_r23android-mainline-11.0.0_r15android11-mainline-os-statsd-releaseandroid11-mainline-extservices-release
BUG: 167962588
Test: TH
Merged-In: I536a324182f70725a5fda0c36f7f9d4676fd49b9
Change-Id: I8b4ceadcdd0777468b6aaa3b8a57e765f19fb781
Exempt-From-Owner-Approval: Code Migration / Cleanup
22 files changed, 0 insertions, 2516 deletions
diff --git a/libstats/pull/Android.bp b/libstats/pull/Android.bp deleted file mode 100644 index 6d6b46622..000000000 --- a/libstats/pull/Android.bp +++ /dev/null @@ -1,111 +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", - "//packages/modules/StatsD/apex/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 7855774a7..000000000 --- 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 76f4f0271..000000000 --- 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 17df58435..000000000 --- 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 e0e851a15..000000000 --- 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 233fc1f18..000000000 --- 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 478cae760..000000000 --- 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 abc8e47af..000000000 --- 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 c39d4751b..000000000 --- a/libstats/socket/Android.bp +++ /dev/null @@ -1,126 +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", - "//packages/modules/StatsD/apex/tests/libstatspull", - "//packages/modules/StatsD/bin", - ], -} - -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 0224998f5..000000000 --- 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 5b41f0e04..000000000 --- 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 3d3baf9cf..000000000 --- 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 5a75fc021..000000000 --- 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 5c1390419..000000000 --- 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 d2694d1dd..000000000 --- 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 549acdc8e..000000000 --- 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 dcd34aaa8..000000000 --- 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 09f8967b0..000000000 --- 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 73b7a7e71..000000000 --- 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 562bda5df..000000000 --- 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 2f9ccdc5c..000000000 --- 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 749599ff3..000000000 --- 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()); -} |