diff options
| -rw-r--r-- | Android.bp | 1 | ||||
| -rw-r--r-- | cmds/statsd/Android.bp | 1 | ||||
| -rw-r--r-- | cmds/statsd/src/StatsService.cpp | 18 | ||||
| -rw-r--r-- | cmds/statsd/src/StatsService.h | 13 | ||||
| -rw-r--r-- | cmds/statsd/src/external/StatsCallbackPuller.cpp | 61 | ||||
| -rw-r--r-- | cmds/statsd/src/external/StatsCallbackPuller.h | 38 | ||||
| -rw-r--r-- | cmds/statsd/src/external/StatsPuller.cpp | 2 | ||||
| -rw-r--r-- | cmds/statsd/src/external/StatsPullerManager.cpp | 28 | ||||
| -rw-r--r-- | cmds/statsd/src/external/StatsPullerManager.h | 8 | ||||
| -rw-r--r-- | cmds/statsd/src/guardrail/StatsdStats.cpp | 17 | ||||
| -rw-r--r-- | cmds/statsd/src/guardrail/StatsdStats.h | 13 | ||||
| -rw-r--r-- | cmds/statsd/src/stats_log.proto | 2 | ||||
| -rw-r--r-- | cmds/statsd/src/stats_log_util.cpp | 6 | ||||
| -rw-r--r-- | cmds/statsd/tests/guardrail/StatsdStats_test.cpp | 6 | ||||
| -rw-r--r-- | core/java/android/app/StatsManager.java | 34 | ||||
| -rw-r--r-- | core/java/android/os/IStatsManager.aidl | 18 | ||||
| -rw-r--r-- | core/java/android/os/IStatsPullerCallback.aidl | 35 | ||||
| -rw-r--r-- | core/java/android/os/StatsLogEventWrapper.java | 78 |
18 files changed, 366 insertions, 13 deletions
diff --git a/Android.bp b/Android.bp index 7bdedc79943d..0848d2b7668e 100644 --- a/Android.bp +++ b/Android.bp @@ -804,6 +804,7 @@ filegroup { srcs: [ "core/java/android/os/IStatsCompanionService.aidl", "core/java/android/os/IStatsManager.aidl", + "core/java/android/os/IStatsPullerCallback.aidl", ], } diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp index d6f045ea43fd..faf2053835fa 100644 --- a/cmds/statsd/Android.bp +++ b/cmds/statsd/Android.bp @@ -71,6 +71,7 @@ cc_defaults { "src/external/Perfetto.cpp", "src/external/Perfprofd.cpp", "src/external/StatsPuller.cpp", + "src/external/StatsCallbackPuller.cpp", "src/external/StatsCompanionServicePuller.cpp", "src/external/SubsystemSleepStatePuller.cpp", "src/external/PowerStatsPuller.cpp", diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp index 86bf3eca3ee6..bd21a955729d 100644 --- a/cmds/statsd/src/StatsService.cpp +++ b/cmds/statsd/src/StatsService.cpp @@ -1057,6 +1057,24 @@ Status StatsService::sendAppBreadcrumbAtom(int32_t label, int32_t state) { return Status::ok(); } +Status StatsService::registerPullerCallback(int32_t atomTag, + const sp<android::os::IStatsPullerCallback>& pullerCallback, + const String16& packageName) { + ENFORCE_DUMP_AND_USAGE_STATS(packageName); + + VLOG("StatsService::registerPullerCallback called."); + mPullerManager->RegisterPullerCallback(atomTag, pullerCallback); + return Status::ok(); +} + +Status StatsService::unregisterPullerCallback(int32_t atomTag, const String16& packageName) { + ENFORCE_DUMP_AND_USAGE_STATS(packageName); + + VLOG("StatsService::unregisterPullerCallback called."); + mPullerManager->UnregisterPullerCallback(atomTag); + return Status::ok(); +} + hardware::Return<void> StatsService::reportSpeakerImpedance( const SpeakerImpedance& speakerImpedance) { LogEvent event(getWallClockSec() * NS_PER_SEC, getElapsedRealtimeNs(), speakerImpedance); diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h index cdff50fcb62e..941ed462b303 100644 --- a/cmds/statsd/src/StatsService.h +++ b/cmds/statsd/src/StatsService.h @@ -173,6 +173,19 @@ public: virtual Status sendAppBreadcrumbAtom(int32_t label, int32_t state) override; /** + * Binder call to register a callback function for a vendor pulled atom. + * Note: this atom must NOT have uid as a field. + */ + virtual Status registerPullerCallback(int32_t atomTag, + const sp<android::os::IStatsPullerCallback>& pullerCallback, + const String16& packageName) override; + + /** + * Binder call to unregister any existing callback function for a vendor pulled atom. + */ + virtual Status unregisterPullerCallback(int32_t atomTag, const String16& packageName) override; + + /** * Binder call to get SpeakerImpedance atom. */ virtual Return<void> reportSpeakerImpedance(const SpeakerImpedance& speakerImpedance) override; diff --git a/cmds/statsd/src/external/StatsCallbackPuller.cpp b/cmds/statsd/src/external/StatsCallbackPuller.cpp new file mode 100644 index 000000000000..d718273e9b85 --- /dev/null +++ b/cmds/statsd/src/external/StatsCallbackPuller.cpp @@ -0,0 +1,61 @@ +/* + * 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. + */ + +#define DEBUG false // STOPSHIP if true +#include "Log.h" + +#include <android/os/IStatsPullerCallback.h> + +#include "StatsCallbackPuller.h" +#include "logd/LogEvent.h" +#include "stats_log_util.h" + +using namespace android::binder; + +namespace android { +namespace os { +namespace statsd { + +StatsCallbackPuller::StatsCallbackPuller(int tagId, const sp<IStatsPullerCallback>& callback) : + StatsPuller(tagId), mCallback(callback) { + VLOG("StatsCallbackPuller created for tag %d", tagId); +} + +bool StatsCallbackPuller::PullInternal(vector<shared_ptr<LogEvent>>* data) { + VLOG("StatsCallbackPuller called for tag %d", mTagId) + if(mCallback == nullptr) { + ALOGW("No callback registered"); + return false; + } + int64_t wallClockTimeNs = getWallClockNs(); + int64_t elapsedTimeNs = getElapsedRealtimeNs(); + vector<StatsLogEventWrapper> returned_value; + Status status = mCallback->pullData(mTagId, elapsedTimeNs, wallClockTimeNs, &returned_value); + if (!status.isOk()) { + ALOGW("StatsCallbackPuller::pull failed for %d", mTagId); + return false; + } + data->clear(); + for (const StatsLogEventWrapper& it: returned_value) { + LogEvent::createLogEvents(it, *data); + } + VLOG("StatsCallbackPuller::pull succeeded for %d", mTagId); + return true; +} + +} // namespace statsd +} // namespace os +} // namespace android diff --git a/cmds/statsd/src/external/StatsCallbackPuller.h b/cmds/statsd/src/external/StatsCallbackPuller.h new file mode 100644 index 000000000000..c4bfa89ba9a7 --- /dev/null +++ b/cmds/statsd/src/external/StatsCallbackPuller.h @@ -0,0 +1,38 @@ +/* + * 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 <android/os/IStatsPullerCallback.h> +#include <utils/String16.h> +#include "StatsPuller.h" + +namespace android { +namespace os { +namespace statsd { + +class StatsCallbackPuller : public StatsPuller { +public: + explicit StatsCallbackPuller(int tagId, const sp<IStatsPullerCallback>& callback); + +private: + bool PullInternal(vector<std::shared_ptr<LogEvent> >* data) override; + const sp<IStatsPullerCallback> mCallback; +}; + +} // namespace statsd +} // namespace os +} // namespace android diff --git a/cmds/statsd/src/external/StatsPuller.cpp b/cmds/statsd/src/external/StatsPuller.cpp index c7c22ee85f0f..9552c0a5e35e 100644 --- a/cmds/statsd/src/external/StatsPuller.cpp +++ b/cmds/statsd/src/external/StatsPuller.cpp @@ -33,7 +33,7 @@ sp<UidMap> StatsPuller::mUidMap = nullptr; void StatsPuller::SetUidMap(const sp<UidMap>& uidMap) { mUidMap = uidMap; } StatsPuller::StatsPuller(const int tagId) - : mTagId(tagId) { + : mTagId(tagId), mLastPullTimeNs(0) { } bool StatsPuller::Pull(std::vector<std::shared_ptr<LogEvent>>* data) { diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp index ecdcd21d44dd..ed72b2914a34 100644 --- a/cmds/statsd/src/external/StatsPullerManager.cpp +++ b/cmds/statsd/src/external/StatsPullerManager.cpp @@ -18,6 +18,7 @@ #include "Log.h" #include <android/os/IStatsCompanionService.h> +#include <android/os/IStatsPullerCallback.h> #include <cutils/log.h> #include <math.h> #include <stdint.h> @@ -29,6 +30,7 @@ #include "PowerStatsPuller.h" #include "ResourceHealthManagerPuller.h" #include "StatsCompanionServicePuller.h" +#include "StatsCallbackPuller.h" #include "StatsPullerManager.h" #include "SubsystemSleepStatePuller.h" #include "statslog.h" @@ -49,7 +51,7 @@ namespace statsd { // Values smaller than this may require to update the alarm. const int64_t NO_ALARM_UPDATE = INT64_MAX; -const std::map<int, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = { +std::map<int, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = { // wifi_bytes_transfer {android::util::WIFI_BYTES_TRANSFER, {.additiveFields = {2, 3, 4, 5}, @@ -420,6 +422,30 @@ int StatsPullerManager::ClearPullerCacheIfNecessary(int64_t timestampNs) { return totalCleared; } +void StatsPullerManager::RegisterPullerCallback(int32_t atomTag, + const sp<IStatsPullerCallback>& callback) { + AutoMutex _l(mLock); + // Platform pullers cannot be changed. + if (atomTag < StatsdStats::kMaxPlatformAtomTag) { + VLOG("RegisterPullerCallback: atom tag %d is less than min tag %d", + atomTag, StatsdStats::kMaxPlatformAtomTag); + return; + } + VLOG("RegisterPullerCallback: adding puller for tag %d", atomTag); + StatsdStats::getInstance().notePullerCallbackRegistrationChanged(atomTag, /*registered=*/true); + kAllPullAtomInfo[atomTag] = {.puller = new StatsCallbackPuller(atomTag, callback)}; +} + +void StatsPullerManager::UnregisterPullerCallback(int32_t atomTag) { + AutoMutex _l(mLock); + // Platform pullers cannot be changed. + if (atomTag < StatsdStats::kMaxPlatformAtomTag) { + return; + } + StatsdStats::getInstance().notePullerCallbackRegistrationChanged(atomTag, /*registered=*/false); + kAllPullAtomInfo.erase(atomTag); +} + } // namespace statsd } // namespace os } // namespace android diff --git a/cmds/statsd/src/external/StatsPullerManager.h b/cmds/statsd/src/external/StatsPullerManager.h index 807e4af03dae..45f6b3568143 100644 --- a/cmds/statsd/src/external/StatsPullerManager.h +++ b/cmds/statsd/src/external/StatsPullerManager.h @@ -17,6 +17,7 @@ #pragma once #include <android/os/IStatsCompanionService.h> +#include <android/os/IStatsPullerCallback.h> #include <binder/IServiceManager.h> #include <utils/RefBase.h> #include <utils/threads.h> @@ -91,7 +92,12 @@ public: void SetStatsCompanionService(sp<IStatsCompanionService> statsCompanionService); - const static std::map<int, PullAtomInfo> kAllPullAtomInfo; + void RegisterPullerCallback(int32_t atomTag, + const sp<IStatsPullerCallback>& callback); + + void UnregisterPullerCallback(int32_t atomTag); + + static std::map<int, PullAtomInfo> kAllPullAtomInfo; private: sp<IStatsCompanionService> mStatsCompanionService = nullptr; diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp index c4034ffeee22..40329b7c86ab 100644 --- a/cmds/statsd/src/guardrail/StatsdStats.cpp +++ b/cmds/statsd/src/guardrail/StatsdStats.cpp @@ -423,6 +423,15 @@ void StatsdStats::noteEmptyData(int atomId) { mPulledAtomStats[atomId].emptyData++; } +void StatsdStats::notePullerCallbackRegistrationChanged(int atomId, bool registered) { + lock_guard<std::mutex> lock(mLock); + if (registered) { + mPulledAtomStats[atomId].registeredCount++; + } else { + mPulledAtomStats[atomId].unregisteredCount++; + } +} + void StatsdStats::noteHardDimensionLimitReached(int64_t metricId) { lock_guard<std::mutex> lock(mLock); getAtomMetricStats(metricId).hardDimensionLimitReached++; @@ -514,6 +523,8 @@ void StatsdStats::resetInternalLocked() { pullStats.second.dataError = 0; pullStats.second.pullTimeout = 0; pullStats.second.pullExceedMaxDelay = 0; + pullStats.second.registeredCount = 0; + pullStats.second.unregisteredCount = 0; } mAtomMetricStats.clear(); } @@ -625,12 +636,14 @@ void StatsdStats::dumpStats(int out) const { " (average pull time nanos)%lld, (max pull time nanos)%lld, (average pull delay " "nanos)%lld, " " (max pull delay nanos)%lld, (data error)%ld\n" - " (pull timeout)%ld, (pull exceed max delay)%ld\n", + " (pull timeout)%ld, (pull exceed max delay)%ld\n" + " (registered count) %ld, (unregistered count) %ld\n", (int)pair.first, (long)pair.second.totalPull, (long)pair.second.totalPullFromCache, (long)pair.second.minPullIntervalSec, (long long)pair.second.avgPullTimeNs, (long long)pair.second.maxPullTimeNs, (long long)pair.second.avgPullDelayNs, (long long)pair.second.maxPullDelayNs, pair.second.dataError, - pair.second.pullTimeout, pair.second.pullExceedMaxDelay); + pair.second.pullTimeout, pair.second.pullExceedMaxDelay, + pair.second.registeredCount, pair.second.unregisteredCount); } if (mAnomalyAlarmRegisteredStats > 0) { diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h index ea3f3b32b0c4..65e8a324d7d3 100644 --- a/cmds/statsd/src/guardrail/StatsdStats.h +++ b/cmds/statsd/src/guardrail/StatsdStats.h @@ -146,6 +146,10 @@ public: // Max time to do a pull. static const int64_t kPullMaxDelayNs = 10 * NS_PER_SEC; + + // Max platform atom tag number. + static const int32_t kMaxPlatformAtomTag = 100000; + /** * Report a new config has been received and report the static stats about the config. * @@ -340,6 +344,13 @@ public: void noteEmptyData(int atomId); /** + * Records that a puller callback for the given atomId was registered or unregistered. + * + * @param registered True if the callback was registered, false if was unregistered. + */ + void notePullerCallbackRegistrationChanged(int atomId, bool registered); + + /** * Hard limit was reached in the cardinality of an atom */ void noteHardDimensionLimitReached(int64_t metricId); @@ -416,6 +427,8 @@ public: long statsCompanionPullFailed = 0; long statsCompanionPullBinderTransactionFailed = 0; long emptyData = 0; + long registeredCount = 0; + long unregisteredCount = 0; } PulledAtomStats; typedef struct { diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto index 6a07a3f169e0..863261ae1626 100644 --- a/cmds/statsd/src/stats_log.proto +++ b/cmds/statsd/src/stats_log.proto @@ -407,6 +407,8 @@ message StatsdStatsReport { optional int64 stats_companion_pull_failed = 13; optional int64 stats_companion_pull_binder_transaction_failed = 14; optional int64 empty_data = 15; + optional int64 registered_count = 16; + optional int64 unregistered_count = 17; } repeated PulledAtomStats pulled_atom_stats = 10; diff --git a/cmds/statsd/src/stats_log_util.cpp b/cmds/statsd/src/stats_log_util.cpp index aa8cfc508861..0ebf2ca4e035 100644 --- a/cmds/statsd/src/stats_log_util.cpp +++ b/cmds/statsd/src/stats_log_util.cpp @@ -70,6 +70,8 @@ const int FIELD_ID_PULL_FAILED = 12; const int FIELD_ID_STATS_COMPANION_FAILED = 13; const int FIELD_ID_STATS_COMPANION_BINDER_TRANSACTION_FAILED = 14; const int FIELD_ID_EMPTY_DATA = 15; +const int FIELD_ID_PULL_REGISTERED_COUNT = 16; +const int FIELD_ID_PULL_UNREGISTERED_COUNT = 17; // for AtomMetricStats proto const int FIELD_ID_ATOM_METRIC_STATS = 17; const int FIELD_ID_METRIC_ID = 1; @@ -480,6 +482,10 @@ void writePullerStatsToStream(const std::pair<int, StatsdStats::PulledAtomStats> (long long)pair.second.statsCompanionPullBinderTransactionFailed); protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_EMPTY_DATA, (long long)pair.second.emptyData); + protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_PULL_REGISTERED_COUNT, + (long long) pair.second.registeredCount); + protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_PULL_UNREGISTERED_COUNT, + (long long) pair.second.unregisteredCount); protoOutput->end(token); } diff --git a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp index 92aa998d9720..44a88f049443 100644 --- a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp +++ b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp @@ -259,6 +259,10 @@ TEST(StatsdStatsTest, TestPullAtomStats) { stats.notePullDelay(android::util::DISK_SPACE, 3335L); stats.notePull(android::util::DISK_SPACE); stats.notePullFromCache(android::util::DISK_SPACE); + stats.notePullerCallbackRegistrationChanged(android::util::DISK_SPACE, true); + stats.notePullerCallbackRegistrationChanged(android::util::DISK_SPACE, false); + stats.notePullerCallbackRegistrationChanged(android::util::DISK_SPACE, true); + vector<uint8_t> output; stats.dumpStats(&output, false); @@ -276,6 +280,8 @@ TEST(StatsdStatsTest, TestPullAtomStats) { EXPECT_EQ(3333L, report.pulled_atom_stats(0).max_pull_time_nanos()); EXPECT_EQ(2223L, report.pulled_atom_stats(0).average_pull_delay_nanos()); EXPECT_EQ(3335L, report.pulled_atom_stats(0).max_pull_delay_nanos()); + EXPECT_EQ(2L, report.pulled_atom_stats(0).registered_count()); + EXPECT_EQ(1L, report.pulled_atom_stats(0).unregistered_count()); } TEST(StatsdStatsTest, TestAtomMetricsStats) { diff --git a/core/java/android/app/StatsManager.java b/core/java/android/app/StatsManager.java index 3119b37a686e..7746148d325a 100644 --- a/core/java/android/app/StatsManager.java +++ b/core/java/android/app/StatsManager.java @@ -24,6 +24,7 @@ import android.annotation.SystemApi; import android.content.Context; import android.os.IBinder; import android.os.IStatsManager; +import android.os.IStatsPullerCallback; import android.os.RemoteException; import android.os.ServiceManager; import android.util.AndroidException; @@ -408,6 +409,39 @@ public final class StatsManager { } } + /** + * Registers a callback for an atom when that atom is to be pulled. The stats service will + * invoke pullData in the callback when the stats service determines that this atom needs to be + * pulled. Currently, this only works for atoms with tags above 100,000 that do not have a uid. + * + * @param atomTag The tag of the atom for this puller callback. Must be at least 100000. + * @param callback The callback to be invoked when the stats service pulls the atom. + * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service + * + * @hide + */ + @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS }) + public void setPullerCallback(int atomTag, IStatsPullerCallback callback) + throws StatsUnavailableException { + synchronized (this) { + try { + IStatsManager service = getIStatsManagerLocked(); + if (callback == null) { + service.unregisterPullerCallback(atomTag, mContext.getOpPackageName()); + } else { + service.registerPullerCallback(atomTag, callback, + mContext.getOpPackageName()); + } + + } catch (RemoteException e) { + Slog.e(TAG, "Failed to connect to statsd when registering data listener."); + throw new StatsUnavailableException("could not connect", e); + } catch (SecurityException e) { + throw new StatsUnavailableException(e.getMessage(), e); + } + } + } + private class StatsdDeathRecipient implements IBinder.DeathRecipient { @Override public void binderDied() { diff --git a/core/java/android/os/IStatsManager.aidl b/core/java/android/os/IStatsManager.aidl index 93d6f4c12128..f1bba1ab2977 100644 --- a/core/java/android/os/IStatsManager.aidl +++ b/core/java/android/os/IStatsManager.aidl @@ -16,6 +16,8 @@ package android.os; +import android.os.IStatsPullerCallback; + /** * Binder interface to communicate with the statistics management service. * {@hide} @@ -178,4 +180,20 @@ interface IStatsManager { * this label. This allows building custom metrics and predicates. */ void sendAppBreadcrumbAtom(int label, int state); + + /** + * Registers a puller callback function that, when invoked, pulls the data + * for the specified vendor atom tag. + * + * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS + */ + oneway void registerPullerCallback(int atomTag, IStatsPullerCallback pullerCallback, + String packageName); + + /** + * Unregisters a puller callback function for the given vendor atom. + * + * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS + */ + oneway void unregisterPullerCallback(int atomTag, String packageName); } diff --git a/core/java/android/os/IStatsPullerCallback.aidl b/core/java/android/os/IStatsPullerCallback.aidl new file mode 100644 index 000000000000..1684aeb0d666 --- /dev/null +++ b/core/java/android/os/IStatsPullerCallback.aidl @@ -0,0 +1,35 @@ +/* + * 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. + */ + +package android.os; + +import android.os.StatsLogEventWrapper; + +/** + * Binder interface to pull atoms for the stats service. + * {@hide} + */ +interface IStatsPullerCallback { + /** + * Pull data for the specified atom tag. Returns an array of StatsLogEventWrapper containing + * the data. + * + * Note: These pulled atoms should not have uid/attribution chain. Additionally, the event + * timestamps will be truncated to the nearest 5 minutes. + */ + StatsLogEventWrapper[] pullData(int atomTag, long elapsedNanos, long wallClocknanos); + +} diff --git a/core/java/android/os/StatsLogEventWrapper.java b/core/java/android/os/StatsLogEventWrapper.java index acb9eac3572c..23342426693a 100644 --- a/core/java/android/os/StatsLogEventWrapper.java +++ b/core/java/android/os/StatsLogEventWrapper.java @@ -57,20 +57,18 @@ public final class StatsLogEventWrapper implements Parcelable { public static final Parcelable.Creator<StatsLogEventWrapper> CREATOR = new Parcelable.Creator<StatsLogEventWrapper>() { public StatsLogEventWrapper createFromParcel(Parcel in) { - android.util.EventLog.writeEvent(0x534e4554, "112550251", - android.os.Binder.getCallingUid(), ""); - // Purposefully leaving this method not implemented. - throw new RuntimeException("Not implemented"); + return new StatsLogEventWrapper(in); } public StatsLogEventWrapper[] newArray(int size) { - android.util.EventLog.writeEvent(0x534e4554, "112550251", - android.os.Binder.getCallingUid(), ""); - // Purposefully leaving this method not implemented. - throw new RuntimeException("Not implemented"); + return new StatsLogEventWrapper[size]; } }; + private StatsLogEventWrapper(Parcel in) { + readFromParcel(in); + } + /** * Set work source if any. */ @@ -197,6 +195,70 @@ public final class StatsLogEventWrapper implements Parcelable { } /** + * Reads from parcel and appropriately fills member fields. + */ + public void readFromParcel(Parcel in) { + mTypes = new ArrayList<>(); + mValues = new ArrayList<>(); + mWorkSource = null; + + mTag = in.readInt(); + mElapsedTimeNs = in.readLong(); + mWallClockTimeNs = in.readLong(); + + // Clear any data. + if (DEBUG) { + Slog.d(TAG, "Reading " + mTag + " " + mElapsedTimeNs + " " + mWallClockTimeNs); + } + // Set up worksource if present. + int numWorkChains = in.readInt(); + if (numWorkChains > 0) { + mWorkSource = new WorkSource(); + for (int i = 0; i < numWorkChains; i++) { + android.os.WorkSource.WorkChain workChain = mWorkSource.createWorkChain(); + int workChainSize = in.readInt(); + for (int j = 0; j < workChainSize; j++) { + int uid = in.readInt(); + String tag = in.readString(); + workChain.addNode(uid, tag); + } + } + } + + // Do the rest of the types. + int numTypes = in.readInt(); + if (DEBUG) { + Slog.d(TAG, "Reading " + numTypes + " elements"); + } + for (int i = 0; i < numTypes; i++) { + int type = in.readInt(); + mTypes.add(type); + switch (type) { + case EVENT_TYPE_INT: + mValues.add(in.readInt()); + break; + case EVENT_TYPE_LONG: + mValues.add(in.readLong()); + break; + case EVENT_TYPE_FLOAT: + mValues.add(in.readFloat()); + break; + case EVENT_TYPE_DOUBLE: + mValues.add(in.readDouble()); + break; + case EVENT_TYPE_STRING: + mValues.add(in.readString()); + break; + case EVENT_TYPE_STORAGE: + mValues.add(in.createByteArray()); + break; + default: + break; + } + } + } + + /** * Boilerplate for Parcel. */ public int describeContents() { |