Adds aidl definitions and their implementations for binder transfer of
statsd entries to clients. This change only includes changes on statds side and does not include java library for clients to import. Java library will be a separate change as it requires system api review. Test: statsd, statsd_test Change-Id: I306c6e9687801668cc0145b12d38406bfe634775
This commit is contained in:
@@ -270,6 +270,7 @@ LOCAL_SRC_FILES += \
|
||||
core/java/android/os/IRecoverySystemProgressListener.aidl \
|
||||
core/java/android/os/IRemoteCallback.aidl \
|
||||
core/java/android/os/ISchedulingPolicyService.aidl \
|
||||
core/java/android/os/IStatsCallbacks.aidl \
|
||||
core/java/android/os/IStatsCompanionService.aidl \
|
||||
core/java/android/os/IStatsManager.aidl \
|
||||
core/java/android/os/IThermalEventListener.aidl \
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
|
||||
statsd_common_src := \
|
||||
../../core/java/android/os/IStatsCallbacks.aidl \
|
||||
../../core/java/android/os/IStatsCompanionService.aidl \
|
||||
../../core/java/android/os/IStatsManager.aidl \
|
||||
src/stats_log.proto \
|
||||
|
||||
@@ -33,8 +33,9 @@ namespace android {
|
||||
namespace os {
|
||||
namespace statsd {
|
||||
|
||||
StatsLogProcessor::StatsLogProcessor(const sp<UidMap>& uidMap)
|
||||
: m_dropbox_writer("all-logs"), mUidMap(uidMap) {
|
||||
StatsLogProcessor::StatsLogProcessor(const sp<UidMap>& uidMap,
|
||||
const std::function<void(const vector<uint8_t>&)>& pushLog)
|
||||
: m_dropbox_writer("all-logs"), mUidMap(uidMap), mPushLog(pushLog) {
|
||||
}
|
||||
|
||||
StatsLogProcessor::~StatsLogProcessor() {
|
||||
@@ -91,6 +92,41 @@ void StatsLogProcessor::OnConfigRemoved(const ConfigKey& key) {
|
||||
}
|
||||
}
|
||||
|
||||
void StatsLogProcessor::addEventMetricData(const EventMetricData& eventMetricData) {
|
||||
// TODO: Replace this code when MetricsManager.onDumpReport() is ready to
|
||||
// get a list of byte arrays.
|
||||
flushIfNecessary(eventMetricData);
|
||||
const int numBytes = eventMetricData.ByteSize();
|
||||
char buffer[numBytes];
|
||||
eventMetricData.SerializeToArray(&buffer[0], numBytes);
|
||||
string bufferString(buffer, numBytes);
|
||||
mEvents.push_back(bufferString);
|
||||
mBufferSize += eventMetricData.ByteSize();
|
||||
}
|
||||
|
||||
void StatsLogProcessor::flushIfNecessary(const EventMetricData& eventMetricData) {
|
||||
if (eventMetricData.ByteSize() + mBufferSize > kMaxSerializedBytes) {
|
||||
flush();
|
||||
}
|
||||
}
|
||||
|
||||
void StatsLogProcessor::flush() {
|
||||
StatsLogReport logReport;
|
||||
for (string eventBuffer : mEvents) {
|
||||
EventMetricData eventFromBuffer;
|
||||
eventFromBuffer.ParseFromString(eventBuffer);
|
||||
EventMetricData* newEntry = logReport.mutable_event_metrics()->add_data();
|
||||
newEntry->CopyFrom(eventFromBuffer);
|
||||
}
|
||||
|
||||
const int numBytes = logReport.ByteSize();
|
||||
vector<uint8_t> logReportBuffer(numBytes);
|
||||
logReport.SerializeToArray(&logReportBuffer[0], numBytes);
|
||||
mPushLog(logReportBuffer);
|
||||
mEvents.clear();
|
||||
mBufferSize = 0;
|
||||
}
|
||||
|
||||
} // namespace statsd
|
||||
} // namespace os
|
||||
} // namespace android
|
||||
|
||||
@@ -33,7 +33,8 @@ namespace statsd {
|
||||
|
||||
class StatsLogProcessor : public ConfigListener {
|
||||
public:
|
||||
StatsLogProcessor(const sp<UidMap>& uidMap);
|
||||
StatsLogProcessor(const sp<UidMap>& uidMap,
|
||||
const std::function<void(const vector<uint8_t>&)>& pushLog);
|
||||
virtual ~StatsLogProcessor();
|
||||
|
||||
virtual void OnLogEvent(const LogEvent& event);
|
||||
@@ -44,6 +45,9 @@ public:
|
||||
// TODO: Once we have the ProtoOutputStream in c++, we can just return byte array.
|
||||
std::vector<StatsLogReport> onDumpReport(const ConfigKey& key);
|
||||
|
||||
/* Request a flush through a binder call. */
|
||||
void flush();
|
||||
|
||||
private:
|
||||
// TODO: use EventMetrics to log the events.
|
||||
DropboxWriter m_dropbox_writer;
|
||||
@@ -51,6 +55,33 @@ private:
|
||||
std::unordered_map<ConfigKey, std::unique_ptr<MetricsManager>> mMetricsManagers;
|
||||
|
||||
sp<UidMap> mUidMap; // Reference to the UidMap to lookup app name and version for each uid.
|
||||
|
||||
/* Max *serialized* size of the logs kept in memory before flushing through binder call.
|
||||
Proto lite does not implement the SpaceUsed() function which gives the in memory byte size.
|
||||
So we cap memory usage by limiting the serialized size. Note that protobuf's in memory size
|
||||
is higher than its serialized size.
|
||||
*/
|
||||
static const size_t kMaxSerializedBytes = 16 * 1024;
|
||||
|
||||
/* List of data that was captured for a single metric over a given interval of time. */
|
||||
vector<string> mEvents;
|
||||
|
||||
/* Current *serialized* size of the logs kept in memory.
|
||||
To save computation, we will not calculate the size of the StatsLogReport every time when a
|
||||
new entry is added, which would recursively call ByteSize() on every log entry. Instead, we
|
||||
keep the sum of all individual stats log entry sizes. The size of a proto is approximately
|
||||
the sum of the size of all member protos.
|
||||
*/
|
||||
size_t mBufferSize = 0;
|
||||
|
||||
/* Check if the buffer size exceeds the max buffer size when the new entry is added, and flush
|
||||
the logs to dropbox if true. */
|
||||
void flushIfNecessary(const EventMetricData& eventMetricData);
|
||||
|
||||
/* Append event metric data to StatsLogReport. */
|
||||
void addEventMetricData(const EventMetricData& eventMetricData);
|
||||
|
||||
std::function<void(const vector<uint8_t>&)> mPushLog;
|
||||
};
|
||||
|
||||
} // namespace statsd
|
||||
|
||||
@@ -68,7 +68,9 @@ StatsService::StatsService(const sp<Looper>& handlerLooper)
|
||||
mStatsPullerManager = new StatsPullerManager();
|
||||
mUidMap = new UidMap();
|
||||
mConfigManager = new ConfigManager();
|
||||
mProcessor = new StatsLogProcessor(mUidMap);
|
||||
mProcessor = new StatsLogProcessor(mUidMap, [this](const vector<uint8_t>& log) {
|
||||
pushLog(log);
|
||||
});
|
||||
|
||||
mConfigManager->AddListener(mProcessor);
|
||||
|
||||
@@ -507,6 +509,40 @@ void StatsService::OnLogEvent(const LogEvent& event) {
|
||||
mProcessor->OnLogEvent(event);
|
||||
}
|
||||
|
||||
Status StatsService::requestPush() {
|
||||
mProcessor->flush();
|
||||
return Status::ok();
|
||||
}
|
||||
|
||||
Status StatsService::pushLog(const vector<uint8_t>& log) {
|
||||
std::lock_guard<std::mutex> lock(mLock);
|
||||
for (size_t i = 0; i < mCallbacks.size(); i++) {
|
||||
mCallbacks[i]->onReceiveLogs((vector<uint8_t>*)&log);
|
||||
}
|
||||
return Status::ok();
|
||||
}
|
||||
|
||||
Status StatsService::subscribeStatsLog(const sp<IStatsCallbacks>& callback) {
|
||||
std::lock_guard<std::mutex> lock(mLock);
|
||||
for (size_t i = 0; i < mCallbacks.size(); i++) {
|
||||
if (mCallbacks[i] == callback) {
|
||||
return Status::fromStatusT(-errno);
|
||||
}
|
||||
}
|
||||
mCallbacks.add(callback);
|
||||
IInterface::asBinder(callback)->linkToDeath(this);
|
||||
return Status::ok();
|
||||
}
|
||||
|
||||
void StatsService::binderDied(const wp<IBinder>& who) {
|
||||
for (size_t i = 0; i < mCallbacks.size(); i++) {
|
||||
if (IInterface::asBinder(mCallbacks[i]) == who) {
|
||||
mCallbacks.removeAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace statsd
|
||||
} // namespace os
|
||||
} // namespace android
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "packages/UidMap.h"
|
||||
|
||||
#include <android/os/BnStatsManager.h>
|
||||
#include <android/os/IStatsCallbacks.h>
|
||||
#include <android/os/IStatsCompanionService.h>
|
||||
#include <binder/IResultReceiver.h>
|
||||
#include <binder/IShellCallback.h>
|
||||
@@ -42,7 +43,7 @@ namespace android {
|
||||
namespace os {
|
||||
namespace statsd {
|
||||
|
||||
class StatsService : public BnStatsManager, public LogListener {
|
||||
class StatsService : public BnStatsManager, public LogListener, public IBinder::DeathRecipient {
|
||||
public:
|
||||
StatsService(const sp<Looper>& handlerLooper);
|
||||
virtual ~StatsService();
|
||||
@@ -70,6 +71,22 @@ public:
|
||||
*/
|
||||
virtual void OnLogEvent(const LogEvent& event);
|
||||
|
||||
/**
|
||||
* Binder call to force trigger pushLog. This would be called by callback
|
||||
* clients.
|
||||
*/
|
||||
virtual Status requestPush() override;
|
||||
|
||||
/**
|
||||
* Pushes stats log entries from statsd to callback clients.
|
||||
*/
|
||||
Status pushLog(const vector<uint8_t>& log);
|
||||
|
||||
/**
|
||||
* Binder call to listen to statsd to send stats log entries.
|
||||
*/
|
||||
virtual Status subscribeStatsLog(const sp<IStatsCallbacks>& callbacks) override;
|
||||
|
||||
// TODO: public for testing since statsd doesn't run when system starts. Change to private
|
||||
// later.
|
||||
/** Inform statsCompanion that statsd is ready. */
|
||||
@@ -78,6 +95,9 @@ public:
|
||||
/** Fetches and returns the StatsCompanionService. */
|
||||
static sp<IStatsCompanionService> getStatsCompanionService();
|
||||
|
||||
/** IBinder::DeathRecipient */
|
||||
virtual void binderDied(const wp<IBinder>& who) override;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Load system properties at init.
|
||||
@@ -159,6 +179,16 @@ private:
|
||||
* Whether this is an eng build.
|
||||
*/
|
||||
bool mEngBuild;
|
||||
|
||||
/**
|
||||
* Lock for callback handling.
|
||||
*/
|
||||
std::mutex mLock;
|
||||
|
||||
/**
|
||||
* Vector maintaining the list of callbacks for clients.
|
||||
*/
|
||||
Vector< sp<IStatsCallbacks> > mCallbacks;
|
||||
};
|
||||
|
||||
} // namespace statsd
|
||||
|
||||
25
core/java/android/os/IStatsCallbacks.aidl
Normal file
25
core/java/android/os/IStatsCallbacks.aidl
Normal file
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright (c) 2016, 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;
|
||||
|
||||
/**
|
||||
* Callback for Statsd to allow binder calls to clients.
|
||||
* {@hide}
|
||||
*/
|
||||
interface IStatsCallbacks {
|
||||
void onReceiveLogs(out byte[] log);
|
||||
}
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package android.os;
|
||||
|
||||
import android.os.IStatsCallbacks;
|
||||
|
||||
/**
|
||||
* Binder interface to communicate with the statistics management service.
|
||||
* {@hide}
|
||||
@@ -61,4 +63,15 @@ interface IStatsManager {
|
||||
* Inform stats that an app was removed.
|
||||
*/
|
||||
oneway void informOnePackageRemoved(in String app, in int uid);
|
||||
|
||||
/**
|
||||
* Trigger pushLog to force push stats log entries from statsd on client side.
|
||||
*/
|
||||
void requestPush();
|
||||
|
||||
/**
|
||||
* Listen to statsd to send stats log entries.
|
||||
* TODO: Limit callbacks with specific configurations.
|
||||
*/
|
||||
void subscribeStatsLog(IStatsCallbacks callbacks);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user