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

Commit 579b3f88 authored by Mathias Agopian's avatar Mathias Agopian
Browse files

allow re-targetting of surfaces

Surfaces can now be parcelized and sent to remote
processes. When a surface crosses a process
boundary, it looses its connection with the
current process and gets attached to the new one.

Change-Id: I39c7b055bcd3ea1162ef2718d3d4b866bf7c81c0
parent 53503a97
Loading
Loading
Loading
Loading
+6 −10
Original line number Diff line number Diff line
@@ -44,15 +44,6 @@ namespace android {
 * dequeue-able buffer. When these various conditions are not met, the caller
 * waits until the condition is met.
 * 
 * 
 * CAVEATS:
 * 
 * In the current implementation there are several limitations:
 * - buffers must be locked in the same order they've been dequeued
 * - buffers must be enqueued in the same order they've been locked
 * - dequeue() is not reentrant
 * - no error checks are done on the condition above
 * 
 */

// ----------------------------------------------------------------------------
@@ -269,7 +260,9 @@ private:

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

class SharedBufferServer : public SharedBufferBase
class SharedBufferServer
    : public SharedBufferBase,
      public LightRefBase<SharedBufferServer>
{
public:
    SharedBufferServer(SharedClient* sharedClient, int surface, int num,
@@ -290,6 +283,9 @@ public:
    

private:
    friend class LightRefBase<SharedBufferServer>;
    ~SharedBufferServer();

    /*
     * BufferList is basically a fixed-capacity sorted-vector of
     * unsigned 5-bits ints using a 32-bits int as storage.
+3 −3
Original line number Diff line number Diff line
@@ -60,7 +60,6 @@ public:
    static bool isSameSurface(
            const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs);
        
    SurfaceID   ID() const      { return mToken; }
    uint32_t    getFlags() const { return mFlags; }
    uint32_t    getIdentity() const { return mIdentity; }

@@ -145,6 +144,9 @@ public:
        uint32_t    reserved[2];
    };

    static status_t writeToParcel(
            const sp<Surface>& control, Parcel* parcel);

    static sp<Surface> readFromParcel(
            const Parcel& data, const sp<Surface>& other);

@@ -153,7 +155,6 @@ public:
    }

    bool        isValid();
    SurfaceID   ID() const          { return mToken; }
    uint32_t    getFlags() const    { return mFlags; }
    uint32_t    getIdentity() const { return mIdentity; }

@@ -267,7 +268,6 @@ private:
    SharedBufferClient*         mSharedBufferClient;
    status_t                    mInitCheck;
    sp<ISurface>                mSurface;
    SurfaceID                   mToken;
    uint32_t                    mIdentity;
    PixelFormat                 mFormat;
    uint32_t                    mFlags;
+35 −13
Original line number Diff line number Diff line
@@ -76,15 +76,18 @@ Layer::~Layer()
status_t Layer::setToken(const sp<UserClient>& userClient,
        SharedClient* sharedClient, int32_t token)
{
    SharedBufferServer* lcblk = new SharedBufferServer(
    sp<SharedBufferServer> lcblk = new SharedBufferServer(
            sharedClient, token, mBufferManager.getDefaultBufferCount(),
            getIdentity());

    status_t err = mUserClientRef.setToken(userClient, lcblk, token);
    if (err != NO_ERROR) {
        LOGE("ClientRef::setToken(%p, %p, %u) failed",
                userClient.get(), lcblk, token);
        delete lcblk;

    LOGE_IF(err != NO_ERROR,
            "ClientRef::setToken(%p, %p, %u) failed",
            userClient.get(), lcblk.get(), token);

    if (err == NO_ERROR) {
        // we need to free the buffers associated with this surface
    }

    return err;
@@ -95,6 +98,11 @@ int32_t Layer::getToken() const
    return mUserClientRef.getToken();
}

sp<UserClient> Layer::getClient() const
{
    return mUserClientRef.getClient();
}

// called with SurfaceFlinger::mStateLock as soon as the layer is entered
// in the purgatory list
void Layer::onRemoved()
@@ -626,11 +634,10 @@ void Layer::dump(String8& result, char* buffer, size_t SIZE) const
// ---------------------------------------------------------------------------

Layer::ClientRef::ClientRef()
    : mToken(-1) {
    : mControlBlock(0), mToken(-1) {
}

Layer::ClientRef::~ClientRef() {
    delete lcblk;
}

int32_t Layer::ClientRef::getToken() const {
@@ -638,14 +645,25 @@ int32_t Layer::ClientRef::getToken() const {
    return mToken;
}

sp<UserClient> Layer::ClientRef::getClient() const {
    Mutex::Autolock _l(mLock);
    return mUserClient.promote();
}

status_t Layer::ClientRef::setToken(const sp<UserClient>& uc,
        SharedBufferServer* sharedClient, int32_t token) {
        const sp<SharedBufferServer>& sharedClient, int32_t token) {
    Mutex::Autolock _l(mLock);
    if (mToken >= 0)
        return INVALID_OPERATION;

    { // scope for strong mUserClient reference
        sp<UserClient> userClient(mUserClient.promote());
        if (mUserClient != 0 && mControlBlock != 0) {
            mControlBlock->setStatus(NO_INIT);
        }
    }

    mUserClient = uc;
    mToken = token;
    lcblk = sharedClient;
    mControlBlock = sharedClient;
    return NO_ERROR;
}

@@ -657,12 +675,16 @@ sp<UserClient> Layer::ClientRef::getUserClientUnsafe() const {
// it makes sure the UserClient (and its associated shared memory)
// won't go away while we're accessing it.
Layer::ClientRef::Access::Access(const ClientRef& ref)
    : lcblk(0)
    : mControlBlock(0)
{
    Mutex::Autolock _l(ref.mLock);
    mUserClientStrongRef = ref.mUserClient.promote();
    if (mUserClientStrongRef != 0)
        lcblk = ref.lcblk;
        mControlBlock = ref.mControlBlock;
}

Layer::ClientRef::Access::~Access()
{
}

// ---------------------------------------------------------------------------
+7 −4
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ public:
    // associate a UserClient to this Layer
    status_t setToken(const sp<UserClient>& uc, SharedClient* sc, int32_t idx);
    int32_t getToken() const;
    sp<UserClient> getClient() const;

    // Set this Layer's buffers size
    void setBufferSize(uint32_t w, uint32_t h);
@@ -119,24 +120,26 @@ private:
        ClientRef& operator = (const ClientRef& rhs);
        mutable Mutex mLock;
        // binder thread, page-flip thread
        SharedBufferServer* lcblk;
        sp<SharedBufferServer> mControlBlock;
        wp<UserClient> mUserClient;
        int32_t mToken;
    public:
        ClientRef();
        ~ClientRef();
        int32_t getToken() const;
        sp<UserClient> getClient() const;
        status_t setToken(const sp<UserClient>& uc,
                SharedBufferServer* sharedClient, int32_t token);
                const sp<SharedBufferServer>& sharedClient, int32_t token);
        sp<UserClient> getUserClientUnsafe() const;
        class Access {
            Access(const Access& rhs);
            Access& operator = (const Access& rhs);
            sp<UserClient> mUserClientStrongRef;
            SharedBufferServer* lcblk;
            sp<SharedBufferServer> mControlBlock;
        public:
            Access(const ClientRef& ref);
            inline SharedBufferServer* get() const { return lcblk; }
            ~Access();
            inline SharedBufferServer* get() const { return mControlBlock.get(); }
        };
        friend class Access;
    };
+14 −5
Original line number Diff line number Diff line
@@ -1718,7 +1718,10 @@ void UserClient::detachLayer(const Layer* layer)
{
    int32_t name = layer->getToken();
    if (name >= 0) {
        android_atomic_and(~(1LU<<name), &mBitmap);
        int32_t mask = 1LU<<name;
        if ((android_atomic_and(~mask, &mBitmap) & mask) == 0) {
            LOGW("token %d wasn't marked as used %08x", name, int(mBitmap));
        }
    }
}

@@ -1732,17 +1735,23 @@ ssize_t UserClient::getTokenForSurface(const sp<ISurface>& sur) const
    sp<Layer> layer(mFlinger->getLayer(sur));
    if (layer == 0) return name;

    // this layer already has a token, just return it
    // FIXME: we should check that this token is for the same client
    // if this layer already has a token, just return it
    name = layer->getToken();
    if (name >= 0) return name;
    if ((name >= 0) && (layer->getClient() == this))
        return name;

    name = 0;
    do {
        int32_t mask = 1LU<<name;
        if ((android_atomic_or(mask, &mBitmap) & mask) == 0) {
            // we found and locked that name
            layer->setToken(const_cast<UserClient*>(this), ctrlblk, name);
            status_t err = layer->setToken(
                    const_cast<UserClient*>(this), ctrlblk, name);
            if (err != NO_ERROR) {
                // free the name
                android_atomic_and(~mask, &mBitmap);
                name = err;
            }
            break;
        }
        if (++name > 31)
Loading