diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h index 1581084fd..9f1937b57 100644 --- a/include/gui/ISurfaceComposer.h +++ b/include/gui/ISurfaceComposer.h @@ -104,15 +104,11 @@ public: virtual bool authenticateSurfaceTexture( const sp& surface) const = 0; - /* triggers screen off and waits for it to complete + /* set display power mode. depending on the mode, it can either trigger + * screen on, off or low power mode and wait for it to complete. * requires ACCESS_SURFACE_FLINGER permission. */ - virtual void blank(const sp& display) = 0; - - /* triggers screen on and waits for it to complete - * requires ACCESS_SURFACE_FLINGER permission. - */ - virtual void unblank(const sp& display) = 0; + virtual void setPowerMode(const sp& display, int mode) = 0; /* returns information for each configuration of the given display * intended to be used to get information about built-in displays */ @@ -165,15 +161,14 @@ public: GET_BUILT_IN_DISPLAY, SET_TRANSACTION_STATE, AUTHENTICATE_SURFACE, - BLANK, - UNBLANK, GET_DISPLAY_CONFIGS, GET_ACTIVE_CONFIG, SET_ACTIVE_CONFIG, CONNECT_DISPLAY, CAPTURE_SCREEN, CLEAR_ANIMATION_FRAME_STATS, - GET_ANIMATION_FRAME_STATS + GET_ANIMATION_FRAME_STATS, + SET_POWER_MODE, }; virtual status_t onTransact(uint32_t code, const Parcel& data, diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h index e66632940..65313df4c 100644 --- a/include/gui/SurfaceComposerClient.h +++ b/include/gui/SurfaceComposerClient.h @@ -82,11 +82,8 @@ public: // returned by getDisplayInfo static status_t setActiveConfig(const sp& display, int id); - /* triggers screen off and waits for it to complete */ - static void blankDisplay(const sp& display); - - /* triggers screen on and waits for it to complete */ - static void unblankDisplay(const sp& display); + /* Triggers screen on/off or low power mode and waits for it to complete */ + static void setDisplayPowerMode(const sp& display, int mode); // ------------------------------------------------------------------------ // surface creation / destruction diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index c6c88a9d9..46801686b 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -205,20 +205,13 @@ public: return reply.readStrongBinder(); } - virtual void blank(const sp& display) + virtual void setPowerMode(const sp& display, int mode) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); - remote()->transact(BnSurfaceComposer::BLANK, data, &reply); - } - - virtual void unblank(const sp& display) - { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - data.writeStrongBinder(display); - remote()->transact(BnSurfaceComposer::UNBLANK, data, &reply); + data.writeInt32(mode); + remote()->transact(BnSurfaceComposer::SET_POWER_MODE, data, &reply); } virtual status_t getDisplayConfigs(const sp& display, @@ -378,18 +371,6 @@ status_t BnSurfaceComposer::onTransact( reply->writeStrongBinder(display); return NO_ERROR; } - case BLANK: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - sp display = data.readStrongBinder(); - blank(display); - return NO_ERROR; - } - case UNBLANK: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - sp display = data.readStrongBinder(); - unblank(display); - return NO_ERROR; - } case GET_DISPLAY_CONFIGS: { CHECK_INTERFACE(ISurfaceComposer, data, reply); Vector configs; @@ -434,6 +415,13 @@ status_t BnSurfaceComposer::onTransact( reply->writeInt32(result); return NO_ERROR; } + case SET_POWER_MODE: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + sp display = data.readStrongBinder(); + int32_t mode = data.readInt32(); + setPowerMode(display, mode); + return NO_ERROR; + } default: { return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index eedeca18d..3bee3fc6e 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -655,12 +655,9 @@ status_t SurfaceComposerClient::setActiveConfig(const sp& display, int return ComposerService::getComposerService()->setActiveConfig(display, id); } -void SurfaceComposerClient::blankDisplay(const sp& token) { - ComposerService::getComposerService()->blank(token); -} - -void SurfaceComposerClient::unblankDisplay(const sp& token) { - ComposerService::getComposerService()->unblank(token); +void SurfaceComposerClient::setDisplayPowerMode(const sp& token, + int mode) { + ComposerService::getComposerService()->setPowerMode(token, mode); } status_t SurfaceComposerClient::clearAnimationFrameStats() { diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 4ebe2915e..71377ed7f 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -70,9 +70,9 @@ DisplayDevice::DisplayDevice( mPageFlipCount(), mIsSecure(isSecure), mSecureLayerVisible(false), - mScreenAcquired(false), mLayerStack(NO_LAYER_STACK), - mOrientation() + mOrientation(), + mPowerMode(HWC_POWER_MODE_OFF) { mNativeWindow = new Surface(producer, false); ANativeWindow* const window = mNativeWindow.get(); @@ -109,7 +109,8 @@ DisplayDevice::DisplayDevice( mFrame.makeInvalid(); // virtual displays are always considered enabled - mScreenAcquired = (mType >= DisplayDevice::DISPLAY_VIRTUAL); + mPowerMode = (mType >= DisplayDevice::DISPLAY_VIRTUAL) ? + HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF; // Name the display. The name will be replaced shortly if the display // was created with createDisplay(). @@ -322,21 +323,16 @@ Region DisplayDevice::getDirtyRegion(bool repaintEverything) const { } // ---------------------------------------------------------------------------- - -bool DisplayDevice::canDraw() const { - return mScreenAcquired; +void DisplayDevice::setPowerMode(int mode) { + mPowerMode = mode; } -void DisplayDevice::releaseScreen() const { - mScreenAcquired = false; +int DisplayDevice::getPowerMode() const { + return mPowerMode; } -void DisplayDevice::acquireScreen() const { - mScreenAcquired = true; -} - -bool DisplayDevice::isScreenAcquired() const { - return mScreenAcquired; +bool DisplayDevice::isDisplayOn() const { + return (mPowerMode != HWC_POWER_MODE_OFF); } // ---------------------------------------------------------------------------- @@ -465,13 +461,13 @@ void DisplayDevice::dump(String8& result) const { result.appendFormat( "+ DisplayDevice: %s\n" " type=%x, hwcId=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), " - "flips=%u, isSecure=%d, secureVis=%d, acquired=%d, numLayers=%zu\n" + "flips=%u, isSecure=%d, secureVis=%d, powerMode=%d, numLayers=%zu\n" " v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d]," "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n", mDisplayName.string(), mType, mHwcDisplayId, mLayerStack, mDisplayWidth, mDisplayHeight, mNativeWindow.get(), mOrientation, tr.getType(), getPageFlipCount(), - mIsSecure, mSecureLayerVisible, mScreenAcquired, mVisibleLayersSortedByZ.size(), + mIsSecure, mSecureLayerVisible, mPowerMode, mVisibleLayersSortedByZ.size(), mViewport.left, mViewport.top, mViewport.right, mViewport.bottom, mFrame.left, mFrame.top, mFrame.right, mFrame.bottom, mScissor.left, mScissor.top, mScissor.right, mScissor.bottom, diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index f750c6c82..4c8ef023e 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -147,12 +147,11 @@ public: void setViewportAndProjection() const; /* ------------------------------------------------------------------------ - * blank / unblank management + * Display power mode management. */ - void releaseScreen() const; - void acquireScreen() const; - bool isScreenAcquired() const; - bool canDraw() const; + int getPowerMode() const; + void setPowerMode(int mode); + bool isDisplayOn() const; // release HWC resources (if any) for removable displays void disconnect(HWComposer& hwc); @@ -197,9 +196,6 @@ private: // Whether we have a visible secure layer on this display bool mSecureLayerVisible; - // Whether the screen is blanked; - mutable int mScreenAcquired; - /* * Transaction state @@ -217,6 +213,8 @@ private: Rect mScissor; Transform mGlobalTransform; bool mNeedsFiltering; + // Current power mode + int mPowerMode; }; }; // namespace android diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index c3b215940..185dab227 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -759,19 +759,18 @@ status_t HWComposer::commit() { return (status_t)err; } -status_t HWComposer::release(int disp) { +status_t HWComposer::setPowerMode(int disp, int mode) { LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE); if (mHwc) { - eventControl(disp, HWC_EVENT_VSYNC, 0); - return (status_t)mHwc->blank(mHwc, disp, 1); - } - return NO_ERROR; -} - -status_t HWComposer::acquire(int disp) { - LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE); - if (mHwc) { - return (status_t)mHwc->blank(mHwc, disp, 0); + if (mode == HWC_POWER_MODE_OFF) { + eventControl(disp, HWC_EVENT_VSYNC, 0); + } + if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_4)) { + return (status_t)mHwc->setPowerMode(mHwc, disp, mode); + } else { + return (status_t)mHwc->blank(mHwc, disp, + mode == HWC_POWER_MODE_OFF ? 1 : 0); + } } return NO_ERROR; } diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 2f926729e..c62b924ca 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -97,11 +97,8 @@ public: // commits the list status_t commit(); - // release hardware resources and blank screen - status_t release(int disp); - - // acquire hardware resources and unblank screen - status_t acquire(int disp); + // set power mode + status_t setPowerMode(int disp, int mode); // reset state when an external, non-virtual display is disconnected void disconnectDisplay(int disp); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 7152f9364..06435abd7 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -437,7 +437,7 @@ void SurfaceFlinger::init() { // for displays other than the main display, so we always // assume a connected display is unblanked. ALOGD("marking display %zu as acquired/unblanked", i); - hw->acquireScreen(); + hw->setPowerMode(HWC_POWER_MODE_NORMAL); } mDisplays.add(token, hw); } @@ -793,7 +793,7 @@ void SurfaceFlinger::doDebugFlashRegions() const bool repaintEverything = mRepaintEverything; for (size_t dpy=0 ; dpy& hw(mDisplays[dpy]); - if (hw->canDraw()) { + if (hw->isDisplayOn()) { // transform the dirty region into this screen's coordinate space const Region dirtyRegion(hw->getDirtyRegion(repaintEverything)); if (!dirtyRegion.isEmpty()) { @@ -860,7 +860,7 @@ void SurfaceFlinger::postComposition() if (runningWithoutSyncFramework) { const sp hw(getDefaultDisplayDevice()); - if (hw->isScreenAcquired()) { + if (hw->isDisplayOn()) { enableHardwareVsync(); } } @@ -895,7 +895,7 @@ void SurfaceFlinger::rebuildLayerStacks() { const sp& hw(mDisplays[dpy]); const Transform& tr(hw->getTransform()); const Rect bounds(hw->getBounds()); - if (hw->canDraw()) { + if (hw->isDisplayOn()) { SurfaceFlinger::computeVisibleRegions(layers, hw->getLayerStack(), dirtyRegion, opaqueRegion); @@ -991,7 +991,7 @@ void SurfaceFlinger::doComposition() { const bool repaintEverything = android_atomic_and(0, &mRepaintEverything); for (size_t dpy=0 ; dpy& hw(mDisplays[dpy]); - if (hw->canDraw()) { + if (hw->isDisplayOn()) { // transform the dirty region into this screen's coordinate space const Region dirtyRegion(hw->getDirtyRegion(repaintEverything)); @@ -2082,7 +2082,7 @@ void SurfaceFlinger::onInitializeDisplays() { d.viewport.makeInvalid(); displays.add(d); setTransactionState(state, displays, 0); - onScreenAcquired(getDefaultDisplayDevice()); + setPowerModeInternal(getDisplayDevice(d.token), HWC_POWER_MODE_NORMAL); const nsecs_t period = getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY); @@ -2103,42 +2103,35 @@ void SurfaceFlinger::initializeDisplays() { postMessageAsync(msg); // we may be called from main thread, use async message } +void SurfaceFlinger::setPowerModeInternal(const sp& hw, + int mode) { + ALOGD("Set power mode=%d, type=%d flinger=%p", mode, hw->getDisplayType(), + this); + int32_t type = hw->getDisplayType(); + int currentMode = hw->getPowerMode(); -void SurfaceFlinger::onScreenAcquired(const sp& hw) { - ALOGD("Screen acquired, type=%d flinger=%p", hw->getDisplayType(), this); - if (hw->isScreenAcquired()) { - // this is expected, e.g. when power manager wakes up during boot - ALOGD(" screen was previously acquired"); + if (mode == currentMode) { + ALOGD("Screen type=%d is already mode=%d", hw->getDisplayType(), mode); return; } - hw->acquireScreen(); - int32_t type = hw->getDisplayType(); - if (type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) { - // built-in display, tell the HWC - getHwComposer().acquire(type); + hw->setPowerMode(mode); + if (type >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) { + ALOGW("Trying to set power mode for virtual display"); + return; + } + if (currentMode == HWC_POWER_MODE_OFF) { + getHwComposer().setPowerMode(type, mode); if (type == DisplayDevice::DISPLAY_PRIMARY) { // FIXME: eventthread only knows about the main display right now mEventThread->onScreenAcquired(); - resyncToHardwareVsync(true); } - } - mVisibleRegionsDirty = true; - repaintEverything(); -} -void SurfaceFlinger::onScreenReleased(const sp& hw) { - ALOGD("Screen released, type=%d flinger=%p", hw->getDisplayType(), this); - if (!hw->isScreenAcquired()) { - ALOGD(" screen was previously released"); - return; - } - - hw->releaseScreen(); - int32_t type = hw->getDisplayType(); - if (type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) { + mVisibleRegionsDirty = true; + repaintEverything(); + } else if (mode == HWC_POWER_MODE_OFF) { if (type == DisplayDevice::DISPLAY_PRIMARY) { disableHardwareVsync(true); // also cancels any in-progress resync @@ -2146,56 +2139,38 @@ void SurfaceFlinger::onScreenReleased(const sp& hw) { mEventThread->onScreenReleased(); } - // built-in display, tell the HWC - getHwComposer().release(type); + getHwComposer().setPowerMode(type, mode); + mVisibleRegionsDirty = true; + // from this point on, SF will stop drawing on this display + } else { + getHwComposer().setPowerMode(type, mode); } - mVisibleRegionsDirty = true; - // from this point on, SF will stop drawing on this display } -void SurfaceFlinger::unblank(const sp& display) { - class MessageScreenAcquired : public MessageBase { +void SurfaceFlinger::setPowerMode(const sp& display, int mode) { + class MessageSetPowerMode: public MessageBase { SurfaceFlinger& mFlinger; sp mDisplay; + int mMode; public: - MessageScreenAcquired(SurfaceFlinger& flinger, - const sp& disp) : mFlinger(flinger), mDisplay(disp) { } + MessageSetPowerMode(SurfaceFlinger& flinger, + const sp& disp, int mode) : mFlinger(flinger), + mDisplay(disp) { mMode = mode; } virtual bool handler() { - const sp hw(mFlinger.getDisplayDevice(mDisplay)); + sp hw(mFlinger.getDisplayDevice(mDisplay)); if (hw == NULL) { - ALOGE("Attempt to unblank null display %p", mDisplay.get()); + ALOGE("Attempt to set power mode = %d for null display %p", + mDisplay.get(), mMode); } else if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL) { - ALOGW("Attempt to unblank virtual display"); + ALOGW("Attempt to set power mode = %d for virtual display", + mMode); } else { - mFlinger.onScreenAcquired(hw); + mFlinger.setPowerModeInternal(hw, mMode); } return true; } }; - sp msg = new MessageScreenAcquired(*this, display); - postMessageSync(msg); -} - -void SurfaceFlinger::blank(const sp& display) { - class MessageScreenReleased : public MessageBase { - SurfaceFlinger& mFlinger; - sp mDisplay; - public: - MessageScreenReleased(SurfaceFlinger& flinger, - const sp& disp) : mFlinger(flinger), mDisplay(disp) { } - virtual bool handler() { - const sp hw(mFlinger.getDisplayDevice(mDisplay)); - if (hw == NULL) { - ALOGE("Attempt to blank null display %p", mDisplay.get()); - } else if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL) { - ALOGW("Attempt to blank virtual display"); - } else { - mFlinger.onScreenReleased(hw); - } - return true; - } - }; - sp msg = new MessageScreenReleased(*this, display); + sp msg = new MessageSetPowerMode(*this, display, mode); postMessageSync(msg); } @@ -2456,8 +2431,8 @@ void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, mRenderEngine->dump(result); hw->undefinedRegion.dump(result, "undefinedRegion"); - result.appendFormat(" orientation=%d, canDraw=%d\n", - hw->getOrientation(), hw->canDraw()); + result.appendFormat(" orientation=%d, isDisplayOn=%d\n", + hw->getOrientation(), hw->isDisplayOn()); result.appendFormat( " last eglSwapBuffers() time: %f us\n" " last transaction time : %f us\n" @@ -2549,10 +2524,9 @@ status_t SurfaceFlinger::onTransact( case CREATE_DISPLAY: case SET_TRANSACTION_STATE: case BOOT_FINISHED: - case BLANK: - case UNBLANK: case CLEAR_ANIMATION_FRAME_STATS: case GET_ANIMATION_FRAME_STATS: + case SET_POWER_MODE: { // codes that require permission check IPCThreadState* ipc = IPCThreadState::self(); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index cc01eb395..996a795cf 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -205,13 +205,10 @@ private: Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ, bool useIdentityTransform); - // called when screen needs to turn off - virtual void blank(const sp& display); - // called when screen is turning back on - virtual void unblank(const sp& display); virtual status_t getDisplayConfigs(const sp& display, Vector* configs); virtual int getActiveConfig(const sp& display); + virtual void setPowerMode(const sp& display, int mode); virtual status_t setActiveConfig(const sp& display, int id); virtual status_t clearAnimationFrameStats(); virtual status_t getAnimationFrameStats(FrameStats* outStats) const; @@ -242,10 +239,8 @@ private: // called on the main thread in response to initializeDisplays() void onInitializeDisplays(); - // called on the main thread in response to blank() - void onScreenReleased(const sp& hw); - // called on the main thread in response to unblank() - void onScreenAcquired(const sp& hw); + // called on the main thread in response to setPowerMode() + void setPowerModeInternal(const sp& hw, int mode); void handleMessageTransaction(); void handleMessageInvalidate();