diff options
Diffstat (limited to 'services')
-rw-r--r-- | services/sensorservice/SensorService.cpp | 95 | ||||
-rw-r--r-- | services/sensorservice/SensorService.h | 4 | ||||
-rw-r--r-- | services/surfaceflinger/DispSync.cpp | 46 | ||||
-rw-r--r-- | services/surfaceflinger/DispSync.h | 3 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayDevice.cpp | 4 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayDevice.h | 4 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayHardware/DisplaySurface.h | 4 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp | 2 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayHardware/FramebufferSurface.h | 2 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp | 35 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h | 4 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.cpp | 22 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.h | 7 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 28 | ||||
-rw-r--r-- | services/surfaceflinger/main_surfaceflinger.cpp | 2 |
15 files changed, 206 insertions, 56 deletions
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp index 6df6315..148f404 100644 --- a/services/sensorservice/SensorService.cpp +++ b/services/sensorservice/SensorService.cpp @@ -206,7 +206,7 @@ status_t SensorService::dump(int fd, const Vector<String16>& /*args*/) String8 result; if (!PermissionCache::checkCallingPermission(sDump)) { result.appendFormat("Permission Denial: " - "can't dump SurfaceFlinger from pid=%d, uid=%d\n", + "can't dump SensorService from pid=%d, uid=%d\n", IPCThreadState::self()->getCallingPid(), IPCThreadState::self()->getCallingUid()); } else { @@ -216,21 +216,24 @@ status_t SensorService::dump(int fd, const Vector<String16>& /*args*/) const Sensor& s(mSensorList[i]); const sensors_event_t& e(mLastEventSeen.valueFor(s.getHandle())); result.appendFormat( - "%-48s| %-32s | 0x%08x | ", + "%-48s| %-32s| %-48s| 0x%08x | \"%s\"\n\t", s.getName().string(), s.getVendor().string(), - s.getHandle()); + s.getStringType().string(), + s.getHandle(), + s.getRequiredPermission().string()); if (s.getMinDelay() > 0) { result.appendFormat( - "maxRate=%7.2fHz | ", 1e6f / s.getMinDelay()); + "maxRate=%7.2fHz | ", 1e6f / s.getMinDelay()); } else { result.append(s.getMinDelay() == 0 ? "on-demand | " : "one-shot | "); } if (s.getFifoMaxEventCount() > 0) { - result.appendFormat("getFifoMaxEventCount=%d events | ", s.getFifoMaxEventCount()); + result.appendFormat("FifoMax=%d events | ", + s.getFifoMaxEventCount()); } else { result.append("no batching support | "); } @@ -491,10 +494,23 @@ Vector<Sensor> SensorService::getSensorList() { char value[PROPERTY_VALUE_MAX]; property_get("debug.sensors", value, "0"); - if (atoi(value)) { - return mUserSensorListDebug; + const Vector<Sensor>& initialSensorList = (atoi(value)) ? + mUserSensorListDebug : mUserSensorList; + Vector<Sensor> accessibleSensorList; + for (size_t i = 0; i < initialSensorList.size(); i++) { + Sensor sensor = initialSensorList[i]; + if (canAccessSensor(sensor)) { + accessibleSensorList.add(sensor); + } else { + String8 infoMessage; + infoMessage.appendFormat( + "Skipped sensor %s because it requires permission %s", + sensor.getName().string(), + sensor.getRequiredPermission().string()); + ALOGI(infoMessage.string()); + } } - return mUserSensorList; + return accessibleSensorList; } sp<ISensorEventConnection> SensorService::createSensorEventConnection() @@ -540,6 +556,10 @@ void SensorService::cleanupConnection(SensorEventConnection* c) BatteryService::cleanup(c->getUid()); } +Sensor SensorService::getSensorFromHandle(int handle) const { + return mSensorMap.valueFor(handle)->getSensor(); +} + status_t SensorService::enable(const sp<SensorEventConnection>& connection, int handle, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs, int reservedFlags) { @@ -550,6 +570,11 @@ status_t SensorService::enable(const sp<SensorEventConnection>& connection, if (sensor == NULL) { return BAD_VALUE; } + + if (!verifyCanAccessSensor(sensor->getSensor(), "Tried enabling")) { + return BAD_VALUE; + } + Mutex::Autolock _l(mLock); SensorRecord* rec = mActiveSensors.valueFor(handle); if (rec == 0) { @@ -671,6 +696,10 @@ status_t SensorService::setEventRate(const sp<SensorEventConnection>& connection if (!sensor) return BAD_VALUE; + if (!verifyCanAccessSensor(sensor->getSensor(), "Tried configuring")) { + return BAD_VALUE; + } + if (ns < 0) return BAD_VALUE; @@ -684,17 +713,44 @@ status_t SensorService::setEventRate(const sp<SensorEventConnection>& connection status_t SensorService::flushSensor(const sp<SensorEventConnection>& connection, int handle) { - if (mInitCheck != NO_ERROR) return mInitCheck; - SensorInterface* sensor = mSensorMap.valueFor(handle); - if (sensor == NULL) { - return BAD_VALUE; - } - if (sensor->getSensor().getType() == SENSOR_TYPE_SIGNIFICANT_MOTION) { - ALOGE("flush called on Significant Motion sensor"); - return INVALID_OPERATION; - } - return sensor->flush(connection.get(), handle); + if (mInitCheck != NO_ERROR) return mInitCheck; + SensorInterface* sensor = mSensorMap.valueFor(handle); + if (sensor == NULL) { + return BAD_VALUE; + } + + if (!verifyCanAccessSensor(sensor->getSensor(), "Tried flushing")) { + return BAD_VALUE; + } + + if (sensor->getSensor().getType() == SENSOR_TYPE_SIGNIFICANT_MOTION) { + ALOGE("flush called on Significant Motion sensor"); + return INVALID_OPERATION; + } + return sensor->flush(connection.get(), handle); +} + + +bool SensorService::canAccessSensor(const Sensor& sensor) { + String16 permissionString(sensor.getRequiredPermission()); + return permissionString.size() == 0 || + PermissionCache::checkCallingPermission(permissionString); } + +bool SensorService::verifyCanAccessSensor(const Sensor& sensor, const char* operation) { + if (canAccessSensor(sensor)) { + return true; + } else { + String8 errorMessage; + errorMessage.appendFormat( + "%s a sensor (%s) without holding its required permission: %s", + operation, + sensor.getName().string(), + sensor.getRequiredPermission().string()); + return false; + } +} + // --------------------------------------------------------------------------- SensorService::SensorRecord::SensorRecord( @@ -762,6 +818,9 @@ void SensorService::SensorEventConnection::dump(String8& result) { bool SensorService::SensorEventConnection::addSensor(int32_t handle) { Mutex::Autolock _l(mConnectionLock); + if (!verifyCanAccessSensor(mService->getSensorFromHandle(handle), "Tried adding")) { + return false; + } if (mSensorInfo.indexOfKey(handle) < 0) { mSensorInfo.add(handle, FlushInfo()); return true; diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h index 1dc2dd3..e88ffc8 100644 --- a/services/sensorservice/SensorService.h +++ b/services/sensorservice/SensorService.h @@ -131,6 +131,7 @@ class SensorService : String8 getSensorName(int handle) const; bool isVirtualSensor(int handle) const; + Sensor getSensorFromHandle(int handle) const; void recordLastValue(const sensors_event_t* buffer, size_t count); static void sortEventBuffer(sensors_event_t* buffer, size_t count); Sensor registerSensor(SensorInterface* sensor); @@ -141,7 +142,8 @@ class SensorService : const sp<SensorEventConnection>& connection, int handle); void cleanupAutoDisabledSensor(const sp<SensorEventConnection>& connection, sensors_event_t const* buffer, const int count); - + static bool canAccessSensor(const Sensor& sensor); + static bool verifyCanAccessSensor(const Sensor& sensor, const char* operation); // constants Vector<Sensor> mSensorList; Vector<Sensor> mUserSensorListDebug; diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp index 602f20a..95839b7 100644 --- a/services/surfaceflinger/DispSync.cpp +++ b/services/surfaceflinger/DispSync.cpp @@ -20,6 +20,7 @@ #define __STDC_LIMIT_MACROS #include <math.h> +#include <inttypes.h> #include <cutils/log.h> @@ -487,4 +488,49 @@ void DispSync::resetErrorLocked() { } } +void DispSync::dump(String8& result) const { + Mutex::Autolock lock(mMutex); + result.appendFormat("mPeriod: %"PRId64" ns\n", mPeriod); + result.appendFormat("mPhase: %"PRId64" ns\n", mPhase); + result.appendFormat("mError: %"PRId64" ns (sqrt: %.1f)\n", + mError, sqrt(mError)); + result.appendFormat("mNumResyncSamplesSincePresent: %d (max %d)\n", + mNumResyncSamplesSincePresent, MAX_RESYNC_SAMPLES_WITHOUT_PRESENT); + result.appendFormat("mNumResyncSamples: %d (max %d)\n", + mNumResyncSamples, MAX_RESYNC_SAMPLES); + + result.appendFormat("mResyncSamples:\n"); + nsecs_t previous = -1; + for (size_t i = 0; i < mNumResyncSamples; i++) { + size_t idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES; + nsecs_t sampleTime = mResyncSamples[idx]; + if (i == 0) { + result.appendFormat(" %"PRId64"\n", sampleTime); + } else { + result.appendFormat(" %"PRId64" (+%"PRId64")\n", + sampleTime, sampleTime - previous); + } + previous = sampleTime; + } + + result.appendFormat("mPresentFences / mPresentTimes [%d]:\n", + NUM_PRESENT_SAMPLES); + previous = 0; + for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) { + size_t idx = (i + mPresentSampleOffset) % NUM_PRESENT_SAMPLES; + bool signaled = mPresentFences[idx] == NULL; + nsecs_t presentTime = mPresentTimes[idx]; + if (!signaled) { + result.appendFormat(" [unsignaled fence]\n"); + } else if (previous == 0) { + result.appendFormat(" %"PRId64"\n", presentTime); + } else { + result.appendFormat(" %"PRId64" (+%"PRId64" / %.3f)\n", + presentTime, presentTime - previous, + (presentTime - previous) / (double) mPeriod); + } + previous = presentTime; + } +} + } // namespace android diff --git a/services/surfaceflinger/DispSync.h b/services/surfaceflinger/DispSync.h index c4280aa..19eb3e5 100644 --- a/services/surfaceflinger/DispSync.h +++ b/services/surfaceflinger/DispSync.h @@ -99,6 +99,9 @@ public: // DispSync object. status_t removeEventListener(const sp<Callback>& callback); + // dump appends human-readable debug info to the result string. + void dump(String8& result) const; + private: void updateModelLocked(); diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index a1430b9..f9034a6 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -199,8 +199,8 @@ void DisplayDevice::flip(const Region& dirty) const mPageFlipCount++; } -status_t DisplayDevice::beginFrame() const { - return mDisplaySurface->beginFrame(); +status_t DisplayDevice::beginFrame(bool mustRecompose) const { + return mDisplaySurface->beginFrame(mustRecompose); } status_t DisplayDevice::prepareFrame(const HWComposer& hwc) const { diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 01a9d2e..f750c6c 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -124,7 +124,9 @@ public: int32_t getHwcDisplayId() const { return mHwcDisplayId; } const wp<IBinder>& getDisplayToken() const { return mDisplayToken; } - status_t beginFrame() const; + // We pass in mustRecompose so we can keep VirtualDisplaySurface's state + // machine happy without actually queueing a buffer if nothing has changed + status_t beginFrame(bool mustRecompose) const; status_t prepareFrame(const HWComposer& hwc) const; void swapBuffers(HWComposer& hwc) const; diff --git a/services/surfaceflinger/DisplayHardware/DisplaySurface.h b/services/surfaceflinger/DisplayHardware/DisplaySurface.h index 48bf3f2..1db3eb8 100644 --- a/services/surfaceflinger/DisplayHardware/DisplaySurface.h +++ b/services/surfaceflinger/DisplayHardware/DisplaySurface.h @@ -33,7 +33,9 @@ public: // beginFrame is called at the beginning of the composition loop, before // the configuration is known. The DisplaySurface should do anything it // needs to do to enable HWComposer to decide how to compose the frame. - virtual status_t beginFrame() = 0; + // We pass in mustRecompose so we can keep VirtualDisplaySurface's state + // machine happy without actually queueing a buffer if nothing has changed. + virtual status_t beginFrame(bool mustRecompose) = 0; // prepareFrame is called after the composition configuration is known but // before composition takes place. The DisplaySurface can use the diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp index 7d4b196..086ccf8 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() { +status_t FramebufferSurface::beginFrame(bool mustRecompose) { return NO_ERROR; } diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h index 1d67446..ba72ce3 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h @@ -39,7 +39,7 @@ class FramebufferSurface : public ConsumerBase, public: FramebufferSurface(HWComposer& hwc, int disp, const sp<IGraphicBufferConsumer>& consumer); - virtual status_t beginFrame(); + virtual status_t beginFrame(bool mustRecompose); virtual status_t prepareFrame(CompositionType compositionType); virtual status_t compositionComplete(); virtual status_t advanceFrame(); diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp index d7fef8c..a1820ab 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp @@ -56,7 +56,8 @@ VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId, mOutputUsage(GRALLOC_USAGE_HW_COMPOSER), mProducerSlotSource(0), mDbgState(DBG_STATE_IDLE), - mDbgLastCompositionType(COMPOSITION_UNKNOWN) + mDbgLastCompositionType(COMPOSITION_UNKNOWN), + mMustRecompose(false) { mSource[SOURCE_SINK] = sink; mSource[SOURCE_SCRATCH] = bq; @@ -92,10 +93,12 @@ VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId, VirtualDisplaySurface::~VirtualDisplaySurface() { } -status_t VirtualDisplaySurface::beginFrame() { +status_t VirtualDisplaySurface::beginFrame(bool mustRecompose) { if (mDisplayId < 0) return NO_ERROR; + mMustRecompose = mustRecompose; + VDS_LOGW_IF(mDbgState != DBG_STATE_IDLE, "Unexpected beginFrame() in %s state", dbgStateStr()); mDbgState = DBG_STATE_BEGUN; @@ -228,16 +231,24 @@ void VirtualDisplaySurface::onFrameCommitted() { QueueBufferOutput qbo; sp<Fence> outFence = mHwc.getLastRetireFence(mDisplayId); VDS_LOGV("onFrameCommitted: queue sink sslot=%d", sslot); - status_t result = mSource[SOURCE_SINK]->queueBuffer(sslot, - QueueBufferInput( - systemTime(), false /* isAutoTimestamp */, - Rect(mSinkBufferWidth, mSinkBufferHeight), - NATIVE_WINDOW_SCALING_MODE_FREEZE, 0 /* transform */, - true /* async*/, - outFence), - &qbo); - if (result == NO_ERROR) { - updateQueueBufferOutput(qbo); + if (mMustRecompose) { + status_t result = mSource[SOURCE_SINK]->queueBuffer(sslot, + QueueBufferInput( + systemTime(), false /* isAutoTimestamp */, + Rect(mSinkBufferWidth, mSinkBufferHeight), + NATIVE_WINDOW_SCALING_MODE_FREEZE, 0 /* transform */, + true /* async*/, + outFence), + &qbo); + if (result == NO_ERROR) { + updateQueueBufferOutput(qbo); + } + } else { + // If the surface hadn't actually been updated, then we only went + // through the motions of updating the display to keep our state + // machine happy. We cancel the buffer to avoid triggering another + // re-composition and causing an infinite loop. + mSource[SOURCE_SINK]->cancelBuffer(sslot, outFence); } } diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h index 1e85ac4..6899904 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h @@ -79,7 +79,7 @@ public: // // DisplaySurface interface // - virtual status_t beginFrame(); + virtual status_t beginFrame(bool mustRecompose); virtual status_t prepareFrame(CompositionType compositionType); virtual status_t compositionComplete(); virtual status_t advanceFrame(); @@ -222,6 +222,8 @@ private: const char* dbgStateStr() const; static const char* dbgSourceStr(Source s); + + bool mMustRecompose; }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 61af51f..fcc9d78 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -64,7 +64,6 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, mName("unnamed"), mDebug(false), mFormat(PIXEL_FORMAT_NONE), - mOpaqueLayer(true), mTransactionFlags(0), mQueuedFrames(0), mCurrentTransform(0), @@ -86,7 +85,9 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, uint32_t layerFlags = 0; if (flags & ISurfaceComposerClient::eHidden) - layerFlags = layer_state_t::eLayerHidden; + layerFlags |= layer_state_t::eLayerHidden; + if (flags & ISurfaceComposerClient::eOpaque) + layerFlags |= layer_state_t::eLayerOpaque; if (flags & ISurfaceComposerClient::eNonPremultiplied) mPremultipliedAlpha = false; @@ -189,7 +190,6 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h, mSecure = (flags & ISurfaceComposerClient::eSecure) ? true : false; mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false; - mOpaqueLayer = (flags & ISurfaceComposerClient::eOpaque); mCurrentOpacity = getOpacityForFormat(format); mSurfaceFlingerConsumer->setDefaultBufferSize(w, h); @@ -352,7 +352,7 @@ void Layer::setGeometry( // this gives us only the "orientation" component of the transform const State& s(getDrawingState()); - if (!isOpaque() || s.alpha != 0xFF) { + if (!isOpaque(s) || s.alpha != 0xFF) { layer.setBlending(mPremultipliedAlpha ? HWC_BLENDING_PREMULT : HWC_BLENDING_COVERAGE); @@ -596,7 +596,7 @@ void Layer::drawWithOpenGL( texCoords[3] = vec2(right, 1.0f - top); RenderEngine& engine(mFlinger->getRenderEngine()); - engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(), s.alpha); + engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), s.alpha); engine.drawMesh(mMesh); engine.disableBlending(); } @@ -656,7 +656,7 @@ void Layer::computeGeometry(const sp<const DisplayDevice>& hw, Mesh& mesh) const } } -bool Layer::isOpaque() const +bool Layer::isOpaque(const Layer::State& s) const { // if we don't have a buffer yet, we're translucent regardless of the // layer's opaque flag. @@ -666,7 +666,7 @@ bool Layer::isOpaque() const // if the layer has the opaque flag, then we're always opaque, // otherwise we use the current buffer's format. - return mOpaqueLayer || mCurrentOpacity; + return ((s.flags & layer_state_t::eLayerOpaque) != 0) || mCurrentOpacity; } bool Layer::isProtected() const @@ -954,7 +954,8 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions) } // Capture the old state of the layer for comparisons later - const bool oldOpacity = isOpaque(); + const State& s(getDrawingState()); + const bool oldOpacity = isOpaque(s); sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer; struct Reject : public SurfaceFlingerConsumer::BufferRejecter { @@ -1122,12 +1123,11 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions) } mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format); - if (oldOpacity != isOpaque()) { + if (oldOpacity != isOpaque(s)) { recomputeVisibleRegions = true; } // FIXME: postedRegion should be dirty & bounds - const Layer::State& s(getDrawingState()); Region dirtyRegion(Rect(s.active.w, s.active.h)); // transform the dirty region to window-manager space @@ -1188,7 +1188,7 @@ void Layer::dump(String8& result, Colorizer& colorizer) const s.layerStack, s.z, s.transform.tx(), s.transform.ty(), s.active.w, s.active.h, s.active.crop.left, s.active.crop.top, s.active.crop.right, s.active.crop.bottom, - isOpaque(), contentDirty, + isOpaque(s), contentDirty, s.alpha, s.flags, s.transform[0][0], s.transform[0][1], s.transform[1][0], s.transform[1][1], diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index ef4a7e9..ea65ded 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -149,8 +149,12 @@ public: /* * isOpaque - true if this surface is opaque + * + * This takes into account the buffer format (i.e. whether or not the + * pixel format includes an alpha channel) and the "opaque" flag set + * on the layer. It does not examine the current plane alpha value. */ - virtual bool isOpaque() const; + virtual bool isOpaque(const Layer::State& s) const; /* * isSecure - true if this surface is secure, that is if it prevents @@ -335,7 +339,6 @@ private: String8 mName; mutable bool mDebug; PixelFormat mFormat; - bool mOpaqueLayer; // these are protected by an external lock State mCurrentState; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 943ed02..94bef9a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -882,7 +882,9 @@ void SurfaceFlinger::rebuildLayerStacks() { void SurfaceFlinger::setUpHWComposer() { for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) { - mDisplays[dpy]->beginFrame(); + bool mustRecompose = + !(mDisplays[dpy]->getDirtyRegion(false).isEmpty()); + mDisplays[dpy]->beginFrame(mustRecompose); } HWComposer& hwc(getHwComposer()); @@ -1380,7 +1382,7 @@ void SurfaceFlinger::computeVisibleRegions( // handle hidden surfaces by setting the visible region to empty if (CC_LIKELY(layer->isVisible())) { - const bool translucent = !layer->isOpaque(); + const bool translucent = !layer->isOpaque(s); Rect bounds(s.transform.transform(layer->computeBounds())); visibleRegion.set(bounds); if (!visibleRegion.isEmpty()) { @@ -1500,6 +1502,15 @@ void SurfaceFlinger::invalidateHwcGeometry() void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& hw, const Region& inDirtyRegion) { + // We only need to actually compose the display if: + // 1) It is being handled by hardware composer, which may need this to + // keep its virtual display state machine in sync, or + // 2) There is work to be done (the dirty region isn't empty) + bool isHwcDisplay = hw->getHwcDisplayId() >= 0; + if (!isHwcDisplay && inDirtyRegion.isEmpty()) { + return; + } + Region dirtyRegion(inDirtyRegion); // compute the invalid region @@ -1625,7 +1636,7 @@ void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const const Layer::State& state(layer->getDrawingState()); if ((cur->getHints() & HWC_HINT_CLEAR_FB) && i - && layer->isOpaque() && (state.alpha == 0xFF) + && layer->isOpaque(state) && (state.alpha == 0xFF) && hasGlesComposition) { // never clear the very first layer since we're // guaranteed the FB is already cleared @@ -1869,7 +1880,9 @@ uint32_t SurfaceFlinger::setClientStateLocked( if (layer->setTransparentRegionHint(s.transparentRegion)) flags |= eTraversalNeeded; } - if (what & layer_state_t::eVisibilityChanged) { + if ((what & layer_state_t::eVisibilityChanged) || + (what & layer_state_t::eOpacityChanged)) { + // TODO: should we just use an eFlagsChanged for this? if (layer->setFlags(s.flags, s.mask)) flags |= eTraversalNeeded; } @@ -2189,6 +2202,13 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) clearStatsLocked(args, index, result); dumpAll = false; } + + if ((index < numArgs) && + (args[index] == String16("--dispsync"))) { + index++; + mPrimaryDispSync.dump(result); + dumpAll = false; + } } if (dumpAll) { diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp index b161480..90e3f7d 100644 --- a/services/surfaceflinger/main_surfaceflinger.cpp +++ b/services/surfaceflinger/main_surfaceflinger.cpp @@ -27,7 +27,7 @@ using namespace android; -int main(int argc, char** argv) { +int main(int, char**) { // When SF is launched in its own process, limit the number of // binder threads to 4. ProcessState::self()->setThreadPoolMaxThreadCount(4); |