Support SurfaceView synchronization.
Add API for fetching the next frame number to be produced by
a given buffer producer. Add an API to SurfaceComposer to
defer execution of the current transaction until a given frame number.
Together these may be used to synchronize app drawing and surface
control updates.
Change-Id: I8e0f4993332ac0199c768c88581a453fefbaff1d
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 0cb018c..9ef8ff7 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -1151,6 +1151,14 @@
return mConsumerName;
}
+uint64_t BufferQueueProducer::getNextFrameNumber() const {
+ ATRACE_CALL();
+
+ Mutex::Autolock lock(mCore->mMutex);
+ uint64_t nextFrameNumber = mCore->mFrameCounter + 1;
+ return nextFrameNumber;
+}
+
void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) {
// If we're here, it means that a producer we were connected to died.
// We're guaranteed that we are still connected to it because we remove
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index 8ab963d..640a9f2 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -49,7 +49,8 @@
SET_GENERATION_NUMBER,
GET_CONSUMER_NAME,
SET_MAX_DEQUEUED_BUFFER_COUNT,
- SET_ASYNC_MODE
+ SET_ASYNC_MODE,
+ GET_NEXT_FRAME_NUMBER
};
class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
@@ -326,6 +327,18 @@
}
return reply.readString8();
}
+
+ virtual uint64_t getNextFrameNumber() const {
+ Parcel data, reply;
+ data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
+ status_t result = remote()->transact(GET_NEXT_FRAME_NUMBER, data, &reply);
+ if (result != NO_ERROR) {
+ ALOGE("getNextFrameNumber failed to transact: %d", result);
+ return 0;
+ }
+ uint64_t frameNumber = reply.readUint64();
+ return frameNumber;
+ }
};
// Out-of-line virtual method definition to trigger vtable emission in this
@@ -508,6 +521,12 @@
reply->writeString8(getConsumerName());
return NO_ERROR;
}
+ case GET_NEXT_FRAME_NUMBER: {
+ CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
+ uint64_t frameNumber = getNextFrameNumber();
+ reply->writeUint64(frameNumber);
+ return NO_ERROR;
+ }
}
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index eafda86..06f13e8 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -38,6 +38,8 @@
*reinterpret_cast<layer_state_t::matrix22_t *>(
output.writeInplace(sizeof(layer_state_t::matrix22_t))) = matrix;
output.write(crop);
+ output.writeStrongBinder(handle);
+ output.writeUint64(frameNumber);
output.write(transparentRegion);
return NO_ERROR;
}
@@ -62,6 +64,8 @@
return BAD_VALUE;
}
input.read(crop);
+ handle = input.readStrongBinder();
+ frameNumber = input.readUint64();
input.read(transparentRegion);
return NO_ERROR;
}
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index a31876b..9191b2a 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -111,6 +111,10 @@
return result;
}
+uint64_t Surface::getNextFrameNumber() const {
+ return mGraphicBufferProducer->getNextFrameNumber();
+}
+
String8 Surface::getConsumerName() const {
return mGraphicBufferProducer->getConsumerName();
}
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 9167a0c..3242f55 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -158,6 +158,9 @@
const Rect& crop);
status_t setLayerStack(const sp<SurfaceComposerClient>& client,
const sp<IBinder>& id, uint32_t layerStack);
+ status_t deferTransactionUntil(const sp<SurfaceComposerClient>& client,
+ const sp<IBinder>& id, const sp<IBinder>& handle,
+ uint64_t frameNumber);
void setDisplaySurface(const sp<IBinder>& token,
const sp<IGraphicBufferProducer>& bufferProducer);
@@ -383,6 +386,20 @@
return NO_ERROR;
}
+status_t Composer::deferTransactionUntil(
+ const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
+ const sp<IBinder>& handle, uint64_t frameNumber) {
+ Mutex::Autolock lock(mLock);
+ layer_state_t* s = getLayerStateLocked(client, id);
+ if (!s) {
+ return BAD_INDEX;
+ }
+ s->what |= layer_state_t::eDeferTransaction;
+ s->handle = handle;
+ s->frameNumber = frameNumber;
+ return NO_ERROR;
+}
+
// ---------------------------------------------------------------------------
DisplayState& Composer::getDisplayStateLocked(const sp<IBinder>& token) {
@@ -609,6 +626,11 @@
return getComposer().setMatrix(this, id, dsdx, dtdx, dsdy, dtdy);
}
+status_t SurfaceComposerClient::deferTransactionUntil(const sp<IBinder>& id,
+ const sp<IBinder>& handle, uint64_t frameNumber) {
+ return getComposer().deferTransactionUntil(this, id, handle, frameNumber);
+}
+
// ----------------------------------------------------------------------------
void SurfaceComposerClient::setDisplaySurface(const sp<IBinder>& token,
diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp
index 1983027..a945358 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -145,6 +145,13 @@
return mClient->setCrop(mHandle, crop);
}
+status_t SurfaceControl::deferTransactionUntil(sp<IBinder> handle,
+ uint64_t frameNumber) {
+ status_t err = validate();
+ if (err < 0) return err;
+ return mClient->deferTransactionUntil(mHandle, handle, frameNumber);
+}
+
status_t SurfaceControl::clearLayerFrameStats() const {
status_t err = validate();
if (err < 0) return err;
@@ -190,5 +197,11 @@
return mSurfaceData;
}
+sp<IBinder> SurfaceControl::getHandle() const
+{
+ Mutex::Autolock lock(mLock);
+ return mHandle;
+}
+
// ----------------------------------------------------------------------------
}; // namespace android