diff options
-rw-r--r-- | include/ui/Surface.h | 72 | ||||
-rw-r--r-- | include/ui/SurfaceComposerClient.h | 29 | ||||
-rw-r--r-- | libs/ui/Surface.cpp | 313 | ||||
-rw-r--r-- | libs/ui/SurfaceComposerClient.cpp | 60 |
4 files changed, 369 insertions, 105 deletions
diff --git a/include/ui/Surface.h b/include/ui/Surface.h index 1637961..87a11c2 100644 --- a/include/ui/Surface.h +++ b/include/ui/Surface.h @@ -76,6 +76,76 @@ private: // --------------------------------------------------------------------------- +class SurfaceControl : public RefBase +{ +public: + static bool isValid(const sp<SurfaceControl>& surface) { + return (surface != 0) && surface->mToken>=0 && surface->mClient!=0; + } + + SurfaceID ID() const { return mToken; } + uint32_t getFlags() const { return mFlags; } + uint32_t getIdentity() const { return mIdentity; } + + // release surface data from java + void clear(); + + static sp<SurfaceControl> readFromParcel(Parcel* parcel); + static status_t writeToParcel(const sp<SurfaceControl>& surface, Parcel* parcel); + static bool isSameSurface(const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs); + + status_t setLayer(int32_t layer); + status_t setPosition(int32_t x, int32_t y); + status_t setSize(uint32_t w, uint32_t h); + status_t hide(); + status_t show(int32_t layer = -1); + status_t freeze(); + status_t unfreeze(); + status_t setFlags(uint32_t flags, uint32_t mask); + status_t setTransparentRegionHint(const Region& transparent); + status_t setAlpha(float alpha=1.0f); + status_t setMatrix(float dsdx, float dtdx, float dsdy, float dtdy); + status_t setFreezeTint(uint32_t tint); + +private: + friend class SurfaceComposerClient; + + // camera and camcorder need access to the ISurface binder interface for preview + friend class Camera; + friend class MediaRecorder; + // mediaplayer needs access to ISurface for display + friend class MediaPlayer; + friend class Test; + const sp<ISurface>& getISurface() const { return mSurface; } + + // can't be copied + SurfaceControl& operator = (SurfaceControl& rhs); + SurfaceControl(const SurfaceControl& rhs); + + friend class Surface; + SurfaceControl(const sp<SurfaceComposerClient>& client, + const sp<ISurface>& surface, + const ISurfaceFlingerClient::surface_data_t& data, + uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, + bool owner = true); + + ~SurfaceControl(); + + status_t validate(per_client_cblk_t const* cblk) const; + void destroy(); + + sp<SurfaceComposerClient> mClient; + sp<ISurface> mSurface; + SurfaceID mToken; + uint32_t mIdentity; + PixelFormat mFormat; + uint32_t mFlags; + const bool mOwner; + mutable Mutex mLock; +}; + +// --------------------------------------------------------------------------- + class Surface : public EGLNativeBase<android_native_window_t, Surface, RefBase> { @@ -192,6 +262,8 @@ private: mutable Rect mSwapRectangle; mutable uint8_t mBackbufferIndex; mutable Mutex mSurfaceLock; + + sp<SurfaceControl> mSurfaceControl; }; }; // namespace android diff --git a/include/ui/SurfaceComposerClient.h b/include/ui/SurfaceComposerClient.h index 86de6ea..a175a18 100644 --- a/include/ui/SurfaceComposerClient.h +++ b/include/ui/SurfaceComposerClient.h @@ -111,22 +111,23 @@ public: private: friend class Surface; + friend class SurfaceControl; SurfaceComposerClient(const sp<ISurfaceComposer>& sm, const sp<IBinder>& conn); - status_t hide(Surface* surface); - status_t show(Surface* surface, int32_t layer = -1); - status_t freeze(Surface* surface); - status_t unfreeze(Surface* surface); - status_t setFlags(Surface* surface, uint32_t flags, uint32_t mask); - status_t setTransparentRegionHint(Surface* surface, const Region& transparent); - status_t setLayer(Surface* surface, int32_t layer); - status_t setAlpha(Surface* surface, float alpha=1.0f); - status_t setFreezeTint(Surface* surface, uint32_t tint); - status_t setMatrix(Surface* surface, float dsdx, float dtdx, float dsdy, float dtdy); - status_t setPosition(Surface* surface, int32_t x, int32_t y); - status_t setSize(Surface* surface, uint32_t w, uint32_t h); + status_t hide(SurfaceID id); + status_t show(SurfaceID id, int32_t layer = -1); + status_t freeze(SurfaceID id); + status_t unfreeze(SurfaceID id); + status_t setFlags(SurfaceID id, uint32_t flags, uint32_t mask); + status_t setTransparentRegionHint(SurfaceID id, const Region& transparent); + status_t setLayer(SurfaceID id, int32_t layer); + status_t setAlpha(SurfaceID id, float alpha=1.0f); + status_t setFreezeTint(SurfaceID id, uint32_t tint); + status_t setMatrix(SurfaceID id, float dsdx, float dtdx, float dsdy, float dtdy); + status_t setPosition(SurfaceID id, int32_t x, int32_t y); + status_t setSize(SurfaceID id, uint32_t w, uint32_t h); void signalServer(); @@ -135,8 +136,8 @@ private: void _init(const sp<ISurfaceComposer>& sm, const sp<ISurfaceFlingerClient>& conn); - inline layer_state_t* _get_state_l(const sp<Surface>& surface); - layer_state_t* _lockLayerState(const sp<Surface>& surface); + inline layer_state_t* _get_state_l(SurfaceID id); + layer_state_t* _lockLayerState(SurfaceID id); inline void _unlockLayerState(); mutable Mutex mLock; diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp index 51abd95..63699c7 100644 --- a/libs/ui/Surface.cpp +++ b/libs/ui/Surface.cpp @@ -143,6 +143,216 @@ static void copyBlt(const android_native_buffer_t* dst, } } + +// ============================================================================ +// SurfaceControl +// ============================================================================ + + +SurfaceControl::SurfaceControl(const sp<SurfaceComposerClient>& client, + const sp<ISurface>& surface, + const ISurfaceFlingerClient::surface_data_t& data, + uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, + bool owner) + : mClient(client), mSurface(surface), + mToken(data.token), mIdentity(data.identity), + mFormat(format), mFlags(flags), mOwner(owner) +{ +} + +SurfaceControl::~SurfaceControl() +{ + destroy(); +} + +void SurfaceControl::destroy() +{ + // Destroy the surface in SurfaceFlinger if we were the owner + // (in any case, a client won't be able to, because it won't have the + // right permission). + if (mOwner && mToken>=0 && mClient!=0) { + mClient->destroySurface(mToken); + } + + // clear all references and trigger an IPC now, to make sure things + // happen without delay, since these resources are quite heavy. + mClient.clear(); + mSurface.clear(); + IPCThreadState::self()->flushCommands(); +} + +void SurfaceControl::clear() +{ + // here, the window manager tells us explicitly that we should destroy + // the surface's resource. Soon after this call, it will also release + // its last reference (which will call the dtor); however, it is possible + // that a client living in the same process still holds references which + // would delay the call to the dtor -- that is why we need this explicit + // "clear()" call. + destroy(); +} + +status_t SurfaceControl::setLayer(int32_t layer) { + const sp<SurfaceComposerClient>& client(mClient); + if (client == 0) return INVALID_OPERATION; + status_t err = validate(client->mControl); + if (err < 0) return err; + return client->setLayer(mToken, layer); +} +status_t SurfaceControl::setPosition(int32_t x, int32_t y) { + const sp<SurfaceComposerClient>& client(mClient); + if (client == 0) return INVALID_OPERATION; + status_t err = validate(client->mControl); + if (err < 0) return err; + return client->setPosition(mToken, x, y); +} +status_t SurfaceControl::setSize(uint32_t w, uint32_t h) { + const sp<SurfaceComposerClient>& client(mClient); + if (client == 0) return INVALID_OPERATION; + status_t err = validate(client->mControl); + if (err < 0) return err; + return client->setSize(mToken, w, h); +} +status_t SurfaceControl::hide() { + const sp<SurfaceComposerClient>& client(mClient); + if (client == 0) return INVALID_OPERATION; + status_t err = validate(client->mControl); + if (err < 0) return err; + return client->hide(mToken); +} +status_t SurfaceControl::show(int32_t layer) { + const sp<SurfaceComposerClient>& client(mClient); + if (client == 0) return INVALID_OPERATION; + status_t err = validate(client->mControl); + if (err < 0) return err; + return client->show(mToken, layer); +} +status_t SurfaceControl::freeze() { + const sp<SurfaceComposerClient>& client(mClient); + if (client == 0) return INVALID_OPERATION; + status_t err = validate(client->mControl); + if (err < 0) return err; + return client->freeze(mToken); +} +status_t SurfaceControl::unfreeze() { + const sp<SurfaceComposerClient>& client(mClient); + if (client == 0) return INVALID_OPERATION; + status_t err = validate(client->mControl); + if (err < 0) return err; + return client->unfreeze(mToken); +} +status_t SurfaceControl::setFlags(uint32_t flags, uint32_t mask) { + const sp<SurfaceComposerClient>& client(mClient); + if (client == 0) return INVALID_OPERATION; + status_t err = validate(client->mControl); + if (err < 0) return err; + return client->setFlags(mToken, flags, mask); +} +status_t SurfaceControl::setTransparentRegionHint(const Region& transparent) { + const sp<SurfaceComposerClient>& client(mClient); + if (client == 0) return INVALID_OPERATION; + status_t err = validate(client->mControl); + if (err < 0) return err; + return client->setTransparentRegionHint(mToken, transparent); +} +status_t SurfaceControl::setAlpha(float alpha) { + const sp<SurfaceComposerClient>& client(mClient); + if (client == 0) return INVALID_OPERATION; + status_t err = validate(client->mControl); + if (err < 0) return err; + return client->setAlpha(mToken, alpha); +} +status_t SurfaceControl::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) { + const sp<SurfaceComposerClient>& client(mClient); + if (client == 0) return INVALID_OPERATION; + status_t err = validate(client->mControl); + if (err < 0) return err; + return client->setMatrix(mToken, dsdx, dtdx, dsdy, dtdy); +} +status_t SurfaceControl::setFreezeTint(uint32_t tint) { + const sp<SurfaceComposerClient>& client(mClient); + if (client == 0) return INVALID_OPERATION; + status_t err = validate(client->mControl); + if (err < 0) return err; + return client->setFreezeTint(mToken, tint); +} + +sp<SurfaceControl> SurfaceControl::readFromParcel(Parcel* parcel) +{ + sp<SurfaceComposerClient> client; + ISurfaceFlingerClient::surface_data_t data; + sp<IBinder> clientBinder= parcel->readStrongBinder(); + sp<ISurface> surface = interface_cast<ISurface>(parcel->readStrongBinder()); + data.token = parcel->readInt32(); + data.identity = parcel->readInt32(); + PixelFormat format = parcel->readInt32(); + uint32_t flags = parcel->readInt32(); + + if (clientBinder != NULL) + client = SurfaceComposerClient::clientForConnection(clientBinder); + + return new SurfaceControl(client, surface, data, 0, 0, format, flags, false); +} + +status_t SurfaceControl::writeToParcel(const sp<SurfaceControl>& surface, Parcel* parcel) +{ + uint32_t flags=0; + uint32_t format=0; + SurfaceID token = -1; + uint32_t identity = 0; + sp<SurfaceComposerClient> client; + sp<ISurface> sur; + if (SurfaceControl::isValid(surface)) { + token = surface->mToken; + identity = surface->mIdentity; + client = surface->mClient; + sur = surface->mSurface; + format = surface->mFormat; + flags = surface->mFlags; + } + parcel->writeStrongBinder(client!=0 ? client->connection() : NULL); + parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL); + parcel->writeInt32(token); + parcel->writeInt32(identity); + parcel->writeInt32(format); + parcel->writeInt32(flags); + return NO_ERROR; +} + +bool SurfaceControl::isSameSurface( + const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs) +{ + if (lhs == 0 || rhs == 0) + return false; + return lhs->mSurface->asBinder() == rhs->mSurface->asBinder(); +} + + +status_t SurfaceControl::validate(per_client_cblk_t const* cblk) const +{ + if (mToken<0 || mClient==0) { + LOGE("invalid token (%d, identity=%u) or client (%p)", + mToken, mIdentity, mClient.get()); + return NO_INIT; + } + if (cblk == 0) { + LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity); + return NO_INIT; + } + status_t err = cblk->validate(mToken); + if (err != NO_ERROR) { + LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)", + mToken, mIdentity, err, strerror(-err)); + return err; + } + if (mIdentity != uint32_t(cblk->layers[mToken].identity)) { + LOGE("using an invalid surface id=%d, identity=%u should be %d", + mToken, mIdentity, cblk->layers[mToken].identity); + return NO_INIT; + } + return NO_ERROR; +} + // ============================================================================ // Surface // ============================================================================ @@ -156,6 +366,9 @@ Surface::Surface(const sp<SurfaceComposerClient>& client, mToken(data.token), mIdentity(data.identity), mFormat(format), mFlags(flags), mOwner(owner) { + mSurfaceControl = new SurfaceControl( + client, surface, data, w, h, format, flags, owner); + android_native_window_t::connect = connect; android_native_window_t::disconnect = disconnect; android_native_window_t::setSwapInterval = setSwapInterval; @@ -191,12 +404,7 @@ Surface::~Surface() void Surface::destroy() { - // Destroy the surface in SurfaceFlinger if we were the owner - // (in any case, a client won't be able to, because it won't have the - // right permission). - if (mOwner && mToken>=0 && mClient!=0) { - mClient->destroySurface(mToken); - } + mSurfaceControl->destroy(); // clear all references and trigger an IPC now, to make sure things // happen without delay, since these resources are quite heavy. @@ -207,20 +415,7 @@ void Surface::destroy() void Surface::clear() { - // here, the window manager tells us explicitly that we should destroy - // the surface's resource. Soon after this call, it will also release - // its last reference (which will call the dtor); however, it is possible - // that a client living in the same process still holds references which - // would delay the call to the dtor -- that is why we need this explicit - // "clear()" call. - - // FIXME: we should probably unmap the buffers here. The problem is that - // the app could be in the middle of using them, and if we don't unmap now - // and we're in the system process, the mapping will be lost (because - // the buffer will be freed, and the handles destroyed) - - Mutex::Autolock _l(mSurfaceLock); - destroy(); + mSurfaceControl->clear(); } status_t Surface::validate(per_client_cblk_t const* cblk) const @@ -473,44 +668,6 @@ void Surface::_send_dirty_region( } } - -status_t Surface::setLayer(int32_t layer) { - return mClient->setLayer(this, layer); -} -status_t Surface::setPosition(int32_t x, int32_t y) { - return mClient->setPosition(this, x, y); -} -status_t Surface::setSize(uint32_t w, uint32_t h) { - return mClient->setSize(this, w, h); -} -status_t Surface::hide() { - return mClient->hide(this); -} -status_t Surface::show(int32_t layer) { - return mClient->show(this, layer); -} -status_t Surface::freeze() { - return mClient->freeze(this); -} -status_t Surface::unfreeze() { - return mClient->unfreeze(this); -} -status_t Surface::setFlags(uint32_t flags, uint32_t mask) { - return mClient->setFlags(this, flags, mask); -} -status_t Surface::setTransparentRegionHint(const Region& transparent) { - return mClient->setTransparentRegionHint(this, transparent); -} -status_t Surface::setAlpha(float alpha) { - return mClient->setAlpha(this, alpha); -} -status_t Surface::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) { - return mClient->setMatrix(this, dsdx, dtdx, dsdy, dtdy); -} -status_t Surface::setFreezeTint(uint32_t tint) { - return mClient->setFreezeTint(this, tint); -} - Region Surface::dirtyRegion() const { return mDirtyRegion; } @@ -593,5 +750,45 @@ status_t Surface::getBufferLocked(int index) return err; } + + +status_t Surface::setLayer(int32_t layer) { + return mSurfaceControl->setLayer(layer); +} +status_t Surface::setPosition(int32_t x, int32_t y) { + return mSurfaceControl->setPosition(x, y); +} +status_t Surface::setSize(uint32_t w, uint32_t h) { + return mSurfaceControl->setSize(w, h); +} +status_t Surface::hide() { + return mSurfaceControl->hide(); +} +status_t Surface::show(int32_t layer) { + return mSurfaceControl->show(layer); +} +status_t Surface::freeze() { + return mSurfaceControl->freeze(); +} +status_t Surface::unfreeze() { + return mSurfaceControl->unfreeze(); +} +status_t Surface::setFlags(uint32_t flags, uint32_t mask) { + return mSurfaceControl->setFlags(flags, mask); +} +status_t Surface::setTransparentRegionHint(const Region& transparent) { + return mSurfaceControl->setTransparentRegionHint(transparent); +} +status_t Surface::setAlpha(float alpha) { + return mSurfaceControl->setAlpha(alpha); +} +status_t Surface::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) { + return mSurfaceControl->setMatrix(dsdx, dtdx, dsdy, dtdy); +} +status_t Surface::setFreezeTint(uint32_t tint) { + return mSurfaceControl->setFreezeTint(tint); +} + + }; // namespace android diff --git a/libs/ui/SurfaceComposerClient.cpp b/libs/ui/SurfaceComposerClient.cpp index e1b13c7..4ccd396 100644 --- a/libs/ui/SurfaceComposerClient.cpp +++ b/libs/ui/SurfaceComposerClient.cpp @@ -616,14 +616,8 @@ status_t SurfaceComposerClient::closeTransaction() return NO_ERROR; } -layer_state_t* SurfaceComposerClient::_get_state_l(const sp<Surface>& surface) +layer_state_t* SurfaceComposerClient::_get_state_l(SurfaceID index) { - SurfaceID index = surface->ID(); - per_client_cblk_t* const cblk = mControl; - status_t err = surface->validate(cblk); - if (err != NO_ERROR) - return 0; - // API usage error, do nothing. if (mTransactionOpen<=0) { LOGE("Not in transaction (client=%p, SurfaceID=%d, mTransactionOpen=%d", @@ -642,11 +636,11 @@ layer_state_t* SurfaceComposerClient::_get_state_l(const sp<Surface>& surface) return mStates.editArray() + i; } -layer_state_t* SurfaceComposerClient::_lockLayerState(const sp<Surface>& surface) +layer_state_t* SurfaceComposerClient::_lockLayerState(SurfaceID id) { layer_state_t* s; mLock.lock(); - s = _get_state_l(surface); + s = _get_state_l(id); if (!s) mLock.unlock(); return s; } @@ -656,9 +650,9 @@ void SurfaceComposerClient::_unlockLayerState() mLock.unlock(); } -status_t SurfaceComposerClient::setPosition(Surface* surface, int32_t x, int32_t y) +status_t SurfaceComposerClient::setPosition(SurfaceID id, int32_t x, int32_t y) { - layer_state_t* s = _lockLayerState(surface); + layer_state_t* s = _lockLayerState(id); if (!s) return BAD_INDEX; s->what |= ISurfaceComposer::ePositionChanged; s->x = x; @@ -667,9 +661,9 @@ status_t SurfaceComposerClient::setPosition(Surface* surface, int32_t x, int32_t return NO_ERROR; } -status_t SurfaceComposerClient::setSize(Surface* surface, uint32_t w, uint32_t h) +status_t SurfaceComposerClient::setSize(SurfaceID id, uint32_t w, uint32_t h) { - layer_state_t* s = _lockLayerState(surface); + layer_state_t* s = _lockLayerState(id); if (!s) return BAD_INDEX; s->what |= ISurfaceComposer::eSizeChanged; s->w = w; @@ -678,9 +672,9 @@ status_t SurfaceComposerClient::setSize(Surface* surface, uint32_t w, uint32_t h return NO_ERROR; } -status_t SurfaceComposerClient::setLayer(Surface* surface, int32_t z) +status_t SurfaceComposerClient::setLayer(SurfaceID id, int32_t z) { - layer_state_t* s = _lockLayerState(surface); + layer_state_t* s = _lockLayerState(id); if (!s) return BAD_INDEX; s->what |= ISurfaceComposer::eLayerChanged; s->z = z; @@ -688,32 +682,32 @@ status_t SurfaceComposerClient::setLayer(Surface* surface, int32_t z) return NO_ERROR; } -status_t SurfaceComposerClient::hide(Surface* surface) +status_t SurfaceComposerClient::hide(SurfaceID id) { - return setFlags(surface, ISurfaceComposer::eLayerHidden, + return setFlags(id, ISurfaceComposer::eLayerHidden, ISurfaceComposer::eLayerHidden); } -status_t SurfaceComposerClient::show(Surface* surface, int32_t) +status_t SurfaceComposerClient::show(SurfaceID id, int32_t) { - return setFlags(surface, 0, ISurfaceComposer::eLayerHidden); + return setFlags(id, 0, ISurfaceComposer::eLayerHidden); } -status_t SurfaceComposerClient::freeze(Surface* surface) +status_t SurfaceComposerClient::freeze(SurfaceID id) { - return setFlags(surface, ISurfaceComposer::eLayerFrozen, + return setFlags(id, ISurfaceComposer::eLayerFrozen, ISurfaceComposer::eLayerFrozen); } -status_t SurfaceComposerClient::unfreeze(Surface* surface) +status_t SurfaceComposerClient::unfreeze(SurfaceID id) { - return setFlags(surface, 0, ISurfaceComposer::eLayerFrozen); + return setFlags(id, 0, ISurfaceComposer::eLayerFrozen); } -status_t SurfaceComposerClient::setFlags(Surface* surface, +status_t SurfaceComposerClient::setFlags(SurfaceID id, uint32_t flags, uint32_t mask) { - layer_state_t* s = _lockLayerState(surface); + layer_state_t* s = _lockLayerState(id); if (!s) return BAD_INDEX; s->what |= ISurfaceComposer::eVisibilityChanged; s->flags &= ~mask; @@ -724,9 +718,9 @@ status_t SurfaceComposerClient::setFlags(Surface* surface, } status_t SurfaceComposerClient::setTransparentRegionHint( - Surface* surface, const Region& transparentRegion) + SurfaceID id, const Region& transparentRegion) { - layer_state_t* s = _lockLayerState(surface); + layer_state_t* s = _lockLayerState(id); if (!s) return BAD_INDEX; s->what |= ISurfaceComposer::eTransparentRegionChanged; s->transparentRegion = transparentRegion; @@ -734,9 +728,9 @@ status_t SurfaceComposerClient::setTransparentRegionHint( return NO_ERROR; } -status_t SurfaceComposerClient::setAlpha(Surface* surface, float alpha) +status_t SurfaceComposerClient::setAlpha(SurfaceID id, float alpha) { - layer_state_t* s = _lockLayerState(surface); + layer_state_t* s = _lockLayerState(id); if (!s) return BAD_INDEX; s->what |= ISurfaceComposer::eAlphaChanged; s->alpha = alpha; @@ -745,11 +739,11 @@ status_t SurfaceComposerClient::setAlpha(Surface* surface, float alpha) } status_t SurfaceComposerClient::setMatrix( - Surface* surface, + SurfaceID id, float dsdx, float dtdx, float dsdy, float dtdy ) { - layer_state_t* s = _lockLayerState(surface); + layer_state_t* s = _lockLayerState(id); if (!s) return BAD_INDEX; s->what |= ISurfaceComposer::eMatrixChanged; layer_state_t::matrix22_t matrix; @@ -762,9 +756,9 @@ status_t SurfaceComposerClient::setMatrix( return NO_ERROR; } -status_t SurfaceComposerClient::setFreezeTint(Surface* surface, uint32_t tint) +status_t SurfaceComposerClient::setFreezeTint(SurfaceID id, uint32_t tint) { - layer_state_t* s = _lockLayerState(surface); + layer_state_t* s = _lockLayerState(id); if (!s) return BAD_INDEX; s->what |= ISurfaceComposer::eFreezeTintChanged; s->tint = tint; |