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

Commit f25db04c authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Make IGraphicBufferProducer a hybrid interface."

parents b7074a6b 6e1193af
Loading
Loading
Loading
Loading

include/binder/HalToken.h

deleted100644 → 0
+0 −237
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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.
 */

#ifndef ANDROID_HALTOKEN_H
#define ANDROID_HALTOKEN_H

#include <binder/Parcel.h>
#include <hidl/HidlSupport.h>

/**
 * Hybrid Interfaces
 * =================
 *
 * A hybrid interface is a binder interface that
 * 1. is implemented both traditionally and as a wrapper around a hidl
 *    interface, and allows querying whether the underlying instance comes from
 *    a hidl interface or not; and
 * 2. allows efficient calls to a hidl interface (if the underlying instance
 *    comes from a hidl interface) by automatically creating the wrapper in the
 *    process that calls it.
 *
 * Terminology:
 * - `HalToken`: The type for a "token" of a hidl interface. This is defined to
 *   be compatible with `ITokenManager.hal`.
 * - `HInterface`: The base type for a hidl interface. Currently, it is defined
 *   as `::android::hidl::base::V1_0::IBase`.
 * - `HALINTERFACE`: The hidl interface that will be sent through binders.
 * - `INTERFACE`: The binder interface that will be the wrapper of
 *   `HALINTERFACE`. `INTERFACE` is supposed to be somewhat similar to
 *   `HALINTERFACE`.
 *
 * To demonstrate how this is done, here is an example. Suppose `INTERFACE` is
 * `IFoo` and `HALINTERFACE` is `HFoo`. The required steps are:
 * 1. Use DECLARE_HYBRID_META_INTERFACE instead of DECLARE_META_INTERFACE in the
 *    definition of `IFoo`. The usage is
 *        DECLARE_HYBRID_META_INTERFACE(IFoo, HFoo)
 *    inside the body of `IFoo`.
 * 2. Create a converter class that derives from
 *    `H2BConverter<HFoo, IFoo, BnFoo>`. Let us call this `H2BFoo`.
 * 3. Add the following constructor in `H2BFoo` that call the corresponding
 *    constructors in `H2BConverter`:
 *        H2BFoo(const sp<HalInterface>& base) : CBase(base) {}
 *    Note: `CBase = H2BConverter<HFoo, IFoo, BnFoo>` and `HalInterface = HFoo`
 *    are member typedefs of `H2BConverter<HFoo, IFoo, BnFoo>`, so the above
 *    line can be copied into `H2BFoo`.
 * 4. Implement `IFoo` in `H2BFoo` on top of `HFoo`. `H2BConverter` provides a
 *    protected `mBase` of type `sp<HFoo>` that can be used to access the `HFoo`
 *    instance. (There is also a public function named `getHalInterface()` that
 *    returns `mBase`.)
 * 5. Create a hardware proxy class that derives from
 *    `HpInterface<BpFoo, H2BFoo>`. Name this class `HpFoo`. (This name cannot
 *    deviate. See step 8 below.)
 * 6. Add the following constructor to `HpFoo`:
 *        HpFoo(const sp<IBinder>& base): PBase(base) {}
 *    Note: `PBase` a member typedef of `HpInterface<BpFoo, H2BFoo>` that is
 *    equal to `HpInterface<BpFoo, H2BFoo>` itself, so the above line can be
 *    copied verbatim into `HpFoo`.
 * 7. Delegate all functions in `HpFoo` that come from `IFoo` except
 *    `getHalInterface` to the protected member `mBase`,
 *    which is defined in `HpInterface<BpFoo, H2BFoo>` (hence in `HpFoo`) with
 *    type `IFoo`. (There is also a public function named `getBaseInterface()`
 *    that returns `mBase`.)
 * 8. Replace the existing `IMPLEMENT_META_INTERFACE` for INTERFACE by
 *    `IMPLEMENT_HYBRID_META_INTERFACE`. Note that this macro relies on the
 *    exact naming of `HpFoo`, where `Foo` comes from the interface name `IFoo`.
 *    An example usage is
 *        IMPLEMENT_HYBRID_META_INTERFACE(IFoo, HFoo, "example.interface.foo");
 *
 * `GETTOKEN` Template Argument
 * ============================
 *
 * Following the instructions above, `H2BConverter` and `HpInterface` would use
 * `transact()` to send over tokens, with `code` (the first argument of
 * `transact()`) equal to a 4-byte value of '_GTK'. If this value clashes with
 * other values already in use in the `Bp` class, it can be changed by supplying
 * the last optional template argument to `H2BConverter` and `HpInterface`.
 *
 */

