status_t setLayerStack(const sp<IBinder>& id, uint32_t layerStack);
status_t deferTransactionUntil(const sp<IBinder>& id,
const sp<IBinder>& handle, uint64_t frameNumber);
+ status_t deferTransactionUntil(const sp<IBinder>& id,
+ const sp<Surface>& handle, uint64_t frameNumber);
status_t reparentChildren(const sp<IBinder>& id,
const sp<IBinder>& newParentHandle);
status_t setOverrideScalingMode(const sp<IBinder>& id,
status_t setGeometryAppliesWithResize();
// Defers applying any changes made in this transaction until the Layer
- // identified by handle reaches the given frameNumber
+ // identified by handle reaches the given frameNumber. If the Layer identified
+ // by handle is removed, then we will apply this transaction regardless of
+ // what frame number has been reached.
status_t deferTransactionUntil(const sp<IBinder>& handle, uint64_t frameNumber);
+
+ // A variant of deferTransactionUntil which identifies the Layer we wait for by
+ // Surface instead of Handle. Useful for clients which may not have the
+ // SurfaceControl for some of their Surfaces. Otherwise behaves identically.
+ status_t deferTransactionUntil(const sp<Surface>& barrier, uint64_t frameNumber);
+
// Reparents all children of this layer to the new parent handle.
status_t reparentChildren(const sp<IBinder>& newParentHandle);
#include <ui/Region.h>
#include <ui/Rect.h>
+#include <gui/IGraphicBufferProducer.h>
namespace android {
matrix22_t matrix;
Rect crop;
Rect finalCrop;
- sp<IBinder> handle;
+ sp<IBinder> barrierHandle;
sp<IBinder> reparentHandle;
uint64_t frameNumber;
int32_t overrideScalingMode;
+
+ sp<IGraphicBufferProducer> barrierGbp;
+
// non POD must be last. see write/read
Region transparentRegion;
};
output.writeInplace(sizeof(layer_state_t::matrix22_t))) = matrix;
output.write(crop);
output.write(finalCrop);
- output.writeStrongBinder(handle);
+ output.writeStrongBinder(barrierHandle);
output.writeStrongBinder(reparentHandle);
output.writeUint64(frameNumber);
output.writeInt32(overrideScalingMode);
+ output.writeStrongBinder(IInterface::asBinder(barrierGbp));
output.write(transparentRegion);
return NO_ERROR;
}
}
input.read(crop);
input.read(finalCrop);
- handle = input.readStrongBinder();
+ barrierHandle = input.readStrongBinder();
reparentHandle = input.readStrongBinder();
frameNumber = input.readUint64();
overrideScalingMode = input.readInt32();
+ barrierGbp =
+ interface_cast<IGraphicBufferProducer>(input.readStrongBinder());
input.read(transparentRegion);
return NO_ERROR;
}
#include <gui/IGraphicBufferProducer.h>
#include <gui/ISurfaceComposer.h>
#include <gui/ISurfaceComposerClient.h>
+#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
#include <private/gui/ComposerService.h>
status_t deferTransactionUntil(const sp<SurfaceComposerClient>& client,
const sp<IBinder>& id, const sp<IBinder>& handle,
uint64_t frameNumber);
+ status_t deferTransactionUntil(const sp<SurfaceComposerClient>& client,
+ const sp<IBinder>& id, const sp<Surface>& barrierSurface,
+ uint64_t frameNumber);
status_t reparentChildren(const sp<SurfaceComposerClient>& client,
const sp<IBinder>& id,
const sp<IBinder>& newParentHandle);
return BAD_INDEX;
}
s->what |= layer_state_t::eDeferTransaction;
- s->handle = handle;
+ s->barrierHandle = handle;
+ s->frameNumber = frameNumber;
+ return NO_ERROR;
+}
+
+status_t Composer::deferTransactionUntil(
+ const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
+ const sp<Surface>& barrierSurface, 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->barrierGbp = barrierSurface->getIGraphicBufferProducer();
s->frameNumber = frameNumber;
return NO_ERROR;
}
return getComposer().deferTransactionUntil(this, id, handle, frameNumber);
}
+status_t SurfaceComposerClient::deferTransactionUntil(const sp<IBinder>& id,
+ const sp<Surface>& barrierSurface, uint64_t frameNumber) {
+ return getComposer().deferTransactionUntil(this, id, barrierSurface, frameNumber);
+}
+
status_t SurfaceComposerClient::reparentChildren(const sp<IBinder>& id,
const sp<IBinder>& newParentHandle) {
return getComposer().reparentChildren(this, id, newParentHandle);
return mClient->deferTransactionUntil(mHandle, handle, frameNumber);
}
+status_t SurfaceControl::deferTransactionUntil(const sp<Surface>& handle,
+ uint64_t frameNumber) {
+ status_t err = validate();
+ if (err < 0) return err;
+ return mClient->deferTransactionUntil(mHandle, handle, frameNumber);
+}
+
status_t SurfaceControl::reparentChildren(const sp<IBinder>& newParentHandle) {
status_t err = validate();
if (err < 0) return err;
// If this transaction is waiting on the receipt of a frame, generate a sync
// point and send it to the remote layer.
- if (mCurrentState.handle != nullptr) {
- sp<IBinder> strongBinder = mCurrentState.handle.promote();
- sp<Handle> handle = nullptr;
- sp<Layer> handleLayer = nullptr;
- if (strongBinder != nullptr) {
- handle = static_cast<Handle*>(strongBinder.get());
- handleLayer = handle->owner.promote();
- }
- if (strongBinder == nullptr || handleLayer == nullptr) {
- ALOGE("[%s] Unable to promote Layer handle", mName.string());
+ if (mCurrentState.barrierLayer != nullptr) {
+ sp<Layer> barrierLayer = mCurrentState.barrierLayer.promote();
+ if (barrierLayer == nullptr) {
+ ALOGE("[%s] Unable to promote barrier Layer.", mName.string());
// If we can't promote the layer we are intended to wait on,
// then it is expired or otherwise invalid. Allow this transaction
// to be applied as per normal (no synchronization).
- mCurrentState.handle = nullptr;
+ mCurrentState.barrierLayer = nullptr;
} else {
auto syncPoint = std::make_shared<SyncPoint>(
mCurrentState.frameNumber);
- if (handleLayer->addSyncPoint(syncPoint)) {
+ if (barrierLayer->addSyncPoint(syncPoint)) {
mRemoteSyncPoints.push_back(std::move(syncPoint));
} else {
// We already missed the frame we're supposed to synchronize
// on, so go ahead and apply the state update
- mCurrentState.handle = nullptr;
+ mCurrentState.barrierLayer = nullptr;
}
}
bool Layer::applyPendingStates(State* stateToCommit) {
bool stateUpdateAvailable = false;
while (!mPendingStates.empty()) {
- if (mPendingStates[0].handle != nullptr) {
+ if (mPendingStates[0].barrierLayer != nullptr) {
if (mRemoteSyncPoints.empty()) {
// If we don't have a sync point for this, apply it anyway. It
// will be visually wrong, but it should keep us from getting
return p->getLayerStack();
}
-void Layer::deferTransactionUntil(const sp<IBinder>& handle,
+void Layer::deferTransactionUntil(const sp<Layer>& barrierLayer,
uint64_t frameNumber) {
- mCurrentState.handle = handle;
+ mCurrentState.barrierLayer = barrierLayer;
mCurrentState.frameNumber = frameNumber;
// We don't set eTransactionNeeded, because just receiving a deferral
// request without any other state updates shouldn't actually induce a delay
mCurrentState.modified = true;
pushPendingState();
- mCurrentState.handle = nullptr;
+ mCurrentState.barrierLayer = nullptr;
mCurrentState.frameNumber = 0;
mCurrentState.modified = false;
+ ALOGE("Deferred transaction");
+}
+
+void Layer::deferTransactionUntil(const sp<IBinder>& barrierHandle,
+ uint64_t frameNumber) {
+ sp<Handle> handle = static_cast<Handle*>(barrierHandle.get());
+ deferTransactionUntil(handle->owner.promote(), frameNumber);
}
void Layer::useSurfaceDamage() {
// finalCrop is expressed in display space coordinate.
Rect finalCrop;
- // If set, defers this state update until the Layer identified by handle
+ // If set, defers this state update until the identified Layer
// receives a frame with the given frameNumber
- wp<IBinder> handle;
+ wp<Layer> barrierLayer;
uint64_t frameNumber;
// the transparentRegion hint is a bit special, it's latched only
bool setLayerStack(uint32_t layerStack);
bool setDataSpace(android_dataspace dataSpace);
uint32_t getLayerStack() const;
- void deferTransactionUntil(const sp<IBinder>& handle, uint64_t frameNumber);
+ void deferTransactionUntil(const sp<IBinder>& barrierHandle, uint64_t frameNumber);
+ void deferTransactionUntil(const sp<Layer>& barrierLayer, uint64_t frameNumber);
bool setOverrideScalingMode(int32_t overrideScalingMode);
void setInfo(uint32_t type, uint32_t appId);
bool reparentChildren(const sp<IBinder>& layer);
mLastTransactionTime(0),
mBootFinished(false),
mForceFullDamage(false),
- mInterceptor(),
+ mInterceptor(this),
mPrimaryDispSync("PrimaryDispSync"),
mPrimaryHWVsyncEnabled(false),
mHWVsyncAvailable(false),
bool SurfaceFlinger::authenticateSurfaceTexture(
const sp<IGraphicBufferProducer>& bufferProducer) const {
Mutex::Autolock _l(mStateLock);
+ return authenticateSurfaceTextureLocked(bufferProducer);
+}
+
+bool SurfaceFlinger::authenticateSurfaceTextureLocked(
+ const sp<IGraphicBufferProducer>& bufferProducer) const {
sp<IBinder> surfaceTextureBinder(IInterface::asBinder(bufferProducer));
return mGraphicBufferProducerList.indexOf(surfaceTextureBinder) >= 0;
}
}
}
if (what & layer_state_t::eDeferTransaction) {
- layer->deferTransactionUntil(s.handle, s.frameNumber);
+ if (s.barrierHandle != nullptr) {
+ layer->deferTransactionUntil(s.barrierHandle, s.frameNumber);
+ } else if (s.barrierGbp != nullptr) {
+ const sp<IGraphicBufferProducer>& gbp = s.barrierGbp;
+ if (authenticateSurfaceTextureLocked(gbp)) {
+ const auto& otherLayer =
+ (static_cast<MonitoredProducer*>(gbp.get()))->getLayer();
+ layer->deferTransactionUntil(otherLayer, s.frameNumber);
+ } else {
+ ALOGE("Attempt to defer transaction to to an"
+ " unrecognized GraphicBufferProducer");
+ }
+ }
// We don't trigger a traversal here because if no other state is
// changed, we don't want this to cause any more work
}
return *mRenderEngine;
}
+ bool authenticateSurfaceTextureLocked(
+ const sp<IGraphicBufferProducer>& bufferProducer) const;
+
private:
friend class Client;
friend class DisplayEventConnection;
mLastTransactionTime(0),
mBootFinished(false),
mForceFullDamage(false),
- mInterceptor(),
+ mInterceptor(this),
mPrimaryDispSync("PrimaryDispSync"),
mPrimaryHWVsyncEnabled(false),
mHWVsyncAvailable(false),
bool SurfaceFlinger::authenticateSurfaceTexture(
const sp<IGraphicBufferProducer>& bufferProducer) const {
Mutex::Autolock _l(mStateLock);
+ return authenticateSurfaceTextureLocked(bufferProducer);
+}
+
+bool SurfaceFlinger::authenticateSurfaceTextureLocked(
+ const sp<IGraphicBufferProducer>& bufferProducer) const {
sp<IBinder> surfaceTextureBinder(IInterface::asBinder(bufferProducer));
return mGraphicBufferProducerList.indexOf(surfaceTextureBinder) >= 0;
}
}
}
if (what & layer_state_t::eDeferTransaction) {
- layer->deferTransactionUntil(s.handle, s.frameNumber);
+ if (s.barrierHandle != nullptr) {
+ layer->deferTransactionUntil(s.barrierHandle, s.frameNumber);
+ } else if (s.barrierGbp != nullptr) {
+ const sp<IGraphicBufferProducer>& gbp = s.barrierGbp;
+ if (authenticateSurfaceTextureLocked(gbp)) {
+ const auto& otherLayer =
+ (static_cast<MonitoredProducer*>(gbp.get()))->getLayer();
+ layer->deferTransactionUntil(otherLayer, s.frameNumber);
+ } else {
+ ALOGE("Attempt to defer transaction to to an"
+ " unrecognized GraphicBufferProducer");
+ }
+ }
// We don't trigger a traversal here because if no other state is
// changed, we don't want this to cause any more work
}
// ----------------------------------------------------------------------------
+SurfaceInterceptor::SurfaceInterceptor(SurfaceFlinger* flinger)
+ : mFlinger(flinger)
+{
+}
+
void SurfaceInterceptor::enable(const SortedVector<sp<Layer>>& layers,
const DefaultKeyedVector< wp<IBinder>, DisplayDeviceState>& displays)
{
addTransparentRegionLocked(transaction, layerId, layer->mCurrentState.activeTransparentRegion);
addLayerStackLocked(transaction, layerId, layer->mCurrentState.layerStack);
addCropLocked(transaction, layerId, layer->mCurrentState.crop);
- if (layer->mCurrentState.handle != nullptr) {
- addDeferTransactionLocked(transaction, layerId, layer->mCurrentState.handle,
+ if (layer->mCurrentState.barrierLayer != nullptr) {
+ addDeferTransactionLocked(transaction, layerId, layer->mCurrentState.barrierLayer.promote(),
layer->mCurrentState.frameNumber);
}
addFinalCropLocked(transaction, layerId, layer->mCurrentState.finalCrop);
}
void SurfaceInterceptor::addDeferTransactionLocked(Transaction* transaction, int32_t layerId,
- const wp<const IBinder>& weakHandle, uint64_t frameNumber)
+ const sp<const Layer>& layer, uint64_t frameNumber)
{
SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
- const sp<const Layer> layer(getLayer(weakHandle));
if (layer == nullptr) {
ALOGE("An existing layer could not be retrieved with the handle"
" for the deferred transaction");
addCropLocked(transaction, layerId, state.crop);
}
if (state.what & layer_state_t::eDeferTransaction) {
- addDeferTransactionLocked(transaction, layerId, state.handle, state.frameNumber);
+ sp<Layer> otherLayer = nullptr;
+ if (state.barrierHandle != nullptr) {
+ otherLayer = static_cast<Layer::Handle*>(state.barrierHandle.get())->owner.promote();
+ } else if (state.barrierGbp != nullptr) {
+ auto const& gbp = state.barrierGbp;
+ if (mFlinger->authenticateSurfaceTextureLocked(gbp)) {
+ otherLayer = (static_cast<MonitoredProducer*>(gbp.get()))->getLayer();
+ } else {
+ ALOGE("Attempt to defer transaction to to an unrecognized GraphicBufferProducer");
+ }
+ }
+ addDeferTransactionLocked(transaction, layerId, otherLayer, state.frameNumber);
}
if (state.what & layer_state_t::eFinalCropChanged) {
addFinalCropLocked(transaction, layerId, state.finalCrop);
class BufferItem;
class Layer;
+class SurfaceFlinger;
struct DisplayState;
struct layer_state_t;
*/
class SurfaceInterceptor {
public:
+ SurfaceInterceptor(SurfaceFlinger* const flinger);
// Both vectors are used to capture the current state of SF as the initial snapshot in the trace
void enable(const SortedVector<sp<Layer>>& layers,
const DefaultKeyedVector< wp<IBinder>, DisplayDeviceState>& displays);
void addLayerStackLocked(Transaction* transaction, int32_t layerId, uint32_t layerStack);
void addCropLocked(Transaction* transaction, int32_t layerId, const Rect& rect);
void addDeferTransactionLocked(Transaction* transaction, int32_t layerId,
- const wp<const IBinder>& weakHandle, uint64_t frameNumber);
+ const sp<const Layer>& layer, uint64_t frameNumber);
void addFinalCropLocked(Transaction* transaction, int32_t layerId, const Rect& rect);
void addOverrideScalingModeLocked(Transaction* transaction, int32_t layerId,
int32_t overrideScalingMode);
std::string mOutputFileName {DEFAULT_FILENAME};
std::mutex mTraceMutex {};
Trace mTrace {};
+ SurfaceFlinger* const mFlinger;
};
}