MediaMetrics: Make submit one-way

Remove the unused session id to improve speed and clarity.

Test: dumpsys media.metrics sanity, mediametrics_tests
Change-Id: Ide5e9218811e110997fed19f43eb6a5fdc5812ec
gugelfrei
Andy Hung 5 years ago
parent 2392e6d96d
commit a87e69cf8b

@ -59,7 +59,6 @@ void DrmManager::reportEngineMetrics(
IDrmEngine& engine = mPlugInManager.getPlugIn(plugInId);
std::unique_ptr<MediaAnalyticsItem> item(MediaAnalyticsItem::create("drmmanager"));
item->generateSessionID();
item->setUid(IPCThreadState::self()->getCallingUid());
item->setCString("function_name", func);
item->setCString("plugin_id", plugInId.getPathLeaf().getBasePath().c_str());

@ -1574,7 +1574,6 @@ void DrmHal::writeByteArray(Parcel &obj, hidl_vec<uint8_t> const &vec)
void DrmHal::reportFrameworkMetrics() const
{
std::unique_ptr<MediaAnalyticsItem> item(MediaAnalyticsItem::create("mediadrm"));
item->generateSessionID();
item->setPkgName(mMetrics.GetAppPackageName().c_str());
String8 vendor;
String8 description;

@ -35,8 +35,6 @@ status_t reportVendorMetrics(const std::string& metrics,
const String8& name,
const String8& appPackageName) {
std::unique_ptr<MediaAnalyticsItem> analyticsItem(MediaAnalyticsItem::create(name.c_str()));
analyticsItem->generateSessionID();
std::string app_package_name(appPackageName.c_str(), appPackageName.size());
analyticsItem->setPkgName(app_package_name);
if (metrics.size() > 0) {
@ -44,7 +42,7 @@ status_t reportVendorMetrics(const std::string& metrics,
}
if (!analyticsItem->selfrecord()) {
ALOGE("selfrecord() returned false. sessioId %" PRId64, analyticsItem->getSessionID());
ALOGE("%s: selfrecord() returned false", __func__);
}
return OK;

@ -32,15 +32,10 @@
#include <media/MediaAnalyticsItem.h>
#include <media/IMediaAnalyticsService.h>
#define DEBUGGING 0
#define DEBUGGING_FLOW 0
#define DEBUGGING_RETURNS 0
namespace android {
enum {
GENERATE_UNIQUE_SESSIONID = IBinder::FIRST_CALL_TRANSACTION,
SUBMIT_ITEM,
SUBMIT_ITEM_ONEWAY = IBinder::FIRST_CALL_TRANSACTION,
};
class BpMediaAnalyticsService: public BpInterface<IMediaAnalyticsService>
@ -51,61 +46,23 @@ public:
{
}
virtual MediaAnalyticsItem::SessionID_t generateUniqueSessionID() {
Parcel data, reply;
status_t err;
MediaAnalyticsItem::SessionID_t sessionid =
MediaAnalyticsItem::SessionIDInvalid;
data.writeInterfaceToken(IMediaAnalyticsService::getInterfaceDescriptor());
err = remote()->transact(GENERATE_UNIQUE_SESSIONID, data, &reply);
if (err != NO_ERROR) {
ALOGW("bad response from service for generateSessionId, err=%d", err);
return MediaAnalyticsItem::SessionIDInvalid;
}
sessionid = reply.readInt64();
if (DEBUGGING_RETURNS) {
ALOGD("the caller gets a sessionid of %" PRId64 " back", sessionid);
}
return sessionid;
}
virtual MediaAnalyticsItem::SessionID_t submit(MediaAnalyticsItem *item, bool forcenew)
status_t submit(MediaAnalyticsItem *item) override
{
// have this record submit itself
// this will be a binder call with appropriate timing
// return value is the uuid that the system generated for it.
// the return value 0 and -1 are reserved.
// -1 to indicate that there was a problem recording...
Parcel data, reply;
status_t err;
if (item == NULL) {
return MediaAnalyticsItem::SessionIDInvalid;
if (item == nullptr) {
return BAD_VALUE;
}
ALOGV("%s: (ONEWAY) item=%s", __func__, item->toString().c_str());
Parcel data;
data.writeInterfaceToken(IMediaAnalyticsService::getInterfaceDescriptor());
if(DEBUGGING_FLOW) {
ALOGD("client offers record: %s", item->toString().c_str());
}
data.writeBool(forcenew);
item->writeToParcel(&data);
err = remote()->transact(SUBMIT_ITEM, data, &reply);
if (err != NO_ERROR) {
ALOGW("bad response from service for submit, err=%d", err);
return MediaAnalyticsItem::SessionIDInvalid;
}
// get an answer out of 'reply'
int64_t sessionid = reply.readInt64();
if (DEBUGGING_RETURNS) {
ALOGD("the caller gets sessionid=%" PRId64 "", sessionid);
}
return sessionid;
status_t err = remote()->transact(
SUBMIT_ITEM_ONEWAY, data, nullptr /* reply */, IBinder::FLAG_ONEWAY);
ALOGW_IF(err != NO_ERROR, "%s: bad response from service for submit, err=%d",
__func__, err);
return err;
}
};
IMPLEMENT_META_INTERFACE(MediaAnalyticsService, "android.media.IMediaAnalyticsService");
@ -115,49 +72,23 @@ IMPLEMENT_META_INTERFACE(MediaAnalyticsService, "android.media.IMediaAnalyticsSe
status_t BnMediaAnalyticsService::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
// get calling pid/tid
IPCThreadState *ipc = IPCThreadState::self();
int clientPid = ipc->getCallingPid();
// permission checking
if(DEBUGGING_FLOW) {
ALOGD("running in service, code %d, pid %d; called from pid %d",
code, getpid(), clientPid);
}
const int clientPid = IPCThreadState::self()->getCallingPid();
switch (code) {
case SUBMIT_ITEM_ONEWAY: {
CHECK_INTERFACE(IMediaAnalyticsService, data, reply);
case GENERATE_UNIQUE_SESSIONID: {
CHECK_INTERFACE(IMediaAnalyticsService, data, reply);
MediaAnalyticsItem::SessionID_t sessionid = generateUniqueSessionID();
reply->writeInt64(sessionid);
return NO_ERROR;
} break;
case SUBMIT_ITEM: {
CHECK_INTERFACE(IMediaAnalyticsService, data, reply);
bool forcenew;
MediaAnalyticsItem *item = MediaAnalyticsItem::create();
data.readBool(&forcenew);
item->readFromParcel(data);
item->setPid(clientPid);
// submit() takes over ownership of 'item'
MediaAnalyticsItem::SessionID_t sessionid = submit(item, forcenew);
reply->writeInt64(sessionid);
return NO_ERROR;
} break;
MediaAnalyticsItem * const item = MediaAnalyticsItem::create();
if (item->readFromParcel(data) < 0) {
return BAD_VALUE;
}
item->setPid(clientPid);
const status_t status __unused = submitInternal(item, true /* release */);
return NO_ERROR;
} break;
default:
return BBinder::onTransact(code, data, reply, flags);
default:
return BBinder::onTransact(code, data, reply, flags);
}
}

@ -22,10 +22,11 @@
#include <string.h>
#include <sys/types.h>
#include <mutex>
#include <binder/Parcel.h>
#include <utils/Errors.h>
#include <utils/Log.h>
#include <utils/Mutex.h>
#include <utils/SortedVector.h>
#include <utils/threads.h>
@ -79,9 +80,7 @@ MediaAnalyticsItem::MediaAnalyticsItem()
: mPid(-1),
mUid(-1),
mPkgVersionCode(0),
mSessionID(MediaAnalyticsItem::SessionIDNone),
mTimestamp(0),
mFinalized(1),
mPropCount(0), mPropSize(0), mProps(NULL)
{
mKey = MediaAnalyticsItem::kKeyNone;
@ -91,9 +90,7 @@ MediaAnalyticsItem::MediaAnalyticsItem(MediaAnalyticsItem::Key key)
: mPid(-1),
mUid(-1),
mPkgVersionCode(0),
mSessionID(MediaAnalyticsItem::SessionIDNone),
mTimestamp(0),
mFinalized(1),
mPropCount(0), mPropSize(0), mProps(NULL)
{
if (DEBUG_ALLOCATIONS) {
@ -114,9 +111,6 @@ void MediaAnalyticsItem::clear() {
// clean allocated storage from key
mKey.clear();
// clean various major parameters
mSessionID = MediaAnalyticsItem::SessionIDNone;
// clean attributes
// contents of the attributes
for (size_t i = 0 ; i < mPropCount; i++ ) {
@ -143,9 +137,7 @@ MediaAnalyticsItem *MediaAnalyticsItem::dup() {
dst->mUid = this->mUid;
dst->mPkgName = this->mPkgName;
dst->mPkgVersionCode = this->mPkgVersionCode;
dst->mSessionID = this->mSessionID;
dst->mTimestamp = this->mTimestamp;
dst->mFinalized = this->mFinalized;
// properties aka attributes
dst->growProps(this->mPropCount);
@ -158,35 +150,6 @@ MediaAnalyticsItem *MediaAnalyticsItem::dup() {
return dst;
}
MediaAnalyticsItem &MediaAnalyticsItem::setSessionID(MediaAnalyticsItem::SessionID_t id) {
mSessionID = id;
return *this;
}
MediaAnalyticsItem::SessionID_t MediaAnalyticsItem::getSessionID() const {
return mSessionID;
}
MediaAnalyticsItem::SessionID_t MediaAnalyticsItem::generateSessionID() {
if (mSessionID == SessionIDNone) {
// get one from the server
MediaAnalyticsItem::SessionID_t newid = SessionIDNone;
sp<IMediaAnalyticsService> svc = getInstance();
if (svc != NULL) {
newid = svc->generateUniqueSessionID();
}
mSessionID = newid;
}
return mSessionID;
}
MediaAnalyticsItem &MediaAnalyticsItem::clearSessionID() {
mSessionID = MediaAnalyticsItem::SessionIDNone;
return *this;
}
MediaAnalyticsItem &MediaAnalyticsItem::setTimestamp(nsecs_t ts) {
mTimestamp = ts;
return *this;
@ -679,11 +642,8 @@ int32_t MediaAnalyticsItem::readFromParcel0(const Parcel& data) {
mUid = data.readInt32();
mPkgName = data.readCString();
mPkgVersionCode = data.readInt64();
mSessionID = data.readInt64();
// We no longer pay attention to user setting of finalized, BUT it's
// still part of the wire packet -- so read & discard.
mFinalized = data.readInt32();
mFinalized = 1;
mTimestamp = data.readInt64();
int count = data.readInt32();
@ -744,8 +704,6 @@ int32_t MediaAnalyticsItem::writeToParcel0(Parcel *data) {
data->writeInt32(mUid);
data->writeCString(mPkgName.c_str());
data->writeInt64(mPkgVersionCode);
data->writeInt64(mSessionID);
data->writeInt32(mFinalized);
data->writeInt64(mTimestamp);
// set of items
@ -821,9 +779,7 @@ std::string MediaAnalyticsItem::toString(int version) const {
// same order as we spill into the parcel, although not required
// key+session are our primary matching criteria
result.append(mKey.c_str());
result.append(":");
snprintf(buffer, sizeof(buffer), "%" PRId64 ":", mSessionID);
result.append(buffer);
result.append(":0:"); // sessionID
snprintf(buffer, sizeof(buffer), "%d:", mUid);
result.append(buffer);
@ -842,7 +798,7 @@ std::string MediaAnalyticsItem::toString(int version) const {
}
result.append(buffer);
snprintf(buffer, sizeof(buffer), "%d:", mFinalized);
snprintf(buffer, sizeof(buffer), "%d:", 0 /* finalized */); // TODO: remove this.
result.append(buffer);
snprintf(buffer, sizeof(buffer), "%" PRId64 ":", mTimestamp);
result.append(buffer);
@ -899,23 +855,12 @@ std::string MediaAnalyticsItem::toString(int version) const {
// for the lazy, we offer methods that finds the service and
// calls the appropriate daemon
bool MediaAnalyticsItem::selfrecord() {
return selfrecord(false);
}
bool MediaAnalyticsItem::selfrecord(bool forcenew) {
if (DEBUG_API) {
std::string p = this->toString();
ALOGD("selfrecord of: %s [forcenew=%d]", p.c_str(), forcenew);
}
ALOGD_IF(DEBUG_API, "%s: delivering %s", __func__, this->toString().c_str());
sp<IMediaAnalyticsService> svc = getInstance();
if (svc != NULL) {
MediaAnalyticsItem::SessionID_t newid = svc->submit(this, forcenew);
if (newid == SessionIDInvalid) {
std::string p = this->toString();
ALOGW("Failed to record: %s [forcenew=%d]", p.c_str(), forcenew);
status_t status = svc->submit(this);
if (status != NO_ERROR) {
ALOGW("%s: failed to record: %s", __func__, this->toString().c_str());
return false;
}
return true;
@ -924,29 +869,33 @@ bool MediaAnalyticsItem::selfrecord(bool forcenew) {
}
}
// get a connection we can reuse for most of our lifetime
// static
sp<IMediaAnalyticsService> MediaAnalyticsItem::sAnalyticsService;
static Mutex sInitMutex;
static int remainingBindAttempts = SVC_TRIES;
//static
bool MediaAnalyticsItem::isEnabled() {
int enabled = property_get_int32(MediaAnalyticsItem::EnabledProperty, -1);
// completely skip logging from certain UIDs. We do this here
// to avoid the multi-second timeouts while we learn that
// sepolicy will not let us find the service.
// We do this only for a select set of UIDs
// The sepolicy protection is still in place, we just want a faster
// response from this specific, small set of uids.
// This is checked only once in the lifetime of the process.
const uid_t uid = getuid();
switch (uid) {
case AID_RADIO: // telephony subsystem, RIL
return false;
}
int enabled = property_get_int32(MediaAnalyticsItem::EnabledProperty, -1);
if (enabled == -1) {
enabled = property_get_int32(MediaAnalyticsItem::EnabledPropertyPersist, -1);
}
if (enabled == -1) {
enabled = MediaAnalyticsItem::EnabledProperty_default;
}
if (enabled <= 0) {
return false;
}
return true;
return enabled > 0;
}
// monitor health of our connection to the metrics service
class MediaMetricsDeathNotifier : public IBinder::DeathRecipient {
virtual void binderDied(const wp<IBinder> &) {
@ -955,83 +904,56 @@ class MediaMetricsDeathNotifier : public IBinder::DeathRecipient {
}
};
static sp<MediaMetricsDeathNotifier> sNotifier = NULL;
static sp<MediaMetricsDeathNotifier> sNotifier;
// static
sp<IMediaAnalyticsService> MediaAnalyticsItem::sAnalyticsService;
static std::mutex sServiceMutex;
static int sRemainingBindAttempts = SVC_TRIES;
// static
void MediaAnalyticsItem::dropInstance() {
Mutex::Autolock _l(sInitMutex);
remainingBindAttempts = SVC_TRIES;
sAnalyticsService = NULL;
std::lock_guard _l(sServiceMutex);
sRemainingBindAttempts = SVC_TRIES;
sAnalyticsService = nullptr;
}
//static
sp<IMediaAnalyticsService> MediaAnalyticsItem::getInstance() {
static const char *servicename = "media.metrics";
int enabled = isEnabled();
static const bool enabled = isEnabled(); // singleton initialized
if (enabled == false) {
if (DEBUG_SERVICEACCESS) {
ALOGD("disabled");
}
return NULL;
}
// completely skip logging from certain UIDs. We do this here
// to avoid the multi-second timeouts while we learn that
// sepolicy will not let us find the service.
// We do this only for a select set of UIDs
// The sepolicy protection is still in place, we just want a faster
// response from this specific, small set of uids.
{
uid_t uid = getuid();
switch (uid) {
case AID_RADIO: // telephony subsystem, RIL
return NULL;
break;
default:
// let sepolicy deny access if appropriate
break;
}
}
{
Mutex::Autolock _l(sInitMutex);
ALOGD_IF(DEBUG_SERVICEACCESS, "disabled");
return nullptr;
}
std::lock_guard _l(sServiceMutex);
// think of remainingBindAttempts as telling us whether service == nullptr because
// (1) we haven't tried to initialize it yet
// (2) we've tried to initialize it, but failed.
if (sAnalyticsService == nullptr && sRemainingBindAttempts > 0) {
const char *badness = "";
// think of remainingBindAttempts as telling us whether service==NULL because
// (1) we haven't tried to initialize it yet
// (2) we've tried to initialize it, but failed.
if (sAnalyticsService == NULL && remainingBindAttempts > 0) {
sp<IServiceManager> sm = defaultServiceManager();
if (sm != NULL) {
sp<IBinder> binder = sm->getService(String16(servicename));
if (binder != NULL) {
sAnalyticsService = interface_cast<IMediaAnalyticsService>(binder);
if (sNotifier != NULL) {
sNotifier = NULL;
}
sNotifier = new MediaMetricsDeathNotifier();
binder->linkToDeath(sNotifier);
} else {
badness = "did not find service";
}
sp<IServiceManager> sm = defaultServiceManager();
if (sm != nullptr) {
sp<IBinder> binder = sm->getService(String16(servicename));
if (binder != nullptr) {
sAnalyticsService = interface_cast<IMediaAnalyticsService>(binder);
sNotifier = new MediaMetricsDeathNotifier();
binder->linkToDeath(sNotifier);
} else {
badness = "No Service Manager access";
badness = "did not find service";
}
if (sAnalyticsService == NULL) {
if (remainingBindAttempts > 0) {
remainingBindAttempts--;
}
if (DEBUG_SERVICEACCESS) {
ALOGD("Unable to bind to service %s: %s", servicename, badness);
}
} else {
badness = "No Service Manager access";
}
if (sAnalyticsService == nullptr) {
if (sRemainingBindAttempts > 0) {
sRemainingBindAttempts--;
}
ALOGD_IF(DEBUG_SERVICEACCESS, "%s: unable to bind to service %s: %s",
__func__, servicename, badness);
}
return sAnalyticsService;
}
return sAnalyticsService;
}
// merge the info from 'incoming' into this record.
@ -1042,8 +964,6 @@ bool MediaAnalyticsItem::merge(MediaAnalyticsItem *incoming) {
// 'this' should never be missing both of them...
if (mKey.empty()) {
mKey = incoming->mKey;
} else if (mSessionID == 0) {
mSessionID = incoming->mSessionID;
}
// for each attribute from 'incoming', resolve appropriately

@ -39,25 +39,16 @@ class IMediaAnalyticsService: public IInterface
public:
DECLARE_META_INTERFACE(MediaAnalyticsService);
/**
* Returns a unique sessionID to use across multiple requests;
* 'unique' is within this device, since last reboot.
*/
virtual MediaAnalyticsItem::SessionID_t generateUniqueSessionID() = 0;
/**
* Submits the indicated record to the mediaanalytics service, where
* it will be merged (if appropriate) with incomplete records that
* share the same key and sessionID.
*
* \param item the item to submit.
* \param forcenew marks any matching incomplete record as complete before
* inserting this new record.
*
* \return the sessionID associated with that item or
* MediaAnalyticsItem::SessionIDInvalid on failure.
* \return status which is negative if an error is detected (some errors
may be silent and return 0 - success).
*/
virtual MediaAnalyticsItem::SessionID_t submit(MediaAnalyticsItem *item, bool forcenew) = 0;
virtual status_t submit(MediaAnalyticsItem *item) = 0;
};
// ----------------------------------------------------------------------------
@ -69,6 +60,11 @@ public:
const Parcel& data,
Parcel* reply,
uint32_t flags = 0) override;
protected:
// Internal call where release is true if the service is to delete the item.
virtual status_t submitInternal(
MediaAnalyticsItem *item, bool release) = 0;
};
}; // namespace android

@ -56,12 +56,6 @@ class MediaAnalyticsItem {
kTypeRate = 5,
};
// sessionid
// unique within device, within boot,
typedef int64_t SessionID_t;
static constexpr SessionID_t SessionIDInvalid = -1;
static constexpr SessionID_t SessionIDNone = 0;
// Key: the record descriminator
// values for the record discriminator
// values can be "component/component"
@ -102,16 +96,6 @@ class MediaAnalyticsItem {
// access functions for the class
~MediaAnalyticsItem();
// SessionID ties multiple submissions for same key together
// so that if video "height" and "width" are known at one point
// and "framerate" is only known later, they can be be brought
// together.
MediaAnalyticsItem &setSessionID(SessionID_t);
MediaAnalyticsItem &clearSessionID();
SessionID_t getSessionID() const;
// generates and stores a new ID iff mSessionID == SessionIDNone
SessionID_t generateSessionID();
// reset all contents, discarding any extra data
void clear();
MediaAnalyticsItem *dup();
@ -149,10 +133,7 @@ class MediaAnalyticsItem {
bool getCString(Attr, char **value);
bool getString(Attr, std::string *value);
// parameter indicates whether to close any existing open
// record with same key before establishing a new record
// caller retains ownership of 'this'.
bool selfrecord(bool);
// Deliver the item to MediaMetrics
bool selfrecord();
// remove indicated attributes and their values
@ -231,12 +212,8 @@ class MediaAnalyticsItem {
static void dropInstance();
// tracking information
SessionID_t mSessionID; // grouping similar records
nsecs_t mTimestamp; // ns, system_time_monotonic
// will this record accept further updates
bool mFinalized;
Key mKey;
struct Prop {

@ -66,19 +66,8 @@ MediaAnalyticsService::~MediaAnalyticsService()
mItems.clear();
}
MediaAnalyticsItem::SessionID_t MediaAnalyticsService::generateUniqueSessionID() {
return ++mLastSessionID;
}
// TODO: consider removing forcenew.
MediaAnalyticsItem::SessionID_t MediaAnalyticsService::submit(
MediaAnalyticsItem *item, bool forcenew __unused)
status_t MediaAnalyticsService::submitInternal(MediaAnalyticsItem *item, bool release)
{
// fill in a sessionID if we do not yet have one
if (item->getSessionID() <= MediaAnalyticsItem::SessionIDNone) {
item->setSessionID(generateUniqueSessionID());
}
// we control these, generally not trusting user input
nsecs_t now = systemTime(SYSTEM_TIME_REALTIME);
// round nsecs to seconds
@ -136,8 +125,8 @@ MediaAnalyticsItem::SessionID_t MediaAnalyticsService::submit(
// validate the record; we discard if we don't like it
if (isContentValid(item, isTrusted) == false) {
delete item;
return MediaAnalyticsItem::SessionIDInvalid;
if (release) delete item;
return PERMISSION_DENIED;
}
// XXX: if we have a sessionid in the new record, look to make
@ -145,18 +134,17 @@ MediaAnalyticsItem::SessionID_t MediaAnalyticsService::submit(
if (item->count() == 0) {
ALOGV("%s: dropping empty record...", __func__);
delete item;
return MediaAnalyticsItem::SessionIDInvalid;
if (release) delete item;
return BAD_VALUE;
}
// send to statsd
extern bool dump2Statsd(MediaAnalyticsItem *item); // extern hook
(void)dump2Statsd(item); // failure should be logged in function.
// keep our copy
const MediaAnalyticsItem::SessionID_t id = item->getSessionID();
if (!release) item = item->dup();
saveItem(item);
return id;
return NO_ERROR;
}
status_t MediaAnalyticsService::dump(int fd, const Vector<String16>& args)

@ -35,31 +35,28 @@ public:
~MediaAnalyticsService() override;
/**
* Submits the indicated record to the mediaanalytics service, where
* it will be merged (if appropriate) with incomplete records that
* share the same key and sessionid.
* Submits the indicated record to the mediaanalytics service.
*
* \param item the item to submit.
* \param forcenew marks any matching incomplete record as complete before
* inserting this new record.
*
* \return the sessionID associated with that item or
* MediaAnalyticsItem::SessionIDInvalid on failure.
*
* BEWARE: When called directly on the service (not from the binder interface),
* the caller surrenders ownership of item, MediaAnalyticsService will delete
* even on error. The binder interface does not take ownership.
* TODO: fix this inconsistency with the binder RPC interface.
* \return status failure, which is negative on binder transaction failure.
* As the transaction is one-way, remote failures will not be reported.
*/
MediaAnalyticsItem::SessionID_t submit(MediaAnalyticsItem *item, bool forcenew) override;
status_t submit(MediaAnalyticsItem *item) override {
return submitInternal(item, false /* release */);
}
status_t dump(int fd, const Vector<String16>& args) override;
static constexpr const char * const kServiceName = "media.metrics";
protected:
// Internal call where release is true if ownership of item is transferred
// to the service (that is, the service will eventually delete the item).
status_t submitInternal(MediaAnalyticsItem *item, bool release) override;
private:
void processExpirations();
MediaAnalyticsItem::SessionID_t generateUniqueSessionID();
// input validation after arrival from client
static bool isContentValid(const MediaAnalyticsItem *item, bool isTrusted);
bool isRateLimited(MediaAnalyticsItem *) const;
@ -86,8 +83,6 @@ private:
const size_t mMaxRecordsExpiredAtOnce;
const int mDumpProtoDefault;
std::atomic<MediaAnalyticsItem::SessionID_t> mLastSessionID{};
class UidInfo {
public:
void setPkgInfo(MediaAnalyticsItem *item, uid_t uid, bool setName, bool setVersion);

@ -30,26 +30,25 @@ TEST(mediametrics_tests, instantiate) {
sp mediaMetrics = new MediaAnalyticsService();
status_t status;
// NOTE: submission of items to MediaMetrics releases ownership, even on error.
// random keys ignored when empty
status = mediaMetrics->submit(MediaAnalyticsItem::create("random_key"), false);
ASSERT_EQ(MediaAnalyticsItem::SessionIDInvalid, status);
std::unique_ptr<MediaAnalyticsItem> random_key(MediaAnalyticsItem::create("random_key"));
status = mediaMetrics->submit(random_key.get());
ASSERT_EQ(PERMISSION_DENIED, status);
// random keys ignored with data
auto random_key = MediaAnalyticsItem::create("random_key");
random_key->setInt32("foo", 10);
status = mediaMetrics->submit(random_key, false);
ASSERT_EQ(MediaAnalyticsItem::SessionIDInvalid, status);
status = mediaMetrics->submit(random_key.get());
ASSERT_EQ(PERMISSION_DENIED, status);
// known keys ignored if empty
status = mediaMetrics->submit(MediaAnalyticsItem::create("audiotrack"), false);
ASSERT_EQ(MediaAnalyticsItem::SessionIDInvalid, status);
auto audiotrack = MediaAnalyticsItem::create("audiotrack");
audiotrack->addInt32("foo", 10);
status = mediaMetrics->submit(audiotrack, false);
ASSERT_GT(status, MediaAnalyticsItem::SessionIDNone);
std::unique_ptr<MediaAnalyticsItem> audiotrack_key(MediaAnalyticsItem::create("audiotrack"));
status = mediaMetrics->submit(audiotrack_key.get());
ASSERT_EQ(BAD_VALUE, status);
// known keys not ignored if not empty
audiotrack_key->addInt32("foo", 10);
status = mediaMetrics->submit(audiotrack_key.get());
ASSERT_EQ(NO_ERROR, status);
mediaMetrics->dump(fileno(stdout), {} /* args */);
}

Loading…
Cancel
Save