namespace android {

typedef uint64_t HalToken;
typedef ::android::hidl::base::V1_0::IBase HInterface;

sp<HInterface> retrieveHalInterface(const HalToken& token);
bool createHalToken(const sp<HInterface>& interface, HalToken* token);
bool deleteHalToken(const HalToken& token);

template <
        typename HINTERFACE,
        typename INTERFACE,
        typename BNINTERFACE,
        uint32_t GETTOKEN = '_GTK'>
class H2BConverter : public BNINTERFACE {
public:
    typedef H2BConverter<HINTERFACE, INTERFACE, BNINTERFACE, GETTOKEN> CBase; // Converter Base
    typedef INTERFACE BaseInterface;
    typedef HINTERFACE HalInterface;
    static constexpr uint32_t GET_HAL_TOKEN = GETTOKEN;

    H2BConverter(const sp<HalInterface>& base) : mBase(base) {}
    virtual status_t onTransact(uint32_t code,
            const Parcel& data, Parcel* reply, uint32_t flags = 0);
    sp<HalInterface> getHalInterface() override { return mBase; }
    HalInterface* getBaseInterface() { return mBase.get(); }

protected:
    sp<HalInterface> mBase;
};

template <
        typename BPINTERFACE,
        typename CONVERTER,
        uint32_t GETTOKEN = '_GTK'>
class HpInterface : public CONVERTER::BaseInterface {
public:
    typedef HpInterface<BPINTERFACE, CONVERTER, GETTOKEN> PBase; // Proxy Base
    typedef typename CONVERTER::BaseInterface BaseInterface;
    typedef typename CONVERTER::HalInterface HalInterface;
    static constexpr uint32_t GET_HAL_TOKEN = GETTOKEN;

    explicit HpInterface(const sp<IBinder>& impl);
    sp<HalInterface> getHalInterface() override { return mHal; }
    BaseInterface* getBaseInterface() { return mBase.get(); }

protected:
    sp<IBinder> mImpl;
    sp<BaseInterface> mBase;
    sp<HalInterface> mHal;
    IBinder* onAsBinder() override { return mImpl.get(); }
};

// ----------------------------------------------------------------------

#define DECLARE_HYBRID_META_INTERFACE(INTERFACE, HAL)                   \
    static const ::android::String16 descriptor;                        \
    static ::android::sp<I##INTERFACE> asInterface(                     \
            const ::android::sp<::android::IBinder>& obj);              \
    virtual const ::android::String16& getInterfaceDescriptor() const;  \
    I##INTERFACE();                                                     \
    virtual ~I##INTERFACE();                                            \
    virtual sp<HAL> getHalInterface();                                  \


