split surface management from surface's buffers management
Change-Id: If3c5655d1231f8f0c49ba68f972b1b20c93b3f87
diff --git a/libs/surfaceflinger_client/ISurfaceComposer.cpp b/libs/surfaceflinger_client/ISurfaceComposer.cpp
index 50495c1..5c111f6 100644
--- a/libs/surfaceflinger_client/ISurfaceComposer.cpp
+++ b/libs/surfaceflinger_client/ISurfaceComposer.cpp
@@ -55,6 +55,15 @@
return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
}
+ virtual sp<ISurfaceComposerClient> createClientConnection()
+ {
+ uint32_t n;
+ Parcel data, reply;
+ data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+ remote()->transact(BnSurfaceComposer::CREATE_CLIENT_CONNECTION, data, &reply);
+ return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
+ }
+
virtual sp<IMemoryHeap> getCblk() const
{
Parcel data, reply;
@@ -136,6 +145,11 @@
sp<IBinder> b = createConnection()->asBinder();
reply->writeStrongBinder(b);
} break;
+ case CREATE_CLIENT_CONNECTION: {
+ CHECK_INTERFACE(ISurfaceComposer, data, reply);
+ sp<IBinder> b = createClientConnection()->asBinder();
+ reply->writeStrongBinder(b);
+ } break;
case OPEN_GLOBAL_TRANSACTION: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
openGlobalTransaction();
diff --git a/libs/surfaceflinger_client/ISurfaceComposerClient.cpp b/libs/surfaceflinger_client/ISurfaceComposerClient.cpp
index 67c7df8..2cc1f8e 100644
--- a/libs/surfaceflinger_client/ISurfaceComposerClient.cpp
+++ b/libs/surfaceflinger_client/ISurfaceComposerClient.cpp
@@ -51,6 +51,7 @@
enum {
GET_CBLK = IBinder::FIRST_CALL_TRANSACTION,
+ GET_TOKEN,
CREATE_SURFACE,
DESTROY_SURFACE,
SET_STATE
@@ -72,6 +73,15 @@
return interface_cast<IMemoryHeap>(reply.readStrongBinder());
}
+ virtual ssize_t getTokenForSurface(const sp<ISurface>& sur) const
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor());
+ data.writeStrongBinder(sur->asBinder());
+ remote()->transact(GET_TOKEN, data, &reply);
+ return reply.readInt32();
+ }
+
virtual sp<ISurface> createSurface( surface_data_t* params,
int pid,
const String8& name,
@@ -132,6 +142,13 @@
reply->writeStrongBinder(ctl->asBinder());
return NO_ERROR;
} break;
+ case GET_TOKEN: {
+ CHECK_INTERFACE(ISurfaceComposerClient, data, reply);
+ sp<ISurface> sur = interface_cast<ISurface>(data.readStrongBinder());
+ ssize_t token = getTokenForSurface(sur);
+ reply->writeInt32(token);
+ return NO_ERROR;
+ } break;
}
// these must be checked
diff --git a/libs/surfaceflinger_client/SharedBufferStack.cpp b/libs/surfaceflinger_client/SharedBufferStack.cpp
index 8d03145..1dd8642 100644
--- a/libs/surfaceflinger_client/SharedBufferStack.cpp
+++ b/libs/surfaceflinger_client/SharedBufferStack.cpp
@@ -58,7 +58,7 @@
void SharedBufferStack::init(int32_t i)
{
- inUse = -1;
+ inUse = -2;
status = NO_ERROR;
identity = i;
}
@@ -282,8 +282,10 @@
}
ssize_t SharedBufferServer::UnlockUpdate::operator()() {
if (stack.inUse != lockedBuffer) {
- LOGE("unlocking %d, but currently locked buffer is %d",
- lockedBuffer, stack.inUse);
+ LOGE("unlocking %d, but currently locked buffer is %d "
+ "(identity=%d, token=%d)",
+ lockedBuffer, stack.inUse,
+ stack.identity, stack.token);
return BAD_VALUE;
}
android_atomic_write(-1, &stack.inUse);
@@ -480,6 +482,7 @@
mNumBuffers(num)
{
mSharedStack->init(identity);
+ mSharedStack->token = surface;
mSharedStack->head = num-1;
mSharedStack->available = num;
mSharedStack->queued = 0;
diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp
index ac4b198..01420fe 100644
--- a/libs/surfaceflinger_client/Surface.cpp
+++ b/libs/surfaceflinger_client/Surface.cpp
@@ -238,14 +238,12 @@
{
uint32_t flags = 0;
uint32_t format = 0;
- SurfaceID token = -1;
uint32_t identity = 0;
uint32_t width = 0;
uint32_t height = 0;
sp<SurfaceComposerClient> client;
sp<ISurface> sur;
if (SurfaceControl::isValid(control)) {
- token = control->mToken;
identity = control->mIdentity;
client = control->mClient;
sur = control->mSurface;
@@ -254,9 +252,7 @@
format = control->mFormat;
flags = control->mFlags;
}
- parcel->writeStrongBinder(client!=0 ? client->connection() : NULL);
- parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL);
- parcel->writeInt32(token);
+ parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL);
parcel->writeInt32(identity);
parcel->writeInt32(width);
parcel->writeInt32(height);
@@ -278,31 +274,78 @@
// Surface
// ============================================================================
+class SurfaceClient : public Singleton<SurfaceClient>
+{
+ // all these attributes are constants
+ sp<ISurfaceComposer> mComposerService;
+ sp<ISurfaceComposerClient> mClient;
+ status_t mStatus;
+ SharedClient* mControl;
+ sp<IMemoryHeap> mControlMemory;
+
+ SurfaceClient()
+ : Singleton<SurfaceClient>(), mStatus(NO_INIT)
+ {
+ sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+ mComposerService = sf;
+ mClient = sf->createClientConnection();
+ if (mClient != NULL) {
+ mControlMemory = mClient->getControlBlock();
+ if (mControlMemory != NULL) {
+ mControl = static_cast<SharedClient *>(
+ mControlMemory->getBase());
+ if (mControl) {
+ mStatus = NO_ERROR;
+ }
+ }
+ }
+ }
+ friend class Singleton<SurfaceClient>;
+public:
+ status_t initCheck() const {
+ return mStatus;
+ }
+ SharedClient* getSharedClient() const {
+ return mControl;
+ }
+ ssize_t getTokenForSurface(const sp<ISurface>& sur) const {
+ // TODO: we could cache a few tokens here to avoid an IPC
+ return mClient->getTokenForSurface(sur);
+ }
+ void signalServer() const {
+ mComposerService->signal();
+ }
+};
+
+ANDROID_SINGLETON_STATIC_INSTANCE(SurfaceClient);
+
+// ---------------------------------------------------------------------------
+
Surface::Surface(const sp<SurfaceControl>& surface)
- : mSurface(surface->mSurface),
- mToken(surface->mToken), mIdentity(surface->mIdentity),
- mFormat(surface->mFormat), mFlags(surface->mFlags),
- mBufferMapper(GraphicBufferMapper::get()), mSharedBufferClient(NULL),
+ : mBufferMapper(GraphicBufferMapper::get()),
+ mClient(SurfaceClient::getInstance()),
+ mSharedBufferClient(NULL),
mInitCheck(NO_INIT),
+ mSurface(surface->mSurface),
+ mIdentity(surface->mIdentity),
+ mFormat(surface->mFormat), mFlags(surface->mFlags),
mWidth(surface->mWidth), mHeight(surface->mHeight)
{
- mClient = new SurfaceClient(surface->mClient);
init();
}
Surface::Surface(const Parcel& parcel)
- : mBufferMapper(GraphicBufferMapper::get()),
- mSharedBufferClient(NULL), mInitCheck(NO_INIT)
+ : mBufferMapper(GraphicBufferMapper::get()),
+ mClient(SurfaceClient::getInstance()),
+ mSharedBufferClient(NULL),
+ mInitCheck(NO_INIT)
{
- sp<IBinder> conn = parcel.readStrongBinder();
mSurface = interface_cast<ISurface>(parcel.readStrongBinder());
- mToken = parcel.readInt32();
mIdentity = parcel.readInt32();
mWidth = parcel.readInt32();
mHeight = parcel.readInt32();
mFormat = parcel.readInt32();
mFlags = parcel.readInt32();
- mClient = new SurfaceClient(conn);
init();
}
@@ -330,12 +373,14 @@
mBuffers.setCapacity(2);
mBuffers.insertAt(0, 2);
- if (mClient != 0 && mClient->initCheck() == NO_ERROR) {
- mSharedBufferClient = new SharedBufferClient(
- mClient->getSharedClient(), mToken, 2, mIdentity);
+ if (mSurface != 0 && mClient.initCheck() == NO_ERROR) {
+ mToken = mClient.getTokenForSurface(mSurface);
+ if (mToken >= 0) {
+ mSharedBufferClient = new SharedBufferClient(
+ mClient.getSharedClient(), mToken, 2, mIdentity);
+ mInitCheck = mClient.getSharedClient()->validate(mToken);
+ }
}
-
- mInitCheck = initCheck();
}
Surface::~Surface()
@@ -352,25 +397,11 @@
// clear all references and trigger an IPC now, to make sure things
// happen without delay, since these resources are quite heavy.
mBuffers.clear();
- mClient.clear();
mSurface.clear();
delete mSharedBufferClient;
IPCThreadState::self()->flushCommands();
}
-status_t Surface::initCheck() const
-{
- if (mToken<0 || mClient==0 || mClient->initCheck() != NO_ERROR) {
- return NO_INIT;
- }
- SharedClient const* cblk = mClient->getSharedClient();
- if (cblk == 0) {
- LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity);
- return NO_INIT;
- }
- return cblk->validate(mToken);
-}
-
bool Surface::isValid() {
return mInitCheck == NO_ERROR;
}
@@ -379,8 +410,7 @@
{
// check that we initialized ourself properly
if (mInitCheck != NO_ERROR) {
- LOGE("invalid token (%d, identity=%u) or client (%p)",
- mToken, mIdentity, mClient.get());
+ LOGE("invalid token (%d, identity=%u)", mToken, mIdentity);
return mInitCheck;
}
@@ -558,8 +588,8 @@
LOGE_IF(err, "error queuing buffer %d (%s)", bufIdx, strerror(-err));
if (err == NO_ERROR) {
- // FIXME: can we avoid this IPC if we know there is one pending?
- mClient->signalServer();
+ // TODO: can we avoid this IPC if we know there is one pending?
+ mClient.signalServer();
}
return err;
}
diff --git a/libs/surfaceflinger_client/SurfaceComposerClient.cpp b/libs/surfaceflinger_client/SurfaceComposerClient.cpp
index 0670d20..5ac0d5d 100644
--- a/libs/surfaceflinger_client/SurfaceComposerClient.cpp
+++ b/libs/surfaceflinger_client/SurfaceComposerClient.cpp
@@ -42,36 +42,26 @@
namespace android {
// ---------------------------------------------------------------------------
-class ComposerService : public Singleton<ComposerService>
-{
- // these are constants
- sp<ISurfaceComposer> mComposerService;
- sp<IMemoryHeap> mServerCblkMemory;
- surface_flinger_cblk_t volatile* mServerCblk;
-
- ComposerService() : Singleton<ComposerService>() {
- const String16 name("SurfaceFlinger");
- while (getService(name, &mComposerService) != NO_ERROR) {
- usleep(250000);
- }
- mServerCblkMemory = mComposerService->getCblk();
- mServerCblk = static_cast<surface_flinger_cblk_t volatile *>(
- mServerCblkMemory->getBase());
- }
-
- friend class Singleton<ComposerService>;
-
-public:
- static sp<ISurfaceComposer> getComposerService() {
- return ComposerService::getInstance().mComposerService;
- }
- static surface_flinger_cblk_t const volatile * getControlBlock() {
- return ComposerService::getInstance().mServerCblk;
- }
-};
-
ANDROID_SINGLETON_STATIC_INSTANCE(ComposerService);
+ComposerService::ComposerService()
+: Singleton<ComposerService>() {
+ const String16 name("SurfaceFlinger");
+ while (getService(name, &mComposerService) != NO_ERROR) {
+ usleep(250000);
+ }
+ mServerCblkMemory = mComposerService->getCblk();
+ mServerCblk = static_cast<surface_flinger_cblk_t volatile *>(
+ mServerCblkMemory->getBase());
+}
+
+sp<ISurfaceComposer> ComposerService::getComposerService() {
+ return ComposerService::getInstance().mComposerService;
+}
+
+surface_flinger_cblk_t const volatile * ComposerService::getControlBlock() {
+ return ComposerService::getInstance().mServerCblk;
+}
static inline sp<ISurfaceComposer> getComposerService() {
return ComposerService::getComposerService();
@@ -557,41 +547,5 @@
}
// ----------------------------------------------------------------------------
-
-SurfaceClient::SurfaceClient(const sp<SurfaceComposerClient>& client)
- : mStatus(NO_INIT), mControl(0)
-{
- if (client != 0) {
- sp<IBinder> conn = client->connection();
- init(conn);
- }
-}
-SurfaceClient::SurfaceClient(const sp<IBinder>& conn)
- : mStatus(NO_INIT), mControl(0)
-{
- init(conn);
-}
-void SurfaceClient::init(const sp<IBinder>& conn)
-{
- mComposerService = getComposerService();
- sp<ISurfaceComposerClient> sf(interface_cast<ISurfaceComposerClient>(conn));
- if (sf != 0) {
- mConnection = conn;
- mControlMemory = sf->getControlBlock();
- mControl = static_cast<SharedClient *>(mControlMemory->getBase());
- mStatus = NO_ERROR;
- }
-}
-status_t SurfaceClient::initCheck() const {
- return mStatus;
-}
-SharedClient* SurfaceClient::getSharedClient() const {
- return mControl;
-}
-void SurfaceClient::signalServer() const {
- mComposerService->signal();
-}
-
-// ----------------------------------------------------------------------------
}; // namespace android