Merge "BufferQueue: add a setMaxAcquiredBufferCount check" into jb-mr1-dev
diff --git a/include/android/configuration.h b/include/android/configuration.h
index 06cd3da..0f5c14a 100644
--- a/include/android/configuration.h
+++ b/include/android/configuration.h
@@ -93,6 +93,10 @@
ACONFIGURATION_SMALLEST_SCREEN_WIDTH_DP_ANY = 0x0000,
+ ACONFIGURATION_LAYOUTDIR_ANY = 0x00,
+ ACONFIGURATION_LAYOUTDIR_LTR = 0x01,
+ ACONFIGURATION_LAYOUTDIR_RTL = 0x02,
+
ACONFIGURATION_MCC = 0x0001,
ACONFIGURATION_MNC = 0x0002,
ACONFIGURATION_LOCALE = 0x0004,
@@ -107,6 +111,7 @@
ACONFIGURATION_SCREEN_LAYOUT = 0x0800,
ACONFIGURATION_UI_MODE = 0x1000,
ACONFIGURATION_SMALLEST_SCREEN_SIZE = 0x2000,
+ ACONFIGURATION_LAYOUTDIR = 0x4000,
};
/**
@@ -331,6 +336,17 @@
void AConfiguration_setSmallestScreenWidthDp(AConfiguration* config, int32_t value);
/**
+ * Return the configuration's layout direction, or
+ * ACONFIGURATION_LAYOUTDIR_ANY if not set.
+ */
+int32_t AConfiguration_getLayoutDirection(AConfiguration* config);
+
+/**
+ * Set the configuration's layout direction.
+ */
+void AConfiguration_setLayoutDirection(AConfiguration* config, int32_t value);
+
+/**
* Perform a diff between two configurations. Returns a bit mask of
* ACONFIGURATION_* constants, each bit set meaning that configuration element
* is different between them.
diff --git a/include/binder/IPCThreadState.h b/include/binder/IPCThreadState.h
index 691ba2f..3378d97 100644
--- a/include/binder/IPCThreadState.h
+++ b/include/binder/IPCThreadState.h
@@ -41,7 +41,6 @@
int getCallingPid();
int getCallingUid();
- int getOrigCallingUid();
void setStrictModePolicy(int32_t policy);
int32_t getStrictModePolicy() const;
@@ -117,7 +116,6 @@
status_t mLastError;
pid_t mCallingPid;
uid_t mCallingUid;
- uid_t mOrigCallingUid;
int32_t mStrictModePolicy;
int32_t mLastTransactionBinderFlags;
};
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
index 877b17c..3ff95d2 100644
--- a/include/binder/Parcel.h
+++ b/include/binder/Parcel.h
@@ -285,9 +285,12 @@
return err;
}
}
- void* buffer = writeInplace(size);
- return buffer == NULL ? NO_MEMORY :
- val.flatten(buffer);
+ if (size) {
+ void* buffer = writeInplace(size);
+ return buffer == NULL ? NO_MEMORY :
+ val.flatten(buffer);
+ }
+ return NO_ERROR;
}
template<typename T>
@@ -303,9 +306,12 @@
}
size = s;
}
- void const* buffer = readInplace(size);
- return buffer == NULL ? NO_MEMORY :
- val.unflatten(buffer, size);
+ if (size) {
+ void const* buffer = readInplace(size);
+ return buffer == NULL ? NO_MEMORY :
+ val.unflatten(buffer, size);
+ }
+ return NO_ERROR;
}
// ---------------------------------------------------------------------------
diff --git a/include/ui/Region.h b/include/ui/Region.h
index f0819af..0049fde 100644
--- a/include/ui/Region.h
+++ b/include/ui/Region.h
@@ -28,6 +28,7 @@
namespace android {
// ---------------------------------------------------------------------------
+class SharedBuffer;
class String8;
// ---------------------------------------------------------------------------
@@ -41,10 +42,10 @@
Region& operator = (const Region& rhs);
- inline bool isEmpty() const { return mBounds.isEmpty(); }
- inline bool isRect() const { return mStorage.isEmpty(); }
+ inline bool isEmpty() const { return getBounds().isEmpty(); }
+ inline bool isRect() const { return mStorage.size() == 1; }
- inline Rect getBounds() const { return mBounds; }
+ inline Rect getBounds() const { return mStorage[mStorage.size() - 1]; }
inline Rect bounds() const { return getBounds(); }
// the region becomes its bounds
@@ -106,18 +107,24 @@
/* various ways to access the rectangle list */
+
+ // STL-like iterators
typedef Rect const* const_iterator;
-
- const_iterator begin() const;
- const_iterator end() const;
+ const_iterator begin() const;
+ const_iterator end() const;
+
+ // returns an array of rect which has the same life-time has this
+ // Region object.
+ Rect const* getArray(size_t* count) const;
+
+ // returns a SharedBuffer as well as the number of rects.
+ // ownership is transfered to the caller.
+ // the caller must call SharedBuffer::release() to free the memory.
+ SharedBuffer const* getSharedBuffer(size_t* count) const;
/* no user serviceable parts here... */
- size_t getRects(Vector<Rect>& rectList) const;
- Rect const* getArray(size_t* count) const;
-
-
// add a rectangle to the internal list. This rectangle must
// be sorted in Y and X and must not make the region invalid.
void addRectUnchecked(int l, int t, int r, int b);
@@ -156,8 +163,11 @@
static bool validate(const Region& reg, const char* name);
- Rect mBounds;
- Vector<Rect> mStorage;
+ // mStorage is a (manually) sorted array of Rects describing the region
+ // with an extra Rect as the last element which is set to the
+ // bounds of the region. However, if the region is
+ // a simple Rect then mStorage contains only that rect.
+ Vector<Rect> mStorage;
};
diff --git a/include/utils/SharedBuffer.h b/include/utils/SharedBuffer.h
index 24508b0..b670953 100644
--- a/include/utils/SharedBuffer.h
+++ b/include/utils/SharedBuffer.h
@@ -44,9 +44,6 @@
* users.
*/
static ssize_t dealloc(const SharedBuffer* released);
-
- //! get the SharedBuffer from the data pointer
- static inline const SharedBuffer* sharedBuffer(const void* data);
//! access the data for read
inline const void* data() const;
@@ -94,9 +91,10 @@
private:
inline SharedBuffer() { }
inline ~SharedBuffer() { }
- inline SharedBuffer(const SharedBuffer&);
+ SharedBuffer(const SharedBuffer&);
+ SharedBuffer& operator = (const SharedBuffer&);
- // 16 bytes. must be sized to preserve correct alingment.
+ // 16 bytes. must be sized to preserve correct alignment.
mutable int32_t mRefs;
size_t mSize;
uint32_t mReserved[2];
@@ -104,10 +102,6 @@
// ---------------------------------------------------------------------------
-const SharedBuffer* SharedBuffer::sharedBuffer(const void* data) {
- return data ? reinterpret_cast<const SharedBuffer *>(data)-1 : 0;
-}
-
const void* SharedBuffer::data() const {
return this + 1;
}
@@ -120,19 +114,16 @@
return mSize;
}
-SharedBuffer* SharedBuffer::bufferFromData(void* data)
-{
- return ((SharedBuffer*)data)-1;
+SharedBuffer* SharedBuffer::bufferFromData(void* data) {
+ return data ? static_cast<SharedBuffer *>(data)-1 : 0;
}
-const SharedBuffer* SharedBuffer::bufferFromData(const void* data)
-{
- return ((const SharedBuffer*)data)-1;
+const SharedBuffer* SharedBuffer::bufferFromData(const void* data) {
+ return data ? static_cast<const SharedBuffer *>(data)-1 : 0;
}
-size_t SharedBuffer::sizeFromData(const void* data)
-{
- return (((const SharedBuffer*)data)-1)->mSize;
+size_t SharedBuffer::sizeFromData(const void* data) {
+ return data ? bufferFromData(data)->mSize : 0;
}
bool SharedBuffer::onlyOwner() const {
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 7e416b9..6e83faa 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -371,11 +371,6 @@
return mCallingUid;
}
-int IPCThreadState::getOrigCallingUid()
-{
- return mOrigCallingUid;
-}
-
int64_t IPCThreadState::clearCallingIdentity()
{
int64_t token = ((int64_t)mCallingUid<<32) | mCallingPid;
@@ -646,7 +641,6 @@
{
pthread_setspecific(gTLS, this);
clearCaller();
- mOrigCallingUid = mCallingUid;
mIn.setDataCapacity(256);
mOut.setDataCapacity(256);
}
@@ -998,7 +992,6 @@
mCallingPid = tr.sender_pid;
mCallingUid = tr.sender_euid;
- mOrigCallingUid = tr.sender_euid;
int curPrio = getpriority(PRIO_PROCESS, mMyThreadId);
if (gDisableBackgroundScheduling) {
@@ -1056,7 +1049,6 @@
mCallingPid = origPid;
mCallingUid = origUid;
- mOrigCallingUid = origUid;
IF_LOG_TRANSACTIONS() {
TextOutput::Bundle _b(alog);
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index a3d8b01..94fb1d5 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -48,22 +48,20 @@
// ----------------------------------------------------------------------------
-Region::Region()
- : mBounds(0,0)
-{
+Region::Region() {
+ mStorage.add(Rect(0,0));
}
Region::Region(const Region& rhs)
- : mBounds(rhs.mBounds), mStorage(rhs.mStorage)
+ : mStorage(rhs.mStorage)
{
#if VALIDATE_REGIONS
validate(rhs, "rhs copy-ctor");
#endif
}
-Region::Region(const Rect& rhs)
- : mBounds(rhs)
-{
+Region::Region(const Rect& rhs) {
+ mStorage.add(rhs);
}
Region::~Region()
@@ -76,40 +74,46 @@
validate(*this, "this->operator=");
validate(rhs, "rhs.operator=");
#endif
- mBounds = rhs.mBounds;
mStorage = rhs.mStorage;
return *this;
}
Region& Region::makeBoundsSelf()
{
- mStorage.clear();
+ if (mStorage.size() >= 2) {
+ const Rect bounds(getBounds());
+ mStorage.clear();
+ mStorage.add(bounds);
+ }
return *this;
}
void Region::clear()
{
- mBounds.clear();
mStorage.clear();
+ mStorage.add(Rect(0,0));
}
void Region::set(const Rect& r)
{
- mBounds = r;
mStorage.clear();
+ mStorage.add(r);
}
void Region::set(uint32_t w, uint32_t h)
{
- mBounds = Rect(int(w), int(h));
mStorage.clear();
+ mStorage.add(Rect(w,h));
}
// ----------------------------------------------------------------------------
void Region::addRectUnchecked(int l, int t, int r, int b)
{
- mStorage.add(Rect(l,t,r,b));
+ Rect rect(l,t,r,b);
+ size_t where = mStorage.size() - 1;
+ mStorage.insertAt(rect, where, 1);
+
#if VALIDATE_REGIONS
validate(*this, "addRectUnchecked");
#endif
@@ -252,7 +256,7 @@
// to obtain an optimal region.
class Region::rasterizer : public region_operator<Rect>::region_rasterizer
{
- Rect& bounds;
+ Rect bounds;
Vector<Rect>& storage;
Rect* head;
Rect* tail;
@@ -260,10 +264,7 @@
Rect* cur;
public:
rasterizer(Region& reg)
- : bounds(reg.mBounds), storage(reg.mStorage), head(), tail(), cur() {
- bounds.top = bounds.bottom = 0;
- bounds.left = INT_MAX;
- bounds.right = INT_MIN;
+ : bounds(INT_MAX, 0, INT_MIN, 0), storage(reg.mStorage), head(), tail(), cur() {
storage.clear();
}
@@ -281,6 +282,7 @@
bounds.left = 0;
bounds.right = 0;
}
+ storage.add(bounds);
}
virtual void operator()(const Rect& rect) {
@@ -372,6 +374,9 @@
reg.getBounds().left, reg.getBounds().top,
reg.getBounds().right, reg.getBounds().bottom);
}
+ if (reg.mStorage.size() == 2) {
+ ALOGE("mStorage size is 2, which is never valid");
+ }
if (result == false) {
reg.dump(name);
}
@@ -529,11 +534,10 @@
void Region::translate(Region& reg, int dx, int dy)
{
- if (!reg.isEmpty()) {
+ if ((dx || dy) && !reg.isEmpty()) {
#if VALIDATE_REGIONS
validate(reg, "translate (before)");
#endif
- reg.mBounds.translate(dx, dy);
size_t count = reg.mStorage.size();
Rect* rects = reg.mStorage.editArray();
while (count) {
@@ -556,12 +560,11 @@
// ----------------------------------------------------------------------------
size_t Region::getSize() const {
- return (mStorage.size() + 1) * sizeof(Rect);
+ return mStorage.size() * sizeof(Rect);
}
status_t Region::flatten(void* buffer) const {
Rect* rects = reinterpret_cast<Rect*>(buffer);
- *rects++ = mBounds;
memcpy(rects, mStorage.array(), mStorage.size() * sizeof(Rect));
return NO_ERROR;
}
@@ -570,8 +573,6 @@
mStorage.clear();
if (size >= sizeof(Rect)) {
Rect const* rects = reinterpret_cast<Rect const*>(buffer);
- mBounds = *rects++;
- size -= sizeof(Rect);
size_t count = size / sizeof(Rect);
if (count > 0) {
ssize_t err = mStorage.insertAt(0, count);
@@ -581,25 +582,21 @@
memcpy(mStorage.editArray(), rects, count*sizeof(Rect));
}
}
+#if VALIDATE_REGIONS
+ validate(*this, "Region::unflatten");
+#endif
return NO_ERROR;
}
// ----------------------------------------------------------------------------
Region::const_iterator Region::begin() const {
- return isRect() ? &mBounds : mStorage.array();
+ return mStorage.array();
}
Region::const_iterator Region::end() const {
- if (isRect()) {
- if (isEmpty()) {
- return &mBounds;
- } else {
- return &mBounds + 1;
- }
- } else {
- return mStorage.array() + mStorage.size();
- }
+ size_t numRects = isRect() ? 1 : mStorage.size() - 1;
+ return mStorage.array() + numRects;
}
Rect const* Region::getArray(size_t* count) const {
@@ -609,14 +606,16 @@
return b;
}
-size_t Region::getRects(Vector<Rect>& rectList) const
-{
- rectList = mStorage;
- if (rectList.isEmpty()) {
- rectList.clear();
- rectList.add(mBounds);
+SharedBuffer const* Region::getSharedBuffer(size_t* count) const {
+ // We can get to the SharedBuffer of a Vector<Rect> because Rect has
+ // a trivial destructor.
+ SharedBuffer const* sb = SharedBuffer::bufferFromData(mStorage.array());
+ if (count) {
+ size_t numRects = isRect() ? 1 : mStorage.size() - 1;
+ count[0] = numRects;
}
- return rectList.size();
+ sb->acquire();
+ return sb;
}
// ----------------------------------------------------------------------------
diff --git a/libs/utils/VectorImpl.cpp b/libs/utils/VectorImpl.cpp
index 020ec15..8083bba 100644
--- a/libs/utils/VectorImpl.cpp
+++ b/libs/utils/VectorImpl.cpp
@@ -51,7 +51,7 @@
mFlags(rhs.mFlags), mItemSize(rhs.mItemSize)
{
if (mStorage) {
- SharedBuffer::sharedBuffer(mStorage)->acquire();
+ SharedBuffer::bufferFromData(mStorage)->acquire();
}
}
@@ -73,7 +73,7 @@
if (rhs.mCount) {
mStorage = rhs.mStorage;
mCount = rhs.mCount;
- SharedBuffer::sharedBuffer(mStorage)->acquire();
+ SharedBuffer::bufferFromData(mStorage)->acquire();
} else {
mStorage = 0;
mCount = 0;
@@ -85,7 +85,7 @@
void* VectorImpl::editArrayImpl()
{
if (mStorage) {
- SharedBuffer* sb = SharedBuffer::sharedBuffer(mStorage)->attemptEdit();
+ SharedBuffer* sb = SharedBuffer::bufferFromData(mStorage)->attemptEdit();
if (sb == 0) {
sb = SharedBuffer::alloc(capacity() * mItemSize);
if (sb) {
@@ -101,7 +101,7 @@
size_t VectorImpl::capacity() const
{
if (mStorage) {
- return SharedBuffer::sharedBuffer(mStorage)->size() / mItemSize;
+ return SharedBuffer::bufferFromData(mStorage)->size() / mItemSize;
}
return 0;
}
@@ -346,7 +346,7 @@
void VectorImpl::release_storage()
{
if (mStorage) {
- const SharedBuffer* sb = SharedBuffer::sharedBuffer(mStorage);
+ const SharedBuffer* sb = SharedBuffer::bufferFromData(mStorage);
if (sb->release(SharedBuffer::eKeepStorage) == 1) {
_do_destroy(mStorage, mCount);
SharedBuffer::dealloc(sb);
@@ -372,7 +372,7 @@
(mFlags & HAS_TRIVIAL_COPY) &&
(mFlags & HAS_TRIVIAL_DTOR))
{
- const SharedBuffer* cur_sb = SharedBuffer::sharedBuffer(mStorage);
+ const SharedBuffer* cur_sb = SharedBuffer::bufferFromData(mStorage);
SharedBuffer* sb = cur_sb->editResize(new_capacity * mItemSize);
mStorage = sb->data();
} else {
@@ -424,7 +424,7 @@
(mFlags & HAS_TRIVIAL_COPY) &&
(mFlags & HAS_TRIVIAL_DTOR))
{
- const SharedBuffer* cur_sb = SharedBuffer::sharedBuffer(mStorage);
+ const SharedBuffer* cur_sb = SharedBuffer::bufferFromData(mStorage);
SharedBuffer* sb = cur_sb->editResize(new_capacity * mItemSize);
mStorage = sb->data();
} else {
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index dd0dc16..07002cc 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -52,3 +52,19 @@
LOCAL_MODULE:= libsurfaceflinger
include $(BUILD_SHARED_LIBRARY)
+
+###############################################################
+# uses jni which may not be available in PDK
+ifneq ($(wildcard libnativehelper/include),)
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES:= \
+ DdmConnection.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+ libdl
+
+LOCAL_MODULE:= libsurfaceflinger_ddmconnection
+
+include $(BUILD_SHARED_LIBRARY)
+endif # libnativehelper
diff --git a/services/surfaceflinger/DdmConnection.cpp b/services/surfaceflinger/DdmConnection.cpp
index 433b38e..ece965c 100644
--- a/services/surfaceflinger/DdmConnection.cpp
+++ b/services/surfaceflinger/DdmConnection.cpp
@@ -23,6 +23,10 @@
namespace android {
+void DdmConnection_start(const char* name) {
+ ALOGI("DdmConnection_start");
+ DdmConnection::start(name);
+}
void DdmConnection::start(const char* name) {
JavaVM* vm;
diff --git a/services/surfaceflinger/DdmConnection.h b/services/surfaceflinger/DdmConnection.h
index 91b737c..b6b088b 100644
--- a/services/surfaceflinger/DdmConnection.h
+++ b/services/surfaceflinger/DdmConnection.h
@@ -19,6 +19,9 @@
namespace android {
+// wrapper for dlsym
+extern "C" void DdmConnection_start(const char* name);
+
class DdmConnection {
public:
static void start(const char* name);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 283d149..23290e3 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -573,9 +573,12 @@
reinterpret_cast<Rect&>(getLayer()->sourceCrop) = crop;
}
virtual void setVisibleRegionScreen(const Region& reg) {
- getLayer()->visibleRegionScreen.rects =
- reinterpret_cast<hwc_rect_t const *>(
- reg.getArray(&getLayer()->visibleRegionScreen.numRects));
+ // Region::getSharedBuffer creates a reference to the underlying
+ // SharedBuffer of this Region, this reference is freed
+ // in onDisplayed()
+ hwc_region_t& visibleRegion = getLayer()->visibleRegionScreen;
+ SharedBuffer const* sb = reg.getSharedBuffer(&visibleRegion.numRects);
+ visibleRegion.rects = reinterpret_cast<hwc_rect_t const *>(sb->data());
}
virtual void setBuffer(const sp<GraphicBuffer>& buffer) {
if (buffer == 0 || buffer->handle == 0) {
@@ -586,6 +589,16 @@
getLayer()->handle = buffer->handle;
}
}
+ virtual void onDisplayed() {
+ hwc_region_t& visibleRegion = getLayer()->visibleRegionScreen;
+ SharedBuffer const* sb = SharedBuffer::bufferFromData(visibleRegion.rects);
+ if (sb) {
+ sb->release();
+ // not technically needed but safer
+ visibleRegion.numRects = 0;
+ visibleRegion.rects = NULL;
+ }
+ }
};
/*
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 8852ab6..a49a023 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -130,6 +130,7 @@
virtual void setVisibleRegionScreen(const Region& reg) = 0;
virtual void setBuffer(const sp<GraphicBuffer>& buffer) = 0;
virtual void setAcquireFenceFd(int fenceFd) = 0;
+ virtual void onDisplayed() = 0;
};
/*
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index dcda67e..ade9f75 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -140,6 +140,8 @@
return true;
}
+// This will return when (1) a vsync event has been received, and (2) there was
+// at least one connection interested in receiving it when we started waiting.
Vector< sp<EventThread::Connection> > EventThread::waitForEvent(
DisplayEventReceiver::Event* event)
{
@@ -193,31 +195,54 @@
// don't report it, and disable VSYNC events
disableVSyncLocked();
} else if (!timestamp && waitForVSync) {
+ // we have at least one client, so we want vsync enabled
+ // (TODO: this function is called right after we finish
+ // notifying clients of a vsync, so this call will be made
+ // at the vsync rate, e.g. 60fps. If we can accurately
+ // track the current state we could avoid making this call
+ // so often.)
enableVSyncLocked();
}
- // note: !timestamp implies signalConnections.isEmpty()
+ // note: !timestamp implies signalConnections.isEmpty(), because we
+ // don't populate signalConnections if there's no vsync pending
if (!timestamp) {
// wait for something to happen
- if (CC_UNLIKELY(mUseSoftwareVSync && waitForVSync)) {
- // h/w vsync cannot be used (screen is off), so we use
- // a timeout instead. it doesn't matter how imprecise this
- // is, we just need to make sure to serve the clients
- if (mCondition.waitRelative(mLock, ms2ns(16)) == TIMED_OUT) {
+ if (waitForVSync) {
+ // This is where we spend most of our time, waiting
+ // for vsync events and new client registrations.
+ //
+ // If the screen is off, we can't use h/w vsync, so we
+ // use a 16ms timeout instead. It doesn't need to be
+ // precise, we just need to keep feeding our clients.
+ //
+ // We don't want to stall if there's a driver bug, so we
+ // use a (long) timeout when waiting for h/w vsync, and
+ // generate fake events when necessary.
+ bool softwareSync = mUseSoftwareVSync;
+ nsecs_t timeout = softwareSync ? ms2ns(16) : ms2ns(1000);
+ if (mCondition.waitRelative(mLock, timeout) == TIMED_OUT) {
+ if (!softwareSync) {
+ ALOGW("Timed out waiting for hw vsync; faking it");
+ }
mVSyncTimestamp = systemTime(SYSTEM_TIME_MONOTONIC);
mVSyncCount++;
}
} else {
- // This is where we spend most of our time, waiting
- // for a vsync events and registered clients
+ // Nobody is interested in vsync, so we just want to sleep.
+ // h/w vsync should be disabled, so this will wait until we
+ // get a new connection, or an existing connection becomes
+ // interested in receiving vsync again.
mCondition.wait(mLock);
}
}
} while (signalConnections.isEmpty());
// here we're guaranteed to have a timestamp and some connections to signal
+ // (The connections might have dropped out of mDisplayEventConnections
+ // while we were asleep, but we'll still have strong references to them.)
- // dispatch vsync events to listeners...
+ // fill in vsync event info
event->header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
event->header.timestamp = timestamp;
event->vsync.count = vsyncCount;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index ea1bc54..f928805 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -72,6 +72,7 @@
void Layer::onLayerDisplayed(const sp<const DisplayDevice>& hw,
HWComposer::HWCLayerInterface* layer) {
+ LayerBaseClient::onLayerDisplayed(hw, layer);
if (layer) {
mSurfaceTexture->setReleaseFence(layer->getAndResetReleaseFenceFd());
}
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index a2513a2..87dc572 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -288,12 +288,16 @@
// scaling is already applied in transformedBounds
layer.setFrame(transformedBounds);
layer.setCrop(transformedBounds.getBounds());
- layer.setVisibleRegionScreen(tr.transform(visibleRegion));
}
void LayerBase::setPerFrameData(const sp<const DisplayDevice>& hw,
HWComposer::HWCLayerInterface& layer) {
layer.setBuffer(0);
+ // we have to set the visible region on every frame because
+ // we currently free it during onLayerDisplayed(), which is called
+ // after HWComposer::commit() -- every frame.
+ const Transform& tr = hw->getTransform();
+ layer.setVisibleRegionScreen(tr.transform(visibleRegion));
}
void LayerBase::setAcquireFence(const sp<const DisplayDevice>& hw,
@@ -301,6 +305,13 @@
layer.setAcquireFenceFd(-1);
}
+void LayerBase::onLayerDisplayed(const sp<const DisplayDevice>& hw,
+ HWComposer::HWCLayerInterface* layer) {
+ if (layer) {
+ layer->onDisplayed();
+ }
+}
+
void LayerBase::setFiltering(bool filtering)
{
mFiltering = filtering;
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index c18f397..4651517 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -218,7 +218,7 @@
/** called after page-flip
*/
virtual void onLayerDisplayed(const sp<const DisplayDevice>& hw,
- HWComposer::HWCLayerInterface* layer) { }
+ HWComposer::HWCLayerInterface* layer);
/** called before composition.
* returns true if the layer has pending updates.
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 7124b0c..ee653f3 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -20,6 +20,7 @@
#include <sys/types.h>
#include <errno.h>
#include <math.h>
+#include <dlfcn.h>
#include <EGL/egl.h>
#include <GLES/gl.h>
@@ -108,9 +109,11 @@
property_get("debug.sf.ddms", value, "0");
mDebugDDMS = atoi(value);
if (mDebugDDMS) {
- DdmConnection::start(getServiceName());
+ if (!startDdmConnection()) {
+ // start failed, and DDMS debugging not enabled
+ mDebugDDMS = 0;
+ }
}
-
ALOGI_IF(mDebugRegion, "showupdates enabled");
ALOGI_IF(mDebugDDMS, "DDMS debugging enabled");
}
@@ -2061,6 +2064,24 @@
hw->dump(result);
}
+bool SurfaceFlinger::startDdmConnection()
+{
+ void* libddmconnection_dso =
+ dlopen("libsurfaceflinger_ddmconnection.so", RTLD_NOW);
+ if (!libddmconnection_dso) {
+ return false;
+ }
+ void (*DdmConnection_start)(const char* name);
+ DdmConnection_start =
+ (typeof DdmConnection_start)dlsym(libddmconnection_dso, "DdmConnection_start");
+ if (!DdmConnection_start) {
+ dlclose(libddmconnection_dso);
+ return false;
+ }
+ (*DdmConnection_start)(getServiceName());
+ return true;
+}
+
status_t SurfaceFlinger::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 50fef00..9db6b2d 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -388,6 +388,7 @@
void clearStatsLocked(const Vector<String16>& args, size_t& index,
String8& result, char* buffer, size_t SIZE) const;
void dumpAllLocked(String8& result, char* buffer, size_t SIZE) const;
+ bool startDdmConnection();
/* ------------------------------------------------------------------------
* Attributes