diff options
-rw-r--r-- | include/android/configuration.h | 16 | ||||
-rw-r--r-- | include/binder/IPCThreadState.h | 2 | ||||
-rw-r--r-- | include/binder/Parcel.h | 18 | ||||
-rw-r--r-- | include/ui/Region.h | 34 | ||||
-rw-r--r-- | include/utils/SharedBuffer.h | 27 | ||||
-rw-r--r-- | libs/binder/IPCThreadState.cpp | 8 | ||||
-rw-r--r-- | libs/ui/Region.cpp | 81 | ||||
-rw-r--r-- | libs/utils/VectorImpl.cpp | 14 | ||||
-rw-r--r-- | services/surfaceflinger/Android.mk | 16 | ||||
-rw-r--r-- | services/surfaceflinger/DdmConnection.cpp | 4 | ||||
-rw-r--r-- | services/surfaceflinger/DdmConnection.h | 3 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayHardware/HWComposer.cpp | 19 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayHardware/HWComposer.h | 1 | ||||
-rw-r--r-- | services/surfaceflinger/EventThread.cpp | 43 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.cpp | 1 | ||||
-rw-r--r-- | services/surfaceflinger/LayerBase.cpp | 13 | ||||
-rw-r--r-- | services/surfaceflinger/LayerBase.h | 2 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 25 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 1 |
19 files changed, 218 insertions, 110 deletions
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 @@ enum { 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 @@ enum { ACONFIGURATION_SCREEN_LAYOUT = 0x0800, ACONFIGURATION_UI_MODE = 0x1000, ACONFIGURATION_SMALLEST_SCREEN_SIZE = 0x2000, + ACONFIGURATION_LAYOUTDIR = 0x4000, }; /** @@ -331,6 +336,17 @@ int32_t AConfiguration_getSmallestScreenWidthDp(AConfiguration* config); 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 @@ public: int getCallingPid(); int getCallingUid(); - int getOrigCallingUid(); void setStrictModePolicy(int32_t policy); int32_t getStrictModePolicy() const; @@ -117,7 +116,6 @@ private: 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 @@ status_t Parcel::write(const LightFlattenable<T>& val) { 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 @@ status_t Parcel::read(LightFlattenable<T>& val) const { } 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 @@ public: 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,17 +107,23 @@ public: /* 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; - /* no user serviceable parts here... */ - - size_t getRects(Vector<Rect>& rectList) const; - Rect const* getArray(size_t* count) 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... */ // add a rectangle to the internal list. This rectangle must // be sorted in Y and X and must not make the region invalid. @@ -156,8 +163,11 @@ private: 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 @@ public: * 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 @@ public: 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 @@ private: // --------------------------------------------------------------------------- -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 @@ size_t SharedBuffer::size() const { 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 @@ int IPCThreadState::getCallingUid() return mCallingUid; } -int IPCThreadState::getOrigCallingUid() -{ - return mOrigCallingUid; -} - int64_t IPCThreadState::clearCallingIdentity() { int64_t token = ((int64_t)mCallingUid<<32) | mCallingPid; @@ -646,7 +641,6 @@ IPCThreadState::IPCThreadState() { pthread_setspecific(gTLS, this); clearCaller(); - mOrigCallingUid = mCallingUid; mIn.setDataCapacity(256); mOut.setDataCapacity(256); } @@ -998,7 +992,6 @@ status_t IPCThreadState::executeCommand(int32_t cmd) mCallingPid = tr.sender_pid; mCallingUid = tr.sender_euid; - mOrigCallingUid = tr.sender_euid; int curPrio = getpriority(PRIO_PROCESS, mMyThreadId); if (gDisableBackgroundScheduling) { @@ -1056,7 +1049,6 @@ status_t IPCThreadState::executeCommand(int32_t cmd) 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 @@ enum { // ---------------------------------------------------------------------------- -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 @@ Region& Region::operator = (const Region& rhs) 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 @@ const Region Region::operation(const Region& rhs, int dx, int dy, int op) const // 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 @@ class Region::rasterizer : public region_operator<Rect>::region_rasterizer 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 @@ public: bounds.left = 0; bounds.right = 0; } + storage.add(bounds); } virtual void operator()(const Rect& rect) { @@ -372,6 +374,9 @@ bool Region::validate(const Region& reg, const char* name) 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::boolean_operation(int op, Region& dst, 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 @@ void Region::translate(Region& dst, const Region& reg, int dx, int dy) // ---------------------------------------------------------------------------- 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 @@ status_t Region::unflatten(void const* buffer, size_t size) { 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 @@ status_t Region::unflatten(void const* buffer, size_t size) { 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 @@ Rect const* Region::getArray(size_t* count) const { 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 @@ VectorImpl::VectorImpl(const VectorImpl& rhs) mFlags(rhs.mFlags), mItemSize(rhs.mItemSize) { if (mStorage) { - SharedBuffer::sharedBuffer(mStorage)->acquire(); + SharedBuffer::bufferFromData(mStorage)->acquire(); } } @@ -73,7 +73,7 @@ VectorImpl& VectorImpl::operator = (const VectorImpl& rhs) 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 @@ VectorImpl& VectorImpl::operator = (const VectorImpl& rhs) 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 @@ void* VectorImpl::editArrayImpl() 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 @@ ssize_t VectorImpl::setCapacity(size_t new_capacity) 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 @@ void* VectorImpl::_grow(size_t where, size_t amount) (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 @@ void VectorImpl::_shrink(size_t where, size_t amount) (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_SHARED_LIBRARIES := \ 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ bool EventThread::threadLoop() { 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 @@ Vector< sp<EventThread::Connection> > EventThread::waitForEvent( // 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 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client) 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 @@ void LayerBase::setGeometry( // 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 @@ void LayerBase::setAcquireFence(const sp<const DisplayDevice>& hw, 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 @@ public: /** 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 @@ SurfaceFlinger::SurfaceFlinger() 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 @@ void SurfaceFlinger::dumpAllLocked( 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 @@ private: 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 |