SurfaceTexture: make (dis)connect into an IPC

This change makes the ANativeWindow connect and disconnect calls result
in an IPC to the SurfaceTexture object.  This will allow us to prevent
multiple simultaneous connections from different processes.

Change-Id: Id9aa1003b1335b96ca6bd4a1f5a67aa433d42efb
This commit is contained in:
Jamie Gennis 2011-07-13 19:12:20 -07:00
parent 3e646d62e5
commit fe0a87b546
6 changed files with 127 additions and 40 deletions

View File

@ -104,6 +104,24 @@ protected:
// queued buffers will be retired in order.
// The default mode is asynchronous.
virtual status_t setSynchronousMode(bool enabled) = 0;
// connect attempts to connect a client API to the SurfaceTexture. This
// must be called before any other ISurfaceTexture methods are called except
// for getAllocator.
//
// This method will fail if the connect was previously called on the
// SurfaceTexture and no corresponding disconnect call was made.
virtual status_t connect(int api) = 0;
// disconnect attempts to disconnect a client API from the SurfaceTexture.
// Calling this method will cause any subsequent calls to other
// ISurfaceTexture methods to fail except for getAllocator and connect.
// Successfully calling connect after this will allow the other methods to
// succeed again.
//
// This method will fail if the the SurfaceTexture is not currently
// connected to the specified client API.
virtual status_t disconnect(int api) = 0;
};
// ----------------------------------------------------------------------------

View File

@ -44,6 +44,7 @@ public:
MIN_SYNC_BUFFER_SLOTS = MIN_UNDEQUEUED_BUFFERS
};
enum { NUM_BUFFER_SLOTS = 32 };
enum { NO_CONNECTED_API = 0 };
struct FrameAvailableListener : public virtual RefBase {
// onFrameAvailable() is called from queueBuffer() each time an
@ -97,6 +98,24 @@ public:
// The default mode is asynchronous.
virtual status_t setSynchronousMode(bool enabled);
// connect attempts to connect a client API to the SurfaceTexture. This
// must be called before any other ISurfaceTexture methods are called except
// for getAllocator.
//
// This method will fail if the connect was previously called on the
// SurfaceTexture and no corresponding disconnect call was made.
virtual status_t connect(int api);
// disconnect attempts to disconnect a client API from the SurfaceTexture.
// Calling this method will cause any subsequent calls to other
// ISurfaceTexture methods to fail except for getAllocator and connect.
// Successfully calling connect after this will allow the other methods to
// succeed again.
//
// This method will fail if the the SurfaceTexture is not currently
// connected to the specified client API.
virtual status_t disconnect(int api);
// updateTexImage sets the image contents of the target texture to that of
// the most recently queued buffer.
//
@ -362,6 +381,11 @@ private:
// mAllowSynchronousMode whether we allow synchronous mode or not
const bool mAllowSynchronousMode;
// mConnectedApi indicates the API that is currently connected to this
// SurfaceTexture. It defaults to NO_CONNECTED_API (= 0), and gets updated
// by the connect and disconnect methods.
int mConnectedApi;
// mDequeueCondition condition used for dequeueBuffer in synchronous mode
mutable Condition mDequeueCondition;

View File

@ -126,9 +126,6 @@ private:
// a timestamp is auto-generated when queueBuffer is called.
int64_t mTimestamp;
// mConnectedApi holds the currently connected API to this surface
int mConnectedApi;
// mQueryWidth is the width returned by query(). It is set to width
// of the last dequeued buffer or to mReqWidth if no buffer was dequeued.
uint32_t mQueryWidth;

View File

@ -41,6 +41,8 @@ enum {
GET_ALLOCATOR,
QUERY,
SET_SYNCHRONOUS_MODE,
CONNECT,
DISCONNECT,
};
@ -154,7 +156,23 @@ public:
return result;
}
virtual status_t connect(int api) {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
data.writeInt32(api);
remote()->transact(CONNECT, data, &reply);
status_t result = reply.readInt32();
return result;
}
virtual status_t disconnect(int api) {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
data.writeInt32(api);
remote()->transact(DISCONNECT, data, &reply);
status_t result = reply.readInt32();
return result;
}
};
IMPLEMENT_META_INTERFACE(SurfaceTexture, "android.gui.SurfaceTexture");
@ -248,6 +266,20 @@ status_t BnSurfaceTexture::onTransact(
reply->writeInt32(res);
return NO_ERROR;
} break;
case CONNECT: {
CHECK_INTERFACE(ISurfaceTexture, data, reply);
int api = data.readInt32();
status_t res = connect(api);
reply->writeInt32(res);
return NO_ERROR;
} break;
case DISCONNECT: {
CHECK_INTERFACE(ISurfaceTexture, data, reply);
int api = data.readInt32();
status_t res = connect(api);
reply->writeInt32(res);
return NO_ERROR;
} break;
}
return BBinder::onTransact(code, data, reply, flags);
}

