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

Commit 3b8e6b2f authored by Matthew Bouyack's avatar Matthew Bouyack
Browse files

Eliminate unnecessary calls to onBufferReleased

This change adds a callback to ProducerListener to indicate whether the
listener needs the 'onBufferReleased' notification. This allows us to
avoid making that binder call unnecessarily, saving ~170us per frame on
Android Wear.

By default the new callback returns true, so behavior for existing
clients should be unchanged. Only the DummyProducerListener returns
false.

Also note that it would be simpler to just pass NULL for the
ProducerListener if not for that fact that we still need it for death
notification.

Bug: b/31122630

Change-Id: I730834218a055d89e89f876dd77da8127eb78000
parent 3169437f
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -185,8 +185,12 @@ private:
    // PID of the process which last successfully called connect(...)
    pid_t mConnectedPid;

    // mConnectedProducerToken is used to set a binder death notification on
    // mLinkedToDeath is used to set a binder death notification on
    // the producer.
    sp<IProducerListener> mLinkedToDeath;

    // mConnectedProducerListener is used to handle the onBufferReleased
    // notification.
    sp<IProducerListener> mConnectedProducerListener;

    // mSlots is an array of buffer slots that must be mirrored on the producer
+3 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ public:
    // This is called without any lock held and can be called concurrently by
    // multiple threads.
    virtual void onBufferReleased() = 0; // Asynchronous
    virtual bool needsReleaseNotify() = 0;
};

class IProducerListener : public ProducerListener, public IInterface
@@ -54,12 +55,14 @@ class BnProducerListener : public BnInterface<IProducerListener>
public:
    virtual status_t onTransact(uint32_t code, const Parcel& data,
            Parcel* reply, uint32_t flags = 0);
    virtual bool needsReleaseNotify();
};

class DummyProducerListener : public BnProducerListener
{
public:
    virtual void onBufferReleased() {}
    virtual bool needsReleaseNotify() { return false; }
};

} // namespace android
+1 −0
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ BufferQueueCore::BufferQueueCore(const sp<IGraphicBufferAlloc>& allocator) :
    mConsumerListener(),
    mConsumerUsageBits(0),
    mConnectedApi(NO_CONNECTED_API),
    mLinkedToDeath(),
    mConnectedProducerListener(),
    mSlots(),
    mQueue(),
+17 −12
Original line number Diff line number Diff line
@@ -1113,18 +1113,22 @@ status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
                    static_cast<uint32_t>(mCore->mQueue.size()),
                    mCore->mFrameCounter + 1);

            if (listener != NULL) {
                // Set up a death notification so that we can disconnect
                // automatically if the remote producer dies
            if (listener != NULL &&
                    IInterface::asBinder(listener)->remoteBinder() != NULL) {
                if (IInterface::asBinder(listener)->remoteBinder() != NULL) {
                    status = IInterface::asBinder(listener)->linkToDeath(
                            static_cast<IBinder::DeathRecipient*>(this));
                    if (status != NO_ERROR) {
                        BQ_LOGE("connect: linkToDeath failed: %s (%d)",
                                strerror(-status), status);
                    }
                    mCore->mLinkedToDeath = listener;
                }
                if (listener->needsReleaseNotify()) {
                    mCore->mConnectedProducerListener = listener;
                }
            }
            break;
        default:
            BQ_LOGE("connect: unknown API %d", api);
@@ -1186,9 +1190,9 @@ status_t BufferQueueProducer::disconnect(int api, DisconnectMode mode) {
                    mCore->freeAllBuffersLocked();

                    // Remove our death notification callback if we have one
                    if (mCore->mConnectedProducerListener != NULL) {
                    if (mCore->mLinkedToDeath != NULL) {
                        sp<IBinder> token =
                                IInterface::asBinder(mCore->mConnectedProducerListener);
                                IInterface::asBinder(mCore->mLinkedToDeath);
                        // This can fail if we're here because of the death
                        // notification, but we just ignore it
                        token->unlinkToDeath(
@@ -1196,6 +1200,7 @@ status_t BufferQueueProducer::disconnect(int api, DisconnectMode mode) {
                    }
                    mCore->mSharedBufferSlot =
                            BufferQueueCore::INVALID_BUFFER_SLOT;
                    mCore->mLinkedToDeath = NULL;
                    mCore->mConnectedProducerListener = NULL;
                    mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API;
                    mCore->mConnectedPid = -1;
+26 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ namespace android {

enum {
    ON_BUFFER_RELEASED = IBinder::FIRST_CALL_TRANSACTION,
    NEEDS_RELEASE_NOTIFY,
};

class BpProducerListener : public BpInterface<IProducerListener>
@@ -37,6 +38,23 @@ public:
        data.writeInterfaceToken(IProducerListener::getInterfaceDescriptor());
        remote()->transact(ON_BUFFER_RELEASED, data, &reply, IBinder::FLAG_ONEWAY);
    }

    virtual bool needsReleaseNotify() {
        bool result;
        Parcel data, reply;
        data.writeInterfaceToken(IProducerListener::getInterfaceDescriptor());
        status_t err = remote()->transact(NEEDS_RELEASE_NOTIFY, data, &reply);
        if (err != NO_ERROR) {
            ALOGE("IProducerListener: binder call \'needsReleaseNotify\' failed");
            return true;
        }
        err = reply.readBool(&result);
        if (err != NO_ERROR) {
            ALOGE("IProducerListener: malformed binder reply");
            return true;
        }
        return result;
    }
};

// Out-of-line virtual method definition to trigger vtable emission in this
@@ -52,8 +70,16 @@ status_t BnProducerListener::onTransact(uint32_t code, const Parcel& data,
            CHECK_INTERFACE(IProducerListener, data, reply);
            onBufferReleased();
            return NO_ERROR;
        case NEEDS_RELEASE_NOTIFY:
            CHECK_INTERFACE(IProducerListener, data, reply);
            reply->writeBool(needsReleaseNotify());
            return NO_ERROR;
    }
    return BBinder::onTransact(code, data, reply, flags);
}

bool BnProducerListener::needsReleaseNotify() {
    return true;
}

} // namespace android