diff options
author | Mathias Agopian <mathias@google.com> | 2011-11-29 11:47:03 -0800 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-11-29 11:47:03 -0800 |
commit | aa2892edc7bb2b915771679d9811ec54a26db366 (patch) | |
tree | 49c0dc6ac659e69b4a2b7c4c439d60b7d759e3e6 | |
parent | 1e773932a1658128b80508f081de3c80655465d2 (diff) | |
parent | f3918c5bd4bc9f02f74da42995564150ca2dd382 (diff) | |
download | frameworks_base-aa2892edc7bb2b915771679d9811ec54a26db366.zip frameworks_base-aa2892edc7bb2b915771679d9811ec54a26db366.tar.gz frameworks_base-aa2892edc7bb2b915771679d9811ec54a26db366.tar.bz2 |
Merge changes If4126023,Iacda2386,I1eb691f7,Ib56139f8
* changes:
Add support for sending VSYNC events to the framework
BitTube::read now handles EAGAIN
split ComposerService out of SurfaceComposerClient.h
rewrite SF's message loop on top of Looper
20 files changed, 288 insertions, 266 deletions
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp index 10ceb7b..202abf6 100644 --- a/core/jni/android_hardware_SensorManager.cpp +++ b/core/jni/android_hardware_SensorManager.cpp @@ -126,7 +126,7 @@ sensors_data_poll(JNIEnv *env, jclass clazz, jint nativeQueue, ASensorEvent event; res = queue->read(&event, 1); - if (res == -EAGAIN) { + if (res == 0) { res = queue->waitForEvent(); if (res != NO_ERROR) return -1; diff --git a/include/private/gui/ComposerService.h b/include/private/gui/ComposerService.h new file mode 100644 index 0000000..d04491a --- /dev/null +++ b/include/private/gui/ComposerService.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_PRIVATE_GUI_COMPOSER_SERVICE_H +#define ANDROID_PRIVATE_GUI_COMPOSER_SERVICE_H + +#include <stdint.h> +#include <sys/types.h> + +#include <utils/Singleton.h> +#include <utils/StrongPointer.h> + + +namespace android { + +// --------------------------------------------------------------------------- + +class IMemoryHeap; +class ISurfaceComposer; +class surface_flinger_cblk_t; + +// --------------------------------------------------------------------------- + +class ComposerService : public Singleton<ComposerService> +{ + // these are constants + sp<ISurfaceComposer> mComposerService; + sp<IMemoryHeap> mServerCblkMemory; + surface_flinger_cblk_t volatile* mServerCblk; + ComposerService(); + friend class Singleton<ComposerService>; +public: + static sp<ISurfaceComposer> getComposerService(); + static surface_flinger_cblk_t const volatile * getControlBlock(); +}; + +// --------------------------------------------------------------------------- +}; // namespace android + +#endif // ANDROID_PRIVATE_GUI_COMPOSER_SERVICE_H diff --git a/include/surfaceflinger/ISurfaceComposer.h b/include/surfaceflinger/ISurfaceComposer.h index 5eb09c7..58fd89d 100644 --- a/include/surfaceflinger/ISurfaceComposer.h +++ b/include/surfaceflinger/ISurfaceComposer.h @@ -33,8 +33,9 @@ namespace android { // ---------------------------------------------------------------------------- -class IMemoryHeap; class ComposerState; +class IDisplayEventConnection; +class IMemoryHeap; class ISurfaceComposer : public IInterface { @@ -124,13 +125,19 @@ public: uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ) = 0; + /* triggers screen off animation */ virtual status_t turnElectronBeamOff(int32_t mode) = 0; + + /* triggers screen on animation */ virtual status_t turnElectronBeamOn(int32_t mode) = 0; /* verify that an ISurfaceTexture was created by SurfaceFlinger. */ virtual bool authenticateSurfaceTexture( const sp<ISurfaceTexture>& surface) const = 0; + + /* return an IDisplayEventConnection */ + virtual sp<IDisplayEventConnection> createDisplayEventConnection() = 0; }; // ---------------------------------------------------------------------------- @@ -151,6 +158,7 @@ public: TURN_ELECTRON_BEAM_OFF, TURN_ELECTRON_BEAM_ON, AUTHENTICATE_SURFACE, + CREATE_DISPLAY_EVENT_CONNECTION, }; virtual status_t onTransact( uint32_t code, diff --git a/include/surfaceflinger/SurfaceComposerClient.h b/include/surfaceflinger/SurfaceComposerClient.h index 8226abe..99affda 100644 --- a/include/surfaceflinger/SurfaceComposerClient.h +++ b/include/surfaceflinger/SurfaceComposerClient.h @@ -28,7 +28,6 @@ #include <utils/threads.h> #include <ui/PixelFormat.h> -#include <ui/Region.h> #include <surfaceflinger/Surface.h> @@ -39,30 +38,11 @@ namespace android { class DisplayInfo; class Composer; class IMemoryHeap; -class ISurfaceComposer; +class ISurfaceComposerClient; class Region; -class surface_flinger_cblk_t; -struct layer_state_t; // --------------------------------------------------------------------------- -class ComposerService : public Singleton<ComposerService> -{ - // these are constants - sp<ISurfaceComposer> mComposerService; - sp<IMemoryHeap> mServerCblkMemory; - surface_flinger_cblk_t volatile* mServerCblk; - ComposerService(); - friend class Singleton<ComposerService>; -public: - static sp<ISurfaceComposer> getComposerService(); - static surface_flinger_cblk_t const volatile * getControlBlock(); -}; - -// --------------------------------------------------------------------------- - -class Composer; - class SurfaceComposerClient : public RefBase { friend class Composer; diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk index b7e3ee3..b8be67d 100644 --- a/libs/gui/Android.mk +++ b/libs/gui/Android.mk @@ -3,6 +3,8 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ BitTube.cpp \ + DisplayEventReceiver.cpp \ + IDisplayEventConnection.cpp \ ISensorEventConnection.cpp \ ISensorServer.cpp \ ISurfaceTexture.cpp \ diff --git a/libs/gui/BitTube.cpp b/libs/gui/BitTube.cpp index c632b43..fa8d0ea 100644 --- a/libs/gui/BitTube.cpp +++ b/libs/gui/BitTube.cpp @@ -97,6 +97,11 @@ ssize_t BitTube::read(void* vaddr, size_t size) len = ::read(mReceiveFd, vaddr, size); err = len < 0 ? errno : 0; } while (err == EINTR); + if (err == EAGAIN || err == EWOULDBLOCK) { + // EAGAIN means that we have non-blocking I/O but there was + // no data to be read. Nothing the client should care about. + return 0; + } return err == 0 ? len : -err; } diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 86bc62a..db32827 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -29,6 +29,9 @@ #include <surfaceflinger/ISurfaceComposer.h> +#include <gui/BitTube.h> +#include <gui/IDisplayEventConnection.h> + #include <ui/DisplayInfo.h> #include <gui/ISurfaceTexture.h> @@ -44,6 +47,8 @@ namespace android { +class IDisplayEventConnection; + class BpSurfaceComposer : public BpInterface<ISurfaceComposer> { public: @@ -174,6 +179,27 @@ public: } return result != 0; } + + virtual sp<IDisplayEventConnection> createDisplayEventConnection() + { + Parcel data, reply; + sp<IDisplayEventConnection> result; + int err = data.writeInterfaceToken( + ISurfaceComposer::getInterfaceDescriptor()); + if (err != NO_ERROR) { + return result; + } + err = remote()->transact( + BnSurfaceComposer::CREATE_DISPLAY_EVENT_CONNECTION, + data, &reply); + if (err != NO_ERROR) { + LOGE("ISurfaceComposer::createDisplayEventConnection: error performing " + "transaction: %s (%d)", strerror(-err), -err); + return result; + } + result = interface_cast<IDisplayEventConnection>(reply.readStrongBinder()); + return result; + } }; IMPLEMENT_META_INTERFACE(SurfaceComposer, "android.ui.ISurfaceComposer"); @@ -254,6 +280,12 @@ status_t BnSurfaceComposer::onTransact( int32_t result = authenticateSurfaceTexture(surfaceTexture) ? 1 : 0; reply->writeInt32(result); } break; + case CREATE_DISPLAY_EVENT_CONNECTION: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + sp<IDisplayEventConnection> connection(createDisplayEventConnection()); + reply->writeStrongBinder(connection->asBinder()); + return NO_ERROR; + } break; default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 4ad6c22..699438c 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -39,6 +39,7 @@ #include <private/surfaceflinger/LayerState.h> #include <private/surfaceflinger/SharedBufferStack.h> +#include <private/gui/ComposerService.h> namespace android { // --------------------------------------------------------------------------- diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp index b4d01a9..289726b 100644 --- a/libs/gui/SurfaceTexture.cpp +++ b/libs/gui/SurfaceTexture.cpp @@ -29,6 +29,8 @@ #include <hardware/hardware.h> +#include <private/gui/ComposerService.h> + #include <surfaceflinger/ISurfaceComposer.h> #include <surfaceflinger/SurfaceComposerClient.h> #include <surfaceflinger/IGraphicBufferAlloc.h> diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp index 3d47f05..691b52d 100644 --- a/libs/gui/SurfaceTextureClient.cpp +++ b/libs/gui/SurfaceTextureClient.cpp @@ -23,6 +23,8 @@ #include <utils/Log.h> +#include <private/gui/ComposerService.h> + namespace android { SurfaceTextureClient::SurfaceTextureClient( diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 693b7b8..ea52750 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -22,6 +22,8 @@ #include <surfaceflinger/SurfaceComposerClient.h> #include <utils/String8.h> +#include <private/gui/ComposerService.h> + namespace android { class SurfaceTest : public ::testing::Test { diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp index 210635f..24e0d8c 100644 --- a/media/libstagefright/SurfaceMediaSource.cpp +++ b/media/libstagefright/SurfaceMediaSource.cpp @@ -32,6 +32,8 @@ #include <utils/Log.h> #include <utils/String8.h> +#include <private/gui/ComposerService.h> + namespace android { SurfaceMediaSource::SurfaceMediaSource(uint32_t bufW, uint32_t bufH) : diff --git a/services/jni/com_android_server_PowerManagerService.cpp b/services/jni/com_android_server_PowerManagerService.cpp index a389c11..08650e1 100644 --- a/services/jni/com_android_server_PowerManagerService.cpp +++ b/services/jni/com_android_server_PowerManagerService.cpp @@ -28,6 +28,8 @@ #include <surfaceflinger/ISurfaceComposer.h> #include <surfaceflinger/SurfaceComposerClient.h> +#include <private/gui/ComposerService.h> + #include "com_android_server_PowerManagerService.h" namespace android { diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index f63c0c1..95d651a 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -2,19 +2,22 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ - Layer.cpp \ - LayerBase.cpp \ - LayerDim.cpp \ - LayerScreenshot.cpp \ - DdmConnection.cpp \ - DisplayHardware/DisplayHardware.cpp \ + EventThread.cpp \ + Layer.cpp \ + LayerBase.cpp \ + LayerDim.cpp \ + LayerScreenshot.cpp \ + DdmConnection.cpp \ + DisplayHardware/DisplayHardware.cpp \ DisplayHardware/DisplayHardwareBase.cpp \ - DisplayHardware/HWComposer.cpp \ - GLExtensions.cpp \ - MessageQueue.cpp \ - SurfaceFlinger.cpp \ - SurfaceTextureLayer.cpp \ - Transform.cpp \ + DisplayHardware/HWComposer.cpp \ + DisplayHardware/VSyncBarrier.cpp \ + DisplayEventConnection.cpp \ + GLExtensions.cpp \ + MessageQueue.cpp \ + SurfaceFlinger.cpp \ + SurfaceTextureLayer.cpp \ + Transform.cpp \ LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\" diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp index f94d321..3bbc75e 100644 --- a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp +++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp @@ -140,6 +140,7 @@ void DisplayHardware::init(uint32_t dpy) mDpiX = mNativeWindow->xdpi; mDpiY = mNativeWindow->ydpi; mRefreshRate = fbDev->fps; + mNextFakeVSync = 0; /* FIXME: this is a temporary HACK until we are able to report the refresh rate @@ -152,6 +153,8 @@ void DisplayHardware::init(uint32_t dpy) #warning "refresh rate set via makefile to REFRESH_RATE" #endif + mRefreshPeriod = nsecs_t(1e9 / mRefreshRate); + EGLint w, h, dummy; EGLint numConfigs=0; EGLSurface surface; @@ -346,6 +349,37 @@ uint32_t DisplayHardware::getPageFlipCount() const { return mPageFlipCount; } +// this needs to be thread safe +nsecs_t DisplayHardware::waitForVSync() const { + nsecs_t timestamp; + if (mVSync.wait(×tamp) < 0) { + // vsync not supported! + usleep( getDelayToNextVSyncUs(×tamp) ); + } + return timestamp; +} + +int32_t DisplayHardware::getDelayToNextVSyncUs(nsecs_t* timestamp) const { + Mutex::Autolock _l(mFakeVSyncMutex); + const nsecs_t period = mRefreshPeriod; + const nsecs_t now = systemTime(CLOCK_MONOTONIC); + nsecs_t next_vsync = mNextFakeVSync; + nsecs_t sleep = next_vsync - now; + if (sleep < 0) { + // we missed, find where the next vsync should be + sleep = (period - ((now - next_vsync) % period)); + next_vsync = now + sleep; + } + mNextFakeVSync = next_vsync + period; + timestamp[0] = next_vsync; + + // round to next microsecond + int32_t sleep_us = (sleep + 999LL) / 1000LL; + + // guaranteed to be > 0 + return sleep_us; +} + status_t DisplayHardware::compositionComplete() const { return mNativeWindow->compositionComplete(); } diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.h b/services/surfaceflinger/DisplayHardware/DisplayHardware.h index f02c954..45d4b45 100644 --- a/services/surfaceflinger/DisplayHardware/DisplayHardware.h +++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.h @@ -32,6 +32,7 @@ #include "GLExtensions.h" #include "DisplayHardware/DisplayHardwareBase.h" +#include "DisplayHardware/VSyncBarrier.h" namespace android { @@ -74,6 +75,9 @@ public: uint32_t getMaxTextureSize() const; uint32_t getMaxViewportDims() const; + // waits for the next vsync and returns the timestamp of when it happened + nsecs_t waitForVSync() const; + uint32_t getPageFlipCount() const; EGLDisplay getEGLDisplay() const { return mDisplay; } @@ -95,6 +99,7 @@ public: private: void init(uint32_t displayIndex) __attribute__((noinline)); void fini() __attribute__((noinline)); + int32_t getDelayToNextVSyncUs(nsecs_t* timestamp) const; sp<SurfaceFlinger> mFlinger; EGLDisplay mDisplay; @@ -112,7 +117,12 @@ private: mutable uint32_t mPageFlipCount; GLint mMaxViewportDims[2]; GLint mMaxTextureSize; - + VSyncBarrier mVSync; + + mutable Mutex mFakeVSyncMutex; + mutable nsecs_t mNextFakeVSync; + nsecs_t mRefreshPeriod; + HWComposer* mHwc; sp<FramebufferNativeWindow> mNativeWindow; diff --git a/services/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/MessageQueue.cpp index aebe1b8..1846ccb 100644 --- a/services/surfaceflinger/MessageQueue.cpp +++ b/services/surfaceflinger/MessageQueue.cpp @@ -29,167 +29,79 @@ namespace android { // --------------------------------------------------------------------------- -void MessageList::insert(const sp<MessageBase>& node) -{ - LIST::iterator cur(mList.begin()); - LIST::iterator end(mList.end()); - while (cur != end) { - if (*node < **cur) { - mList.insert(cur, node); - return; - } - ++cur; - } - mList.insert(++end, node); +MessageBase::MessageBase() + : MessageHandler() { } -void MessageList::remove(MessageList::LIST::iterator pos) -{ - mList.erase(pos); +MessageBase::~MessageBase() { } +void MessageBase::handleMessage(const Message&) { + this->handler(); + barrier.open(); +}; + // --------------------------------------------------------------------------- MessageQueue::MessageQueue() - : mInvalidate(false) + : mLooper(new Looper(true)), + mInvalidatePending(0) { - mInvalidateMessage = new MessageBase(INVALIDATE); } -MessageQueue::~MessageQueue() -{ +MessageQueue::~MessageQueue() { } -sp<MessageBase> MessageQueue::waitMessage(nsecs_t timeout) -{ - sp<MessageBase> result; - - bool again; +void MessageQueue::waitMessage() { do { - const nsecs_t timeoutTime = systemTime() + timeout; - while (true) { - Mutex::Autolock _l(mLock); - nsecs_t now = systemTime(); - nsecs_t nextEventTime = -1; - - LIST::iterator cur(mMessages.begin()); - if (cur != mMessages.end()) { - result = *cur; - } - - if (result != 0) { - if (result->when <= now) { - // there is a message to deliver - mMessages.remove(cur); - break; - } - nextEventTime = result->when; - result = 0; - } - - // see if we have an invalidate message - if (mInvalidate) { - mInvalidate = false; - mInvalidateMessage->when = now; - result = mInvalidateMessage; - break; - } - - if (timeout >= 0) { - if (timeoutTime < now) { - // we timed-out, return a NULL message - result = 0; - break; - } - if (nextEventTime > 0) { - if (nextEventTime > timeoutTime) { - nextEventTime = timeoutTime; - } - } else { - nextEventTime = timeoutTime; - } - } - - if (nextEventTime >= 0) { - //LOGD("nextEventTime = %lld ms", nextEventTime); - if (nextEventTime > 0) { - // we're about to wait, flush the binder command buffer - IPCThreadState::self()->flushCommands(); - const nsecs_t reltime = nextEventTime - systemTime(); - if (reltime > 0) { - mCondition.waitRelative(mLock, reltime); - } - } - } else { - //LOGD("going to wait"); - // we're about to wait, flush the binder command buffer - IPCThreadState::self()->flushCommands(); - mCondition.wait(mLock); - } - } - // here we're not holding the lock anymore - - if (result == 0) + // handle invalidate events first + if (android_atomic_and(0, &mInvalidatePending) != 0) break; - again = result->handler(); - if (again) { - // the message has been processed. release our reference to it - // without holding the lock. - result->notify(); - result = 0; - } - - } while (again); + IPCThreadState::self()->flushCommands(); - return result; -} + int32_t ret = mLooper->pollOnce(-1); + switch (ret) { + case ALOOPER_POLL_WAKE: + // we got woken-up there is work to do in the main loop + continue; -status_t MessageQueue::postMessage( - const sp<MessageBase>& message, nsecs_t relTime, uint32_t flags) -{ - return queueMessage(message, relTime, flags); -} + case ALOOPER_POLL_CALLBACK: + // callback was handled, loop again + continue; -status_t MessageQueue::invalidate() { - Mutex::Autolock _l(mLock); - mInvalidate = true; - mCondition.signal(); - return NO_ERROR; -} + case ALOOPER_POLL_TIMEOUT: + // timeout (should not happen) + continue; -status_t MessageQueue::queueMessage( - const sp<MessageBase>& message, nsecs_t relTime, uint32_t flags) -{ - Mutex::Autolock _l(mLock); - message->when = systemTime() + relTime; - mMessages.insert(message); - - //LOGD("MessageQueue::queueMessage time = %lld ms", message->when); - //dumpLocked(message); - - mCondition.signal(); - return NO_ERROR; -} + case ALOOPER_POLL_ERROR: + LOGE("ALOOPER_POLL_ERROR"); + continue; -void MessageQueue::dump(const sp<MessageBase>& message) -{ - Mutex::Autolock _l(mLock); - dumpLocked(message); + default: + // should not happen + LOGE("Looper::pollOnce() returned unknown status %d", ret); + continue; + } + } while (true); } -void MessageQueue::dumpLocked(const sp<MessageBase>& message) +status_t MessageQueue::postMessage( + const sp<MessageBase>& messageHandler, nsecs_t relTime) { - LIST::const_iterator cur(mMessages.begin()); - LIST::const_iterator end(mMessages.end()); - int c = 0; - while (cur != end) { - const char tick = (*cur == message) ? '>' : ' '; - LOGD("%c %d: msg{.what=%08x, when=%lld}", - tick, c, (*cur)->what, (*cur)->when); - ++cur; - c++; + const Message dummyMessage; + if (relTime > 0) { + mLooper->sendMessageDelayed(relTime, messageHandler, dummyMessage); + } else { + mLooper->sendMessage(messageHandler, dummyMessage); } + return NO_ERROR; +} + +status_t MessageQueue::invalidate() { + android_atomic_or(1, &mInvalidatePending); + mLooper->wake(); + return NO_ERROR; } // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/MessageQueue.h b/services/surfaceflinger/MessageQueue.h index 890f809..25030a6 100644 --- a/services/surfaceflinger/MessageQueue.h +++ b/services/surfaceflinger/MessageQueue.h @@ -23,7 +23,7 @@ #include <utils/threads.h> #include <utils/Timers.h> -#include <utils/List.h> +#include <utils/Looper.h> #include "Barrier.h" @@ -31,92 +31,39 @@ namespace android { // --------------------------------------------------------------------------- -class MessageBase; - -class MessageList -{ - List< sp<MessageBase> > mList; - typedef List< sp<MessageBase> > LIST; -public: - inline LIST::iterator begin() { return mList.begin(); } - inline LIST::const_iterator begin() const { return mList.begin(); } - inline LIST::iterator end() { return mList.end(); } - inline LIST::const_iterator end() const { return mList.end(); } - inline bool isEmpty() const { return mList.empty(); } - void insert(const sp<MessageBase>& node); - void remove(LIST::iterator pos); -}; - -// ============================================================================ - -class MessageBase : - public LightRefBase<MessageBase> +class MessageBase : public MessageHandler { public: - nsecs_t when; - uint32_t what; - int32_t arg0; - - MessageBase() : when(0), what(0), arg0(0) { } - MessageBase(uint32_t what, int32_t arg0=0) - : when(0), what(what), arg0(arg0) { } + MessageBase(); // return true if message has a handler - virtual bool handler() { return false; } + virtual bool handler() = 0; // waits for the handler to be processed void wait() const { barrier.wait(); } - - // releases all waiters. this is done automatically if - // handler returns true - void notify() const { barrier.open(); } protected: - virtual ~MessageBase() { } + virtual ~MessageBase(); private: + virtual void handleMessage(const Message& message); + mutable Barrier barrier; - friend class LightRefBase<MessageBase>; }; -inline bool operator < (const MessageBase& lhs, const MessageBase& rhs) { - return lhs.when < rhs.when; -} - // --------------------------------------------------------------------------- -class MessageQueue -{ - typedef List< sp<MessageBase> > LIST; -public: +class MessageQueue { + sp<Looper> mLooper; + volatile int32_t mInvalidatePending; +public: MessageQueue(); ~MessageQueue(); - // pre-defined messages - enum { - INVALIDATE = '_upd' - }; - - sp<MessageBase> waitMessage(nsecs_t timeout = -1); - - status_t postMessage(const sp<MessageBase>& message, - nsecs_t reltime=0, uint32_t flags = 0); - + void waitMessage(); + status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime=0); status_t invalidate(); - - void dump(const sp<MessageBase>& message); - -private: - status_t queueMessage(const sp<MessageBase>& message, - nsecs_t reltime, uint32_t flags); - void dumpLocked(const sp<MessageBase>& message); - - Mutex mLock; - Condition mCondition; - MessageList mMessages; - bool mInvalidate; - sp<MessageBase> mInvalidateMessage; }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 1b00e93..d5a8d08 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -34,6 +34,8 @@ #include <binder/MemoryHeapBase.h> #include <binder/PermissionCache.h> +#include <gui/IDisplayEventConnection.h> + #include <utils/String8.h> #include <utils/String16.h> #include <utils/StopWatch.h> @@ -46,6 +48,8 @@ #include <GLES/gl.h> #include "clz.h" +#include "DisplayEventConnection.h" +#include "EventThread.h" #include "GLExtensions.h" #include "DdmConnection.h" #include "Layer.h" @@ -293,12 +297,16 @@ status_t SurfaceFlinger::readyToRun() // put the origin in the left-bottom corner glOrthof(0, w, 0, h, 0, 1); // l=0, r=w ; b=0, t=h - mReadyToRunBarrier.open(); + + // start the EventThread + mEventThread = new EventThread(this); /* * We're now ready to accept clients... */ + mReadyToRunBarrier.open(); + // start boot animation property_set("ctl.start", "bootanim"); @@ -311,25 +319,30 @@ status_t SurfaceFlinger::readyToRun() #pragma mark Events Handler #endif -void SurfaceFlinger::waitForEvent() -{ - while (true) { - nsecs_t timeout = -1; - sp<MessageBase> msg = mEventQueue.waitMessage(timeout); - if (msg != 0) { - switch (msg->what) { - case MessageQueue::INVALIDATE: - // invalidate message, just return to the main loop - return; - } - } - } +void SurfaceFlinger::waitForEvent() { + mEventQueue.waitMessage(); } void SurfaceFlinger::signalEvent() { mEventQueue.invalidate(); } +status_t SurfaceFlinger::postMessageAsync(const sp<MessageBase>& msg, + nsecs_t reltime, uint32_t flags) { + return mEventQueue.postMessage(msg, reltime); +} + +status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg, + nsecs_t reltime, uint32_t flags) { + status_t res = mEventQueue.postMessage(msg, reltime); + if (res == NO_ERROR) { + msg->wait(); + } + return res; +} + +// ---------------------------------------------------------------------------- + bool SurfaceFlinger::authenticateSurfaceTexture( const sp<ISurfaceTexture>& surfaceTexture) const { Mutex::Autolock _l(mStateLock); @@ -371,20 +384,17 @@ bool SurfaceFlinger::authenticateSurfaceTexture( return false; } -status_t SurfaceFlinger::postMessageAsync(const sp<MessageBase>& msg, - nsecs_t reltime, uint32_t flags) -{ - return mEventQueue.postMessage(msg, reltime, flags); +// ---------------------------------------------------------------------------- + +sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection() { + sp<DisplayEventConnection> result(new DisplayEventConnection(this)); + mEventThread->registerDisplayEventConnection(result); + return result; } -status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg, - nsecs_t reltime, uint32_t flags) -{ - status_t res = mEventQueue.postMessage(msg, reltime, flags); - if (res == NO_ERROR) { - msg->wait(); - } - return res; +void SurfaceFlinger::cleanupDisplayEventConnection( + const wp<DisplayEventConnection>& connection) { + mEventThread->unregisterDisplayEventConnection(connection); } // ---------------------------------------------------------------------------- @@ -443,7 +453,7 @@ bool SurfaceFlinger::threadLoop() } else { // pretend we did the post hw.compositionComplete(); - usleep(16667); // 60 fps period + hw.waitForVSync(); } return true; } @@ -1583,9 +1593,16 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) } /* + * VSYNC state + */ + mEventThread->dump(result, buffer, SIZE); + + /* * Dump HWComposer state */ HWComposer& hwc(hw.getHwComposer()); + snprintf(buffer, SIZE, "h/w composer state:\n"); + result.append(buffer); snprintf(buffer, SIZE, " h/w composer %s and %s\n", hwc.initCheck()==NO_ERROR ? "present" : "not present", (mDebugDisableHWC || mDebugRegion) ? "disabled" : "enabled"); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 17028db..1039f47 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -46,6 +46,8 @@ namespace android { class Client; class DisplayHardware; +class DisplayEventConnection; +class EventThread; class Layer; class LayerDim; class LayerScreenshot; @@ -171,6 +173,7 @@ public: int orientation, uint32_t flags); virtual int setOrientation(DisplayID dpy, int orientation, uint32_t flags); virtual bool authenticateSurfaceTexture(const sp<ISurfaceTexture>& surface) const; + virtual sp<IDisplayEventConnection> createDisplayEventConnection(); virtual status_t captureScreen(DisplayID dpy, sp<IMemoryHeap>* heap, @@ -222,6 +225,7 @@ private: private: friend class Client; + friend class DisplayEventConnection; friend class LayerBase; friend class LayerBaseClient; friend class Layer; @@ -331,6 +335,9 @@ private: status_t electronBeamOffAnimationImplLocked(); status_t electronBeamOnAnimationImplLocked(); + void cleanupDisplayEventConnection( + const wp<DisplayEventConnection>& connection); + void debugFlashRegions(); void debugShowFPS() const; void drawWormhole() const; @@ -361,6 +368,7 @@ private: GLuint mWormholeTexName; GLuint mProtectedTexName; nsecs_t mBootTime; + sp<EventThread> mEventThread; // Can only accessed from the main thread, these members // don't need synchronization |