#define IMPLEMENT_HYBRID_META_INTERFACE(INTERFACE, HAL, NAME)           \
    const ::android::String16 I##INTERFACE::descriptor(NAME);           \
    const ::android::String16&                                          \
            I##INTERFACE::getInterfaceDescriptor() const {              \
        return I##INTERFACE::descriptor;                                \
    }                                                                   \
    ::android::sp<I##INTERFACE> I##INTERFACE::asInterface(              \
            const ::android::sp<::android::IBinder>& obj)               \
    {                                                                   \
        ::android::sp<I##INTERFACE> intr;                               \
        if (obj != NULL) {                                              \
            intr = static_cast<I##INTERFACE*>(                          \
                obj->queryLocalInterface(                               \
                        I##INTERFACE::descriptor).get());               \
            if (intr == NULL) {                                         \
                intr = new Hp##INTERFACE(obj);                          \
            }                                                           \
        }                                                               \
        return intr;                                                    \
    }                                                                   \
    I##INTERFACE::I##INTERFACE() { }                                    \
    I##INTERFACE::~I##INTERFACE() { }                                   \
    sp<HAL> I##INTERFACE::getHalInterface() { return nullptr; }         \

// ----------------------------------------------------------------------

template <
        typename HINTERFACE,
        typename INTERFACE,
        typename BNINTERFACE,
        uint32_t GETTOKEN>
status_t H2BConverter<HINTERFACE, INTERFACE, BNINTERFACE, GETTOKEN>::
        onTransact(
        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
    if (code == GET_HAL_TOKEN) {
        HalToken token;
        bool result;
        result = createHalToken(mBase, &token);
        if (!result) {
            ALOGE("H2BConverter: Failed to create HAL token.");
        }
        reply->writeBool(result);
        reply->writeUint64(token);
        return NO_ERROR;
    }
    return BNINTERFACE::onTransact(code, data, reply, flags);
}

template <typename BPINTERFACE, typename CONVERTER, uint32_t GETTOKEN>
HpInterface<BPINTERFACE, CONVERTER, GETTOKEN>::HpInterface(
        const sp<IBinder>& impl) : mImpl(impl) {
    Parcel data, reply;
    data.writeInterfaceToken(BaseInterface::getInterfaceDescriptor());
    if (impl->transact(GET_HAL_TOKEN, data, &reply) == NO_ERROR) {
        bool tokenCreated = reply.readBool();
        HalToken token = reply.readUint64();
        if (!tokenCreated) {
            ALOGE("HpInterface: Sender failed to create HAL token.");
            mBase = new BPINTERFACE(impl);
        } else {
            sp<HInterface> hInterface = retrieveHalInterface(token);
            deleteHalToken(token);
            if (hInterface != nullptr) {
                mHal = static_cast<HalInterface*>(hInterface.get());
                mBase = new CONVERTER(mHal);
            } else {
                ALOGE("HpInterface: Cannot retrieve HAL interface from token.");
                mBase = new BPINTERFACE(impl);
            }
        }
    } else {
        mBase = new BPINTERFACE(impl);
    }
}

// ----------------------------------------------------------------------

}; // namespace android

#endif // ANDROID_HALTOKEN_H
+1 −5
Original line number Diff line number Diff line
@@ -18,16 +18,12 @@
#define ANDROID_GUI_BUFFERQUEUECOREDEFS_H

#include <gui/BufferSlot.h>
#include <ui/BufferQueueDefs.h>

namespace android {
    class BufferQueueCore;

    namespace BufferQueueDefs {
        // BufferQueue will keep track of at most this value of buffers.
        // Attempts at runtime to increase the number of buffers past this
        // will fail.
        enum { NUM_BUFFER_SLOTS = 64 };

        typedef BufferSlot SlotsType[NUM_BUFFER_SLOTS];
    } // namespace BufferQueueDefs
} // namespace android
+6 −1
Original line number Diff line number Diff line
@@ -32,12 +32,17 @@

#include <gui/FrameTimestamps.h>

#include <hidl/HybridInterface.h>
#include <android/hardware/graphics/bufferqueue/1.0/IGraphicBufferProducer.h>