View File

@ -92,7 +92,8 @@ SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode) :
mNextTransform(0),
mTexName(tex),
mSynchronousMode(false),
mAllowSynchronousMode(allowSynchronousMode) {
mAllowSynchronousMode(allowSynchronousMode),
mConnectedApi(NO_CONNECTED_API) {
LOGV("SurfaceTexture::SurfaceTexture");
sp<ISurfaceComposer> composer(ComposerService::getComposerService());
mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
@ -493,6 +494,50 @@ status_t SurfaceTexture::setTransform(uint32_t transform) {
return OK;
}
status_t SurfaceTexture::connect(int api) {
LOGV("SurfaceTexture::connect");
Mutex::Autolock lock(mMutex);
int err = NO_ERROR;
switch (api) {
case NATIVE_WINDOW_API_EGL:
case NATIVE_WINDOW_API_CPU:
case NATIVE_WINDOW_API_MEDIA:
case NATIVE_WINDOW_API_CAMERA:
if (mConnectedApi != NO_CONNECTED_API) {
err = -EINVAL;
} else {
mConnectedApi = api;
}
break;
default:
err = -EINVAL;
break;
}
return err;
}
status_t SurfaceTexture::disconnect(int api) {
LOGV("SurfaceTexture::disconnect");
Mutex::Autolock lock(mMutex);
int err = NO_ERROR;
switch (api) {
case NATIVE_WINDOW_API_EGL:
case NATIVE_WINDOW_API_CPU:
case NATIVE_WINDOW_API_MEDIA:
case NATIVE_WINDOW_API_CAMERA:
if (mConnectedApi == api) {
mConnectedApi = NO_CONNECTED_API;
} else {
err = -EINVAL;
}
break;
default:
err = -EINVAL;
break;
}
return err;
}
status_t SurfaceTexture::updateTexImage() {
LOGV("SurfaceTexture::updateTexImage");
Mutex::Autolock lock(mMutex);

View File

@ -27,7 +27,7 @@ SurfaceTextureClient::SurfaceTextureClient(
const sp<ISurfaceTexture>& surfaceTexture):
mSurfaceTexture(surfaceTexture), mAllocator(0), mReqWidth(0),
mReqHeight(0), mReqFormat(0), mReqUsage(0),
mTimestamp(NATIVE_WINDOW_TIMESTAMP_AUTO), mConnectedApi(0),
mTimestamp(NATIVE_WINDOW_TIMESTAMP_AUTO),
mQueryWidth(0), mQueryHeight(0), mQueryFormat(0),
mMutex() {
// Initialize the ANativeWindow function pointers.
@ -306,51 +306,22 @@ int SurfaceTextureClient::dispatchSetBuffersTimestamp(va_list args) {
int SurfaceTextureClient::connect(int api) {
LOGV("SurfaceTextureClient::connect");
Mutex::Autolock lock(mMutex);
int err = NO_ERROR;
switch (api) {
case NATIVE_WINDOW_API_EGL:
case NATIVE_WINDOW_API_CPU:
case NATIVE_WINDOW_API_MEDIA:
case NATIVE_WINDOW_API_CAMERA:
if (mConnectedApi) {
err = -EINVAL;
} else {
mConnectedApi = api;
}
break;
default:
err = -EINVAL;
break;
}
return err;
return mSurfaceTexture->connect(api);
}
int SurfaceTextureClient::disconnect(int api) {
LOGV("SurfaceTextureClient::disconnect");
Mutex::Autolock lock(mMutex);
int err = NO_ERROR;
switch (api) {
case NATIVE_WINDOW_API_EGL:
case NATIVE_WINDOW_API_CPU:
case NATIVE_WINDOW_API_MEDIA:
case NATIVE_WINDOW_API_CAMERA:
if (mConnectedApi == api) {
mConnectedApi = 0;
} else {
err = -EINVAL;
}
break;
default:
err = -EINVAL;
break;
}
return err;
return mSurfaceTexture->disconnect(api);
}
int SurfaceTextureClient::getConnectedApi() const
{
// XXX: This method will be going away shortly, and is currently bogus. It
// always returns "nothing is connected". It will go away once Surface gets
// updated to actually connect as the 'CPU' API when locking a buffer.
Mutex::Autolock lock(mMutex);
return mConnectedApi;
return 0;
}