diff options
Diffstat (limited to 'services')
20 files changed, 298 insertions, 128 deletions
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp index 1a6ff33..9157bc1 100644 --- a/services/inputflinger/InputDispatcher.cpp +++ b/services/inputflinger/InputDispatcher.cpp @@ -477,7 +477,6 @@ sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t display const InputWindowInfo* windowInfo = windowHandle->getInfo(); if (windowInfo->displayId == displayId) { int32_t flags = windowInfo->layoutParamsFlags; - int32_t privateFlags = windowInfo->layoutParamsPrivateFlags; if (windowInfo->visible) { if (!(flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) { @@ -489,11 +488,6 @@ sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t display } } } - - if (privateFlags & InputWindowInfo::PRIVATE_FLAG_SYSTEM_ERROR) { - // Error window is on top but not visible, so touch is dropped. - return NULL; - } } } return NULL; @@ -1190,7 +1184,6 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, int32_t y = int32_t(entry->pointerCoords[pointerIndex]. getAxisValue(AMOTION_EVENT_AXIS_Y)); sp<InputWindowHandle> newTouchedWindowHandle; - sp<InputWindowHandle> topErrorWindowHandle; bool isTouchModal = false; // Traverse windows from front to back to find touched window and outside targets. @@ -1202,13 +1195,6 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, continue; // wrong display } - int32_t privateFlags = windowInfo->layoutParamsPrivateFlags; - if (privateFlags & InputWindowInfo::PRIVATE_FLAG_SYSTEM_ERROR) { - if (topErrorWindowHandle == NULL) { - topErrorWindowHandle = windowHandle; - } - } - int32_t flags = windowInfo->layoutParamsFlags; if (windowInfo->visible) { if (! (flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) { @@ -1233,17 +1219,6 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, } } - // If there is an error window but it is not taking focus (typically because - // it is invisible) then wait for it. Any other focused window may in - // fact be in ANR state. - if (topErrorWindowHandle != NULL && newTouchedWindowHandle != topErrorWindowHandle) { - injectionResult = handleTargetsNotReadyLocked(currentTime, entry, - NULL, NULL, nextWakeupTime, - "Waiting because a system error window is about to be displayed."); - injectionPermission = INJECTION_PERMISSION_UNKNOWN; - goto Unresponsive; - } - // Figure out whether splitting will be allowed for this window. if (newTouchedWindowHandle != NULL && newTouchedWindowHandle->getInfo()->supportsSplitTouch()) { diff --git a/services/inputflinger/InputWindow.h b/services/inputflinger/InputWindow.h index 5879c84..42457ce 100644 --- a/services/inputflinger/InputWindow.h +++ b/services/inputflinger/InputWindow.h @@ -64,11 +64,6 @@ struct InputWindowInfo { FLAG_NEEDS_MENU_KEY = 0x40000000, }; - // Private Window flags from WindowManager.LayoutParams - enum { - PRIVATE_FLAG_SYSTEM_ERROR = 0x00000100, - }; - // Window types from WindowManager.LayoutParams enum { FIRST_APPLICATION_WINDOW = 1, @@ -119,7 +114,6 @@ struct InputWindowInfo { sp<InputChannel> inputChannel; String8 name; int32_t layoutParamsFlags; - int32_t layoutParamsPrivateFlags; int32_t layoutParamsType; nsecs_t dispatchingTimeout; int32_t frameLeft; diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp index 9b2acea..a857366 100644 --- a/services/sensorservice/SensorService.cpp +++ b/services/sensorservice/SensorService.cpp @@ -191,6 +191,8 @@ void SensorService::onFirstRef() mSensorEventScratch = new sensors_event_t[minBufferSize]; mMapFlushEventsToConnections = new SensorEventConnection const * [minBufferSize]; + mAckReceiver = new SensorEventAckReceiver(this); + mAckReceiver->run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY); mInitCheck = NO_ERROR; run("SensorService", PRIORITY_URGENT_DISPLAY); } @@ -386,8 +388,6 @@ bool SensorService::threadLoop() SensorDevice& device(SensorDevice::getInstance()); const size_t vcount = mVirtualSensorList.size(); - SensorEventAckReceiver sender(this); - sender.run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY); const int halVersion = device.getHalDeviceVersion(); do { ssize_t count = device.poll(mSensorEventBuffer, numEventMax); @@ -408,16 +408,7 @@ bool SensorService::threadLoop() // result in a deadlock as ~SensorEventConnection() needs to acquire mLock again for // cleanup. So copy all the strongPointers to a vector before the lock is acquired. SortedVector< sp<SensorEventConnection> > activeConnections; - { - Mutex::Autolock _l(mLock); - for (size_t i=0 ; i < mActiveConnections.size(); ++i) { - sp<SensorEventConnection> connection(mActiveConnections[i].promote()); - if (connection != 0) { - activeConnections.add(connection); - } - } - } - + populateActiveConnections(&activeConnections); Mutex::Autolock _l(mLock); // Poll has returned. Hold a wakelock if one of the events is from a wake up sensor. The // rest of this loop is under a critical section protected by mLock. Acquiring a wakeLock, @@ -433,8 +424,7 @@ bool SensorService::threadLoop() } if (bufferHasWakeUpEvent && !mWakeLockAcquired) { - acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME); - mWakeLockAcquired = true; + setWakeLockAcquiredLocked(true); } recordLastValueLocked(mSensorEventBuffer, count); @@ -522,8 +512,7 @@ bool SensorService::threadLoop() } if (mWakeLockAcquired && !needsWakeLock) { - release_wake_lock(WAKE_LOCK_NAME); - mWakeLockAcquired = false; + setWakeLockAcquiredLocked(false); } } while (!Thread::exitPending()); @@ -536,11 +525,52 @@ sp<Looper> SensorService::getLooper() const { return mLooper; } +void SensorService::resetAllWakeLockRefCounts() { + SortedVector< sp<SensorEventConnection> > activeConnections; + populateActiveConnections(&activeConnections); + { + Mutex::Autolock _l(mLock); + for (size_t i=0 ; i < activeConnections.size(); ++i) { + if (activeConnections[i] != 0) { + activeConnections[i]->resetWakeLockRefCount(); + } + } + setWakeLockAcquiredLocked(false); + } +} + +void SensorService::setWakeLockAcquiredLocked(bool acquire) { + if (acquire) { + if (!mWakeLockAcquired) { + acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME); + mWakeLockAcquired = true; + } + mLooper->wake(); + } else { + if (mWakeLockAcquired) { + release_wake_lock(WAKE_LOCK_NAME); + mWakeLockAcquired = false; + } + } +} + + +bool SensorService::isWakeLockAcquired() { + Mutex::Autolock _l(mLock); + return mWakeLockAcquired; +} + bool SensorService::SensorEventAckReceiver::threadLoop() { ALOGD("new thread SensorEventAckReceiver"); + sp<Looper> looper = mService->getLooper(); do { - sp<Looper> looper = mService->getLooper(); - looper->pollOnce(-1); + bool wakeLockAcquired = mService->isWakeLockAcquired(); + int timeout = -1; + if (wakeLockAcquired) timeout = 5000; + int ret = looper->pollOnce(timeout); + if (ret == ALOOPER_POLL_TIMEOUT) { + mService->resetAllWakeLockRefCounts(); + } } while(!Thread::exitPending()); return false; } @@ -711,10 +741,7 @@ status_t SensorService::enable(const sp<SensorEventConnection>& connection, sensors_event_t& event(mLastEventSeen.editValueFor(handle)); if (event.version == sizeof(sensors_event_t)) { if (isWakeUpSensorEvent(event) && !mWakeLockAcquired) { - acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME); - mWakeLockAcquired = true; - ALOGD_IF(DEBUG_CONNECTIONS, "acquired wakelock for on_change sensor %s", - WAKE_LOCK_NAME); + setWakeLockAcquiredLocked(true); } connection->sendEvents(&event, 1, NULL); if (!connection->needsWakeLock() && mWakeLockAcquired) { @@ -919,8 +946,26 @@ void SensorService::checkWakeLockStateLocked() { } } if (releaseLock) { - release_wake_lock(WAKE_LOCK_NAME); - mWakeLockAcquired = false; + setWakeLockAcquiredLocked(false); + } +} + +void SensorService::sendEventsFromCache(const sp<SensorEventConnection>& connection) { + Mutex::Autolock _l(mLock); + connection->writeToSocketFromCache(); + if (connection->needsWakeLock()) { + setWakeLockAcquiredLocked(true); + } +} + +void SensorService::populateActiveConnections( + SortedVector< sp<SensorEventConnection> >* activeConnections) { + Mutex::Autolock _l(mLock); + for (size_t i=0 ; i < mActiveConnections.size(); ++i) { + sp<SensorEventConnection> connection(mActiveConnections[i].promote()); + if (connection != 0) { + activeConnections->add(connection); + } } } @@ -1010,6 +1055,11 @@ bool SensorService::SensorEventConnection::needsWakeLock() { return !mDead && mWakeLockRefCount > 0; } +void SensorService::SensorEventConnection::resetWakeLockRefCount() { + Mutex::Autolock _l(mConnectionLock); + mWakeLockRefCount = 0; +} + void SensorService::SensorEventConnection::dump(String8& result) { Mutex::Autolock _l(mConnectionLock); result.appendFormat("\t WakeLockRefCount %d | uid %d | cache size %d | max cache size %d\n", @@ -1331,11 +1381,14 @@ void SensorService::SensorEventConnection::sendPendingFlushEventsLocked() { while (flushInfo.mPendingFlushEventsToSend > 0) { const int sensor_handle = mSensorInfo.keyAt(i); flushCompleteEvent.meta_data.sensor = sensor_handle; - if (mService->getSensorFromHandle(sensor_handle).isWakeUpSensor()) { + bool wakeUpSensor = mService->getSensorFromHandle(sensor_handle).isWakeUpSensor(); + if (wakeUpSensor) { + ++mWakeLockRefCount; flushCompleteEvent.flags |= WAKE_UP_SENSOR_EVENT_NEEDS_ACK; } ssize_t size = SensorEventQueue::write(mChannel, &flushCompleteEvent, 1); if (size < 0) { + if (wakeUpSensor) --mWakeLockRefCount; return; } ALOGD_IF(DEBUG_CONNECTIONS, "sent dropped flush complete event==%d ", @@ -1345,11 +1398,12 @@ void SensorService::SensorEventConnection::sendPendingFlushEventsLocked() { } } -void SensorService::SensorEventConnection::writeToSocketFromCacheLocked() { +void SensorService::SensorEventConnection::writeToSocketFromCache() { // At a time write at most half the size of the receiver buffer in SensorEventQueue OR // half the size of the socket buffer allocated in BitTube whichever is smaller. const int maxWriteSize = helpers::min(SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT/2, int(mService->mSocketBufferSize/(sizeof(sensors_event_t)*2))); + Mutex::Autolock _l(mConnectionLock); // Send pending flush complete events (if any) sendPendingFlushEventsLocked(); for (int numEventsSent = 0; numEventsSent < mCacheSize;) { @@ -1500,9 +1554,8 @@ int SensorService::SensorEventConnection::handleEvent(int fd, int events, void* } if (events & ALOOPER_EVENT_OUTPUT) { - // send sensor data that is stored in mEventCache. - Mutex::Autolock _l(mConnectionLock); - writeToSocketFromCacheLocked(); + // send sensor data that is stored in mEventCache for this connection. + mService->sendEventsFromCache(this); } return 1; } diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h index 2e16677..e9ca3a5 100644 --- a/services/sensorservice/SensorService.h +++ b/services/sensorservice/SensorService.h @@ -108,7 +108,7 @@ class SensorService : void sendPendingFlushEventsLocked(); // Writes events from mEventCache to the socket. - void writeToSocketFromCacheLocked(); + void writeToSocketFromCache(); // Compute the approximate cache size from the FIFO sizes of various sensors registered for // this connection. Wake up and non-wake up sensors have separate FIFOs but FIFO may be @@ -189,6 +189,7 @@ class SensorService : void setFirstFlushPending(int32_t handle, bool value); void dump(String8& result); bool needsWakeLock(); + void resetWakeLockRefCount(); uid_t getUid() const { return mUid; } }; @@ -237,12 +238,29 @@ class SensorService : // corresponding applications, if yes the wakelock is released. void checkWakeLockState(); void checkWakeLockStateLocked(); + bool isWakeLockAcquired(); bool isWakeUpSensorEvent(const sensors_event_t& event) const; SensorRecord * getSensorRecord(int handle); sp<Looper> getLooper() const; + // Reset mWakeLockRefCounts for all SensorEventConnections to zero. This may happen if + // SensorService did not receive any acknowledgements from apps which have registered for + // wake_up sensors. + void resetAllWakeLockRefCounts(); + + // Acquire or release wake_lock. If wake_lock is acquired, set the timeout in the looper to + // 5 seconds and wake the looper. + void setWakeLockAcquiredLocked(bool acquire); + + // Send events from the event cache for this particular connection. + void sendEventsFromCache(const sp<SensorEventConnection>& connection); + + // Promote all weak referecences in mActiveConnections vector to strong references and add them + // to the output vector. + void populateActiveConnections(SortedVector< sp<SensorEventConnection> >* activeConnections); + // constants Vector<Sensor> mSensorList; Vector<Sensor> mUserSensorListDebug; @@ -254,6 +272,7 @@ class SensorService : // supported or not. uint32_t mSocketBufferSize; sp<Looper> mLooper; + sp<SensorEventAckReceiver> mAckReceiver; // protected by mLock mutable Mutex mLock; diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index 342d685..1eb2361 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -83,8 +83,14 @@ else LOCAL_CFLAGS += -DPRESENT_TIME_OFFSET_FROM_VSYNC_NS=0 endif +ifneq ($(MAX_VIRTUAL_DISPLAY_DIMENSION),) + LOCAL_CFLAGS += -DMAX_VIRTUAL_DISPLAY_DIMENSION=$(MAX_VIRTUAL_DISPLAY_DIMENSION) +else + LOCAL_CFLAGS += -DMAX_VIRTUAL_DISPLAY_DIMENSION=0 +endif + LOCAL_CFLAGS += -fvisibility=hidden -Werror=format -LOCAL_CPPFLAGS := -std=c++11 +LOCAL_CFLAGS += -std=c++11 LOCAL_SHARED_LIBRARIES := \ libcutils \ diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp index f9d76d1..4885c5f 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp @@ -68,7 +68,7 @@ FramebufferSurface::FramebufferSurface(HWComposer& hwc, int disp, mConsumer->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS); } -status_t FramebufferSurface::beginFrame(bool /* mustRecompose */) { +status_t FramebufferSurface::beginFrame(bool /*mustRecompose*/) { return NO_ERROR; } @@ -122,7 +122,7 @@ status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& } // Overrides ConsumerBase::onFrameAvailable(), does not call base class impl. -void FramebufferSurface::onFrameAvailable() { +void FramebufferSurface::onFrameAvailable(const BufferItem& /* item */) { sp<GraphicBuffer> buf; sp<Fence> acquireFence; status_t err = nextBuffer(buf, acquireFence); diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h index 6ffc52d..3d17840 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h @@ -53,7 +53,7 @@ public: private: virtual ~FramebufferSurface() { }; // this class cannot be overloaded - virtual void onFrameAvailable(); + virtual void onFrameAvailable(const BufferItem& item); virtual void freeBufferLocked(int slotIndex); virtual void dumpLocked(String8& result, const char* prefix) const; diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp index ef10fa7..e0f32e9 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp @@ -284,7 +284,7 @@ status_t VirtualDisplaySurface::setBufferCount(int bufferCount) { } status_t VirtualDisplaySurface::dequeueBuffer(Source source, - PixelFormat format, uint32_t usage, int* sslot, sp<Fence>* fence) { + uint32_t format, uint32_t usage, int* sslot, sp<Fence>* fence) { LOG_FATAL_IF(mDisplayId < 0, "mDisplayId=%d but should not be < 0.", mDisplayId); // Don't let a slow consumer block us bool async = (source == SOURCE_SINK); @@ -329,7 +329,7 @@ status_t VirtualDisplaySurface::dequeueBuffer(Source source, } status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence, bool async, - uint32_t w, uint32_t h, PixelFormat format, uint32_t usage) { + uint32_t w, uint32_t h, uint32_t format, uint32_t usage) { if (mDisplayId < 0) return mSource[SOURCE_SINK]->dequeueBuffer(pslot, fence, async, w, h, format, usage); @@ -364,7 +364,7 @@ status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence, bool usage |= GRALLOC_USAGE_HW_COMPOSER; const sp<GraphicBuffer>& buf = mProducerBuffers[mOutputProducerSlot]; if ((usage & ~buf->getUsage()) != 0 || - (format != 0 && format != buf->getPixelFormat()) || + (format != 0 && format != (uint32_t)buf->getPixelFormat()) || (w != 0 && w != mSinkBufferWidth) || (h != 0 && h != mSinkBufferHeight)) { VDS_LOGV("dequeueBuffer: dequeueing new output buffer: " @@ -517,7 +517,7 @@ status_t VirtualDisplaySurface::setSidebandStream(const sp<NativeHandle>& /*stre } void VirtualDisplaySurface::allocateBuffers(bool /* async */, - uint32_t /* width */, uint32_t /* height */, PixelFormat /* format */, + uint32_t /* width */, uint32_t /* height */, uint32_t /* format */, uint32_t /* usage */) { // TODO: Should we actually allocate buffers for a virtual display? } diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h index 0a3f4a1..2c14d6d 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h @@ -100,7 +100,7 @@ private: virtual status_t requestBuffer(int pslot, sp<GraphicBuffer>* outBuf); virtual status_t setBufferCount(int bufferCount); virtual status_t dequeueBuffer(int* pslot, sp<Fence>* fence, bool async, - uint32_t w, uint32_t h, PixelFormat format, uint32_t usage); + uint32_t w, uint32_t h, uint32_t format, uint32_t usage); virtual status_t detachBuffer(int slot); virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence); @@ -114,13 +114,13 @@ private: virtual status_t disconnect(int api); virtual status_t setSidebandStream(const sp<NativeHandle>& stream); virtual void allocateBuffers(bool async, uint32_t width, uint32_t height, - PixelFormat format, uint32_t usage); + uint32_t format, uint32_t usage); // // Utility methods // static Source fbSourceForCompositionType(CompositionType type); - status_t dequeueBuffer(Source source, PixelFormat format, uint32_t usage, + status_t dequeueBuffer(Source source, uint32_t format, uint32_t usage, int* sslot, sp<Fence>* fence); void updateQueueBufferOutput(const QueueBufferOutput& qbo); void resetPerFrameState(); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 91e9a02..9da1efd 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -34,6 +34,7 @@ #include <ui/GraphicBuffer.h> #include <ui/PixelFormat.h> +#include <gui/BufferItem.h> #include <gui/Surface.h> #include "clz.h" @@ -158,11 +159,26 @@ void Layer::onLayerDisplayed(const sp<const DisplayDevice>& /* hw */, } } -void Layer::onFrameAvailable() { +void Layer::onFrameAvailable(const BufferItem& item) { + // Add this buffer from our internal queue tracker + { // Autolock scope + Mutex::Autolock lock(mQueueItemLock); + mQueueItems.push_back(item); + } + android_atomic_inc(&mQueuedFrames); mFlinger->signalLayerUpdate(); } +void Layer::onFrameReplaced(const BufferItem& item) { + Mutex::Autolock lock(mQueueItemLock); + if (mQueueItems.empty()) { + ALOGE("Can't replace a frame on an empty queue"); + return; + } + mQueueItems.editItemAt(0) = item; +} + void Layer::onSidebandStreamChanged() { if (android_atomic_release_cas(false, true, &mSidebandStreamChanged) == 0) { // mSidebandStreamChanged was false @@ -277,12 +293,17 @@ static Rect reduce(const Rect& win, const Region& exclude) { Rect Layer::computeBounds() const { const Layer::State& s(getDrawingState()); + return computeBounds(s.activeTransparentRegion); +} + +Rect Layer::computeBounds(const Region& activeTransparentRegion) const { + const Layer::State& s(getDrawingState()); Rect win(s.active.w, s.active.h); if (!s.active.crop.isEmpty()) { win.intersect(s.active.crop, &win); } // subtract the transparent region and snap to the bounds - return reduce(win, s.activeTransparentRegion); + return reduce(win, activeTransparentRegion); } FloatRect Layer::computeCrop(const sp<const DisplayDevice>& hw) const { @@ -310,8 +331,12 @@ FloatRect Layer::computeCrop(const sp<const DisplayDevice>& hw) const { activeCrop.intersect(hw->getViewport(), &activeCrop); activeCrop = s.transform.inverse().transform(activeCrop); - // paranoia: make sure the window-crop is constrained in the - // window's bounds + // This needs to be here as transform.transform(Rect) computes the + // transformed rect and then takes the bounding box of the result before + // returning. This means + // transform.inverse().transform(transform.transform(Rect)) != Rect + // in which case we need to make sure the final rect is clipped to the + // display bounds. activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop); // subtract the transparent region and snap to the bounds @@ -404,7 +429,29 @@ void Layer::setGeometry( // apply the layer's transform, followed by the display's global transform // here we're guaranteed that the layer's transform preserves rects - Rect frame(s.transform.transform(computeBounds())); + Region activeTransparentRegion(s.activeTransparentRegion); + if (!s.active.crop.isEmpty()) { + Rect activeCrop(s.active.crop); + activeCrop = s.transform.transform(activeCrop); + activeCrop.intersect(hw->getViewport(), &activeCrop); + activeCrop = s.transform.inverse().transform(activeCrop); + // This needs to be here as transform.transform(Rect) computes the + // transformed rect and then takes the bounding box of the result before + // returning. This means + // transform.inverse().transform(transform.transform(Rect)) != Rect + // in which case we need to make sure the final rect is clipped to the + // display bounds. + activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop); + // mark regions outside the crop as transparent + activeTransparentRegion.orSelf(Rect(0, 0, s.active.w, activeCrop.top)); + activeTransparentRegion.orSelf(Rect(0, activeCrop.bottom, + s.active.w, s.active.h)); + activeTransparentRegion.orSelf(Rect(0, activeCrop.top, + activeCrop.left, activeCrop.bottom)); + activeTransparentRegion.orSelf(Rect(activeCrop.right, activeCrop.top, + s.active.w, activeCrop.bottom)); + } + Rect frame(s.transform.transform(computeBounds(activeTransparentRegion))); frame.intersect(hw->getViewport(), &frame); const Transform& tr(hw->getTransform()); layer.setFrame(tr.transform(frame)); @@ -992,6 +1039,14 @@ bool Layer::setLayerStack(uint32_t layerStack) { // pageflip handling... // ---------------------------------------------------------------------------- +bool Layer::shouldPresentNow(const DispSync& dispSync) const { + Mutex::Autolock lock(mQueueItemLock); + nsecs_t expectedPresent = + mSurfaceFlingerConsumer->computeExpectedPresent(dispSync); + return mQueueItems.empty() ? + false : mQueueItems[0].mTimestamp < expectedPresent; +} + bool Layer::onPreComposition() { mRefreshPending = false; return mQueuedFrames > 0 || mSidebandStreamChanged; @@ -1181,6 +1236,12 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions) return outDirtyRegion; } + // Remove this buffer from our internal queue tracker + { // Autolock scope + Mutex::Autolock lock(mQueueItemLock); + mQueueItems.removeAt(0); + } + // Decrement the queued-frames count. Signal another event if we // have more frames pending. if (android_atomic_dec(&mQueuedFrames) > 1) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 2ef39e8..424c03e 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -142,6 +142,7 @@ public: void computeGeometry(const sp<const DisplayDevice>& hw, Mesh& mesh, bool useIdentityTransform) const; + Rect computeBounds(const Region& activeTransparentRegion) const; Rect computeBounds() const; sp<IBinder> getHandle(); @@ -209,6 +210,8 @@ public: void onLayerDisplayed(const sp<const DisplayDevice>& hw, HWComposer::HWCLayerInterface* layer); + bool shouldPresentNow(const DispSync& dispSync) const; + /* * called before composition. * returns true if the layer has pending updates. @@ -329,7 +332,8 @@ protected: private: // Interface implementation for SurfaceFlingerConsumer::ContentsChangedListener - virtual void onFrameAvailable(); + virtual void onFrameAvailable(const BufferItem& item); + virtual void onFrameReplaced(const BufferItem& item); virtual void onSidebandStreamChanged(); void commitTransaction(); @@ -402,6 +406,10 @@ private: // This layer can be a cursor on some displays. bool mPotentialCursor; + + // Local copy of the queued contents of the incoming BufferQueue + mutable Mutex mQueueItemLock; + Vector<BufferItem> mQueueItems; }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/LayerDim.h b/services/surfaceflinger/LayerDim.h index 60edd91..a0cfca9 100644 --- a/services/surfaceflinger/LayerDim.h +++ b/services/surfaceflinger/LayerDim.h @@ -28,7 +28,7 @@ namespace android { class LayerDim : public Layer { -public: +public: LayerDim(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags); virtual ~LayerDim(); @@ -36,8 +36,7 @@ public: virtual const char* getTypeId() const { return "LayerDim"; } virtual void onDraw(const sp<const DisplayDevice>& hw, const Region& clip, bool useIdentityTransform) const; - using Layer::isOpaque; - virtual bool isOpaque() const { return false; } + virtual bool isOpaque(const Layer::State&) const { return false; } virtual bool isSecure() const { return false; } virtual bool isFixedSize() const { return true; } virtual bool isVisible() const; diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp index e4e7d42..37a044e 100644 --- a/services/surfaceflinger/MonitoredProducer.cpp +++ b/services/surfaceflinger/MonitoredProducer.cpp @@ -61,7 +61,7 @@ status_t MonitoredProducer::setBufferCount(int bufferCount) { } status_t MonitoredProducer::dequeueBuffer(int* slot, sp<Fence>* fence, - bool async, uint32_t w, uint32_t h, PixelFormat format, uint32_t usage) { + bool async, uint32_t w, uint32_t h, uint32_t format, uint32_t usage) { return mProducer->dequeueBuffer(slot, fence, async, w, h, format, usage); } @@ -106,7 +106,7 @@ status_t MonitoredProducer::setSidebandStream(const sp<NativeHandle>& stream) { } void MonitoredProducer::allocateBuffers(bool async, uint32_t width, - uint32_t height, PixelFormat format, uint32_t usage) { + uint32_t height, uint32_t format, uint32_t usage) { mProducer->allocateBuffers(async, width, height, format, usage); } diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h index aec3e85..f6ccc51 100644 --- a/services/surfaceflinger/MonitoredProducer.h +++ b/services/surfaceflinger/MonitoredProducer.h @@ -37,7 +37,7 @@ public: virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf); virtual status_t setBufferCount(int bufferCount); virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, bool async, - uint32_t w, uint32_t h, PixelFormat format, uint32_t usage); + uint32_t w, uint32_t h, uint32_t format, uint32_t usage); virtual status_t detachBuffer(int slot); virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence); @@ -52,7 +52,7 @@ public: virtual status_t disconnect(int api); virtual status_t setSidebandStream(const sp<NativeHandle>& stream); virtual void allocateBuffers(bool async, uint32_t width, uint32_t height, - PixelFormat format, uint32_t usage); + uint32_t format, uint32_t usage); virtual IBinder* onAsBinder(); private: diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp index 767b714..7cd42e4 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp @@ -219,6 +219,10 @@ void RenderEngine::fillRegionWithColor(const Region& region, uint32_t height, drawMesh(mesh); } +void RenderEngine::flush() { + glFlush(); +} + void RenderEngine::clearWithColor(float red, float green, float blue, float alpha) { glClearColor(red, green, blue, alpha); glClear(GL_COLOR_BUFFER_BIT); diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h index acbff9b..8d7529c 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/RenderEngine.h @@ -67,6 +67,7 @@ public: virtual void dump(String8& result); // helpers + void flush(); void clearWithColor(float red, float green, float blue, float alpha); void fillRegionWithColor(const Region& region, uint32_t height, float red, float green, float blue, float alpha); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 6a5a39e..3419295 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -506,6 +506,9 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display, return BAD_VALUE; } + if (!display.get()) + return NAME_NOT_FOUND; + int32_t type = NAME_NOT_FOUND; for (int i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) { if (display == mBuiltinDisplays[i]) { @@ -652,7 +655,7 @@ status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& display, int mode) { virtual bool handler() { Vector<DisplayInfo> configs; mFlinger.getDisplayConfigs(mDisplay, &configs); - if(mMode < 0 || static_cast<size_t>(mMode) >= configs.size()) { + if (mMode < 0 || mMode >= static_cast<int>(configs.size())) { ALOGE("Attempt to set active config = %d for display with %zu configs", mMode, configs.size()); } @@ -825,30 +828,41 @@ void SurfaceFlinger::eventControl(int disp, int event, int enabled) { void SurfaceFlinger::onMessageReceived(int32_t what) { ATRACE_CALL(); switch (what) { - case MessageQueue::TRANSACTION: - handleMessageTransaction(); - break; - case MessageQueue::INVALIDATE: - handleMessageTransaction(); - handleMessageInvalidate(); - signalRefresh(); - break; - case MessageQueue::REFRESH: - handleMessageRefresh(); - break; + case MessageQueue::TRANSACTION: { + handleMessageTransaction(); + break; + } + case MessageQueue::INVALIDATE: { + bool refreshNeeded = handleMessageTransaction(); + refreshNeeded |= handleMessageInvalidate(); + refreshNeeded |= mRepaintEverything; + if (refreshNeeded) { + // Signal a refresh if a transaction modified the window state, + // a new buffer was latched, or if HWC has requested a full + // repaint + signalRefresh(); + } + break; + } + case MessageQueue::REFRESH: { + handleMessageRefresh(); + break; + } } } -void SurfaceFlinger::handleMessageTransaction() { +bool SurfaceFlinger::handleMessageTransaction() { uint32_t transactionFlags = peekTransactionFlags(eTransactionMask); if (transactionFlags) { handleTransaction(transactionFlags); + return true; } + return false; } -void SurfaceFlinger::handleMessageInvalidate() { +bool SurfaceFlinger::handleMessageInvalidate() { ATRACE_CALL(); - handlePageFlip(); + return handlePageFlip(); } void SurfaceFlinger::handleMessageRefresh() { @@ -1329,7 +1343,22 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) // etc.) but no internal state (i.e. a DisplayDevice). if (state.surface != NULL) { - hwcDisplayId = allocateHwcDisplayId(state.type); + int width = 0; + int status = state.surface->query( + NATIVE_WINDOW_WIDTH, &width); + ALOGE_IF(status != NO_ERROR, + "Unable to query width (%d)", status); + int height = 0; + status = state.surface->query( + NATIVE_WINDOW_HEIGHT, &height); + ALOGE_IF(status != NO_ERROR, + "Unable to query height (%d)", status); + if (MAX_VIRTUAL_DISPLAY_DIMENSION == 0 || + (width <= MAX_VIRTUAL_DISPLAY_DIMENSION && + height <= MAX_VIRTUAL_DISPLAY_DIMENSION)) { + hwcDisplayId = allocateHwcDisplayId(state.type); + } + sp<VirtualDisplaySurface> vds = new VirtualDisplaySurface( *mHwc, hwcDisplayId, state.surface, bqProducer, bqConsumer, state.displayName); @@ -1668,12 +1697,13 @@ void SurfaceFlinger::invalidateLayerStack(uint32_t layerStack, } } -void SurfaceFlinger::handlePageFlip() +bool SurfaceFlinger::handlePageFlip() { Region dirtyRegion; bool visibleRegions = false; const LayerVector& layers(mDrawingState.layersSortedByZ); + bool frameQueued = false; // Store the set of layers that need updates. This set must not change as // buffers are being latched, as this could result in a deadlock. @@ -1687,8 +1717,12 @@ void SurfaceFlinger::handlePageFlip() Vector<Layer*> layersWithQueuedFrames; for (size_t i = 0, count = layers.size(); i<count ; i++) { const sp<Layer>& layer(layers[i]); - if (layer->hasQueuedFrame()) - layersWithQueuedFrames.push_back(layer.get()); + if (layer->hasQueuedFrame()) { + frameQueued = true; + if (layer->shouldPresentNow(mPrimaryDispSync)) { + layersWithQueuedFrames.push_back(layer.get()); + } + } } for (size_t i = 0, count = layersWithQueuedFrames.size() ; i<count ; i++) { Layer* layer = layersWithQueuedFrames[i]; @@ -1698,6 +1732,16 @@ void SurfaceFlinger::handlePageFlip() } mVisibleRegionsDirty |= visibleRegions; + + // If we will need to wake up at some time in the future to deal with a + // queued frame that shouldn't be displayed during this vsync period, wake + // up during the next vsync period to check again. + if (frameQueued && layersWithQueuedFrames.empty()) { + signalLayerUpdate(); + } + + // Only continue with the refresh if there is actually new work to do + return !layersWithQueuedFrames.empty(); } void SurfaceFlinger::invalidateHwcGeometry() @@ -3200,6 +3244,8 @@ status_t SurfaceFlinger::captureScreenImplLocked( EGLSyncKHR sync; if (!DEBUG_SCREENSHOTS) { sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL); + // native fence fd will not be populated until flush() is done. + getRenderEngine().flush(); } else { sync = EGL_NO_SYNC_KHR; } @@ -3246,10 +3292,8 @@ status_t SurfaceFlinger::captureScreenImplLocked( } else { result = BAD_VALUE; } + // queueBuffer takes ownership of syncFd window->queueBuffer(window, buffer, syncFd); - if (syncFd != -1) { - close(syncFd); - } } } else { result = BAD_VALUE; diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 710dac7..4deb815 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -247,8 +247,12 @@ private: // called on the main thread in response to setPowerMode() void setPowerModeInternal(const sp<DisplayDevice>& hw, int mode); - void handleMessageTransaction(); - void handleMessageInvalidate(); + // Returns whether the transaction actually modified any state + bool handleMessageTransaction(); + + // Returns whether a new buffer has been latched (see handlePageFlip()) + bool handleMessageInvalidate(); + void handleMessageRefresh(); void handleTransaction(uint32_t transactionFlags); @@ -256,10 +260,11 @@ private: void updateCursorAsync(); - /* handlePageFilp: this is were we latch a new buffer - * if available and compute the dirty region. + /* handlePageFlip - latch a new buffer if available and compute the dirty + * region. Returns whether a new buffer has been latched, i.e., whether it + * is necessary to perform a refresh during this vsync. */ - void handlePageFlip(); + bool handlePageFlip(); /* ------------------------------------------------------------------------ * Transactions diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.h b/services/surfaceflinger/SurfaceFlingerConsumer.h index 5633980..28f2f6a 100644 --- a/services/surfaceflinger/SurfaceFlingerConsumer.h +++ b/services/surfaceflinger/SurfaceFlingerConsumer.h @@ -67,9 +67,9 @@ public: sp<NativeHandle> getSidebandStream() const; -private: nsecs_t computeExpectedPresent(const DispSync& dispSync); +private: virtual void onSidebandStreamChanged(); wp<ContentsChangedListener> mContentsChangedListener; diff --git a/services/surfaceflinger/Transform.cpp b/services/surfaceflinger/Transform.cpp index 3456abf..35e7e7d 100644 --- a/services/surfaceflinger/Transform.cpp +++ b/services/surfaceflinger/Transform.cpp @@ -301,16 +301,16 @@ Transform Transform::inverse() const { // (T*M)^-1 = M^-1 * T^-1 Transform result; if (mType <= TRANSLATE) { - // 1 0 x - // 0 1 y - // 0 0 1 + // 1 0 0 + // 0 1 0 + // x y 1 result = *this; result.mMatrix[2][0] = -result.mMatrix[2][0]; result.mMatrix[2][1] = -result.mMatrix[2][1]; } else { - // a c x - // b d y - // 0 0 1 + // a c 0 + // b d 0 + // x y 1 const mat33& M(mMatrix); const float a = M[0][0]; const float b = M[1][0]; @@ -319,16 +319,17 @@ Transform Transform::inverse() const { const float x = M[2][0]; const float y = M[2][1]; - Transform R, T; const float idet = 1.0 / (a*d - b*c); - R.mMatrix[0][0] = d*idet; R.mMatrix[0][1] = -c*idet; - R.mMatrix[1][0] = -b*idet; R.mMatrix[1][1] = a*idet; - R.mType = mType &= ~TRANSLATE; - - T.mMatrix[2][0] = -x; - T.mMatrix[2][1] = -y; - T.mType = TRANSLATE; - result = R * T; + result.mMatrix[0][0] = d*idet; + result.mMatrix[0][1] = -c*idet; + result.mMatrix[1][0] = -b*idet; + result.mMatrix[1][1] = a*idet; + result.mType = mType; + + vec2 T(-x, -y); + T = result.transform(T); + result.mMatrix[2][0] = T[0]; + result.mMatrix[2][1] = T[1]; } return result; } |