Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a87e69cf authored by Andy Hung's avatar Andy Hung
Browse files

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
parent 2392e6d9
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -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());
+0 −1
Original line number Diff line number Diff line
@@ -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;
+1 −3
Original line number Diff line number Diff line
@@ -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;
+24 −93
Original line number Diff line number Diff line
@@ -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);
        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;
    }
        return sessionid;
    }

};

IMPLEMENT_META_INTERFACE(MediaAnalyticsService, "android.media.IMediaAnalyticsService");
@@ -115,44 +72,18 @@ 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 GENERATE_UNIQUE_SESSIONID: {
    case SUBMIT_ITEM_ONEWAY: {
        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);

        MediaAnalyticsItem * const item = MediaAnalyticsItem::create();
        if (item->readFromParcel(data) < 0) {
            return BAD_VALUE;
        }
        item->setPid(clientPid);

            // submit() takes over ownership of 'item'
            MediaAnalyticsItem::SessionID_t sessionid = submit(item, forcenew);
            reply->writeInt64(sessionid);

        const status_t status __unused = submitInternal(item, true /* release */);
        return NO_ERROR;
    } break;

+57 −137
Original line number Diff line number Diff line
@@ -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,62 +904,39 @@ 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");
        ALOGD_IF(DEBUG_SERVICEACCESS, "disabled");
        return nullptr;
    }
        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);
        const char *badness = "";

        // think of remainingBindAttempts as telling us whether service==NULL because
    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 == NULL && remainingBindAttempts > 0) {
    if (sAnalyticsService == nullptr && sRemainingBindAttempts > 0) {
        const char *badness = "";
        sp<IServiceManager> sm = defaultServiceManager();
            if (sm != NULL) {
        if (sm != nullptr) {
            sp<IBinder> binder = sm->getService(String16(servicename));
                if (binder != NULL) {
            if (binder != nullptr) {
                sAnalyticsService = interface_cast<IMediaAnalyticsService>(binder);
                    if (sNotifier != NULL) {
                        sNotifier = NULL;
                    }
                sNotifier = new MediaMetricsDeathNotifier();
                binder->linkToDeath(sNotifier);
            } else {
@@ -1019,20 +945,16 @@ sp<IMediaAnalyticsService> MediaAnalyticsItem::getInstance() {
        } else {
            badness = "No Service Manager access";
        }

            if (sAnalyticsService == NULL) {
                if (remainingBindAttempts > 0) {
                    remainingBindAttempts--;
                }
                if (DEBUG_SERVICEACCESS) {
                    ALOGD("Unable to bind to service %s: %s", servicename, badness);
        if (sAnalyticsService == nullptr) {
            if (sRemainingBindAttempts > 0) {
                sRemainingBindAttempts--;
            }
            ALOGD_IF(DEBUG_SERVICEACCESS, "%s: unable to bind to service %s: %s",
                    __func__, servicename, badness);
        }
    }

    return sAnalyticsService;
}
}

// merge the info from 'incoming' into this record.
// we finish with a union of this+incoming and special handling for collisions
@@ -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
Loading