Statsd Puller Callback Registration
Creates a hidden api to register puller callbacks for vendor atoms.
Test: manual local test
Test: statsd unit tests
Bug: 119898637
Change-Id: Id28817b8fc718e128adc4e1c6b2e997db84517f9
diff --git a/Android.bp b/Android.bp
index 7bdedc7..0848d2b 100644
--- a/Android.bp
+++ b/Android.bp
@@ -804,6 +804,7 @@
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 d6f045e..faf2053 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -71,6 +71,7 @@
"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 86bf3ec..bd21a95 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -1057,6 +1057,24 @@
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 cdff50f..941ed46 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -173,6 +173,19 @@
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 0000000..d718273
--- /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 0000000..c4bfa89
--- /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 c7c22ee..9552c0a 100644
--- a/cmds/statsd/src/external/StatsPuller.cpp
+++ b/cmds/statsd/src/external/StatsPuller.cpp
@@ -33,7 +33,7 @@
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 ecdcd21..ed72b29 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 @@
// 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 @@
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 807e4af..45f6b35 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 @@
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 c4034ff..40329b7 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -423,6 +423,15 @@
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 @@
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 @@
" (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 ea3f3b3..65e8a32 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -146,6 +146,10 @@
// 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 @@
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 @@
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 6a07a3f..863261a 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -407,6 +407,8 @@
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 aa8cfc5..0ebf2ca 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_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 @@
(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 92aa998..44a88f0 100644
--- a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
+++ b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
@@ -259,6 +259,10 @@
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 @@
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 3119b37..7746148 100644
--- a/core/java/android/app/StatsManager.java
+++ b/core/java/android/app/StatsManager.java
@@ -24,6 +24,7 @@
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 @@
}
}
+ /**
+ * 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 93d6f4c..f1bba1a 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 @@
* 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 0000000..1684aeb
--- /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 acb9eac..2334242 100644
--- a/core/java/android/os/StatsLogEventWrapper.java
+++ b/core/java/android/os/StatsLogEventWrapper.java
@@ -57,20 +57,18 @@
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 @@
}
/**
+ * 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() {