namespace android {
// ----------------------------------------------------------------------------

class IProducerListener;
class NativeHandle;
class Surface;
typedef ::android::hardware::graphics::bufferqueue::V1_0::IGraphicBufferProducer
        HGraphicBufferProducer;

/*
 * This class defines the Binder IPC interface for the producer side of
@@ -56,7 +61,7 @@ class Surface;
class IGraphicBufferProducer : public IInterface
{
public:
    DECLARE_META_INTERFACE(GraphicBufferProducer)
    DECLARE_HYBRID_META_INTERFACE(GraphicBufferProducer, HGraphicBufferProducer)

    enum {
        // A flag returned by dequeueBuffer when the client needs to call
+66 −0
Original line number Diff line number Diff line
/*
 * Copyright 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.
 */

#ifndef ANDROID_HARDWARE_GRAPHICS_BUFFERQUEUE_V1_0_B2HPRODUCERLISTENER_H
#define ANDROID_HARDWARE_GRAPHICS_BUFFERQUEUE_V1_0_B2HPRODUCERLISTENER_H

#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>

#include <binder/IBinder.h>
#include <gui/IProducerListener.h>

#include <android/hidl/base/1.0/IBase.h>
#include <android/hardware/graphics/bufferqueue/1.0/IProducerListener.h>

namespace android {
namespace hardware {
namespace graphics {
namespace bufferqueue {
namespace V1_0 {
namespace utils {

using ::android::hidl::base::V1_0::IBase;
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_memory;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::sp;

typedef ::android::hardware::graphics::bufferqueue::V1_0::IProducerListener
        HProducerListener;

typedef ::android::IProducerListener
        BProducerListener;

struct B2HProducerListener : public HProducerListener {
    sp<BProducerListener> mBase;
    B2HProducerListener(sp<BProducerListener> const& base);
    Return<void> onBufferReleased() override;
    Return<bool> needsReleaseNotify() override;
};

}  // namespace utils
}  // namespace V1_0
}  // namespace omx
}  // namespace media
}  // namespace hardware
}  // namespace android

#endif  // ANDROID_HARDWARE_GRAPHICS_BUFFERQUEUE_V1_0_B2HPRODUCERLISTENER_H
+106 −0
Original line number Diff line number Diff line
/*
 * Copyright 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.
 */

#ifndef ANDROID_HARDWARE_GRAPHICS_BUFFERQUEUE_V1_0_H2BGRAPHICBUFFERPRODUCER_H
#define ANDROID_HARDWARE_GRAPHICS_BUFFERQUEUE_V1_0_H2BGRAPHICBUFFERPRODUCER_H

#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>

#include <binder/Binder.h>
#include <gui/IGraphicBufferProducer.h>
#include <gui/IProducerListener.h>

#include <hidl/HybridInterface.h>
#include <android/hardware/graphics/bufferqueue/1.0/IGraphicBufferProducer.h>

namespace android {
namespace hardware {
namespace graphics {
namespace bufferqueue {
namespace V1_0 {
namespace utils {

using ::android::hidl::base::V1_0::IBase;
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_memory;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::sp;

using ::android::hardware::graphics::common::V1_0::PixelFormat;
using ::android::hardware::media::V1_0::AnwBuffer;

typedef ::android::hardware::graphics::bufferqueue::V1_0::IGraphicBufferProducer
        HGraphicBufferProducer;
typedef ::android::hardware::graphics::bufferqueue::V1_0::IProducerListener
        HProducerListener;

typedef ::android::IGraphicBufferProducer BGraphicBufferProducer;
using ::android::BnGraphicBufferProducer;
using ::android::IProducerListener;

struct H2BGraphicBufferProducer : public ::android::H2BConverter<
        HGraphicBufferProducer,
        BGraphicBufferProducer,
        BnGraphicBufferProducer> {
    H2BGraphicBufferProducer(sp<HGraphicBufferProducer> const& base) : CBase(base) {}

    status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) override;
    status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers) override;
    status_t setAsyncMode(bool async) override;
    status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w,
            uint32_t h, ::android::PixelFormat format, uint32_t usage,
            FrameEventHistoryDelta* outTimestamps) override;
    status_t detachBuffer(int slot) override;
    status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence)
            override;
    status_t attachBuffer(int* outSlot, const sp<GraphicBuffer>& buffer)
            override;
    status_t queueBuffer(int slot,
            const QueueBufferInput& input,
            QueueBufferOutput* output) override;
    status_t cancelBuffer(int slot, const sp<Fence>& fence) override;
    int query(int what, int* value) override;
    status_t connect(const sp<IProducerListener>& listener, int api,
            bool producerControlledByApp, QueueBufferOutput* output) override;
    status_t disconnect(int api, DisconnectMode mode = DisconnectMode::Api)
            override;
    status_t setSidebandStream(const sp<NativeHandle>& stream) override;
    void allocateBuffers(uint32_t width, uint32_t height,
            ::android::PixelFormat format, uint32_t usage) override;
    status_t allowAllocation(bool allow) override;
    status_t setGenerationNumber(uint32_t generationNumber) override;
    String8 getConsumerName() const override;
    status_t setSharedBufferMode(bool sharedBufferMode) override;
    status_t setAutoRefresh(bool autoRefresh) override;
    status_t setDequeueTimeout(nsecs_t timeout) override;
    status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
          sp<Fence>* outFence, float outTransformMatrix[16]) override;
    void getFrameTimestamps(FrameEventHistoryDelta* outDelta) override;
    status_t getUniqueId(uint64_t* outId) const override;
};

}  // namespace utils
}  // namespace V1_0
}  // namespace bufferqueue
}  // namespace graphics
}  // namespace hardware
}  // namespace android

#endif  // ANDROID_HARDWARE_GRAPHICS_BUFFERQUEUE_V1_0_H2BGRAPHICBUFFERPRODUCER_H
Loading