diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 71377ed7f..e3e0b0a76 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -72,7 +72,8 @@ DisplayDevice::DisplayDevice( mSecureLayerVisible(false), mLayerStack(NO_LAYER_STACK), mOrientation(), - mPowerMode(HWC_POWER_MODE_OFF) + mPowerMode(HWC_POWER_MODE_OFF), + mActiveConfig(0) { mNativeWindow = new Surface(producer, false); ANativeWindow* const window = mNativeWindow.get(); @@ -335,6 +336,15 @@ bool DisplayDevice::isDisplayOn() const { return (mPowerMode != HWC_POWER_MODE_OFF); } +// ---------------------------------------------------------------------------- +void DisplayDevice::setActiveConfig(int mode) { + mActiveConfig = mode; +} + +int DisplayDevice::getActiveConfig() const { + return mActiveConfig; +} + // ---------------------------------------------------------------------------- void DisplayDevice::setLayerStack(uint32_t stack) { @@ -461,13 +471,14 @@ 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, powerMode=%d, numLayers=%zu\n" + "flips=%u, isSecure=%d, secureVis=%d, powerMode=%d, activeConfig=%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, mPowerMode, mVisibleLayersSortedByZ.size(), + mIsSecure, mSecureLayerVisible, mPowerMode, mActiveConfig, + 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 4c8ef023e..615ca2822 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -153,6 +153,12 @@ public: void setPowerMode(int mode); bool isDisplayOn() const; + /* ------------------------------------------------------------------------ + * Display active config management. + */ + int getActiveConfig() const; + void setActiveConfig(int mode); + // release HWC resources (if any) for removable displays void disconnect(HWComposer& hwc); @@ -215,6 +221,8 @@ private: bool mNeedsFiltering; // Current power mode int mPowerMode; + // Current active config + int mActiveConfig; }; }; // namespace android diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index a8fb5bdf9..5e3fe92bc 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -778,6 +778,16 @@ status_t HWComposer::setPowerMode(int disp, int mode) { return NO_ERROR; } +status_t HWComposer::setActiveConfig(int disp, int mode) { + LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE); + if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_4)) { + return (status_t)mHwc->setActiveConfig(mHwc, disp, mode); + } else { + LOG_FATAL_IF(mode != 0); + } + return NO_ERROR; +} + void HWComposer::disconnectDisplay(int disp) { LOG_ALWAYS_FATAL_IF(disp < 0 || disp == HWC_DISPLAY_PRIMARY); DisplayData& dd(mDisplayData[disp]); diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 9bd99eb78..5cb56a0f4 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -100,6 +100,9 @@ public: // set power mode status_t setPowerMode(int disp, int mode); + // set active config + status_t setActiveConfig(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 53b0dc4d6..80cf6436e 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -603,11 +603,55 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp& display, return NO_ERROR; } -int SurfaceFlinger::getActiveConfig(const sp&) { - return 0; +int SurfaceFlinger::getActiveConfig(const sp& display) { + return getDisplayDevice(display)->getActiveConfig(); } -status_t SurfaceFlinger::setActiveConfig(const sp&, int) { +void SurfaceFlinger::setActiveConfigInternal(const sp& hw, int mode) { + ALOGD("Set active config mode=%d, type=%d flinger=%p", mode, hw->getDisplayType(), + this); + int32_t type = hw->getDisplayType(); + int currentMode = hw->getActiveConfig(); + + if (mode == currentMode) { + ALOGD("Screen type=%d is already mode=%d", hw->getDisplayType(), mode); + return; + } + + if (type >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) { + ALOGW("Trying to set config for virtual display"); + return; + } + + hw->setActiveConfig(mode); + getHwComposer().setActiveConfig(type, mode); +} + +status_t SurfaceFlinger::setActiveConfig(const sp& display, int mode) { + class MessageSetActiveConfig: public MessageBase { + SurfaceFlinger& mFlinger; + sp mDisplay; + int mMode; + public: + MessageSetActiveConfig(SurfaceFlinger& flinger, const sp& disp, + int mode) : + mFlinger(flinger), mDisplay(disp) { mMode = mode; } + virtual bool handler() { + sp hw(mFlinger.getDisplayDevice(mDisplay)); + if (hw == NULL) { + ALOGE("Attempt to set active config = %d for null display %p", + mDisplay.get(), mMode); + } else if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL) { + ALOGW("Attempt to set active config = %d for virtual display", + mMode); + } else { + mFlinger.setActiveConfigInternal(hw, mMode); + } + return true; + } + }; + sp msg = new MessageSetActiveConfig(*this, display, mode); + postMessageSync(msg); return NO_ERROR; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 476e549af..5ae3d0b29 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -239,6 +239,8 @@ private: // called on the main thread in response to initializeDisplays() void onInitializeDisplays(); + // called on the main thread in response to setActiveConfig() + void setActiveConfigInternal(const sp& hw, int mode); // called on the main thread in response to setPowerMode() void setPowerModeInternal(const sp& hw, int mode);