Merge "surfaceflinger: Replace blank/unblank with setPowerMode"
diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h
index 1581084..9f1937b 100644
--- a/include/gui/ISurfaceComposer.h
+++ b/include/gui/ISurfaceComposer.h
@@ -104,15 +104,11 @@
     virtual bool authenticateSurfaceTexture(
             const sp<IGraphicBufferProducer>& 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<IBinder>& display) = 0;
-
-    /* triggers screen on and waits for it to complete
-     * requires ACCESS_SURFACE_FLINGER permission.
-     */
-    virtual void unblank(const sp<IBinder>& display) = 0;
+    virtual void setPowerMode(const sp<IBinder>& 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 @@
         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 e666329..65313df 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/include/gui/SurfaceComposerClient.h
@@ -82,11 +82,8 @@
     // returned by getDisplayInfo
     static status_t setActiveConfig(const sp<IBinder>& display, int id);
 
-    /* triggers screen off and waits for it to complete */
-    static void blankDisplay(const sp<IBinder>& display);
-
-    /* triggers screen on and waits for it to complete */
-    static void unblankDisplay(const sp<IBinder>& display);
+    /* Triggers screen on/off or low power mode and waits for it to complete */
+    static void setDisplayPowerMode(const sp<IBinder>& display, int mode);
 
     // ------------------------------------------------------------------------
     // surface creation / destruction
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index c6c88a9..4680168 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -205,20 +205,13 @@
         return reply.readStrongBinder();
     }
 
-    virtual void blank(const sp<IBinder>& display)
+    virtual void setPowerMode(const sp<IBinder>& display, int mode)
     {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         data.writeStrongBinder(display);
-        remote()->transact(BnSurfaceComposer::BLANK, data, &reply);
-    }
-
-    virtual void unblank(const sp<IBinder>& 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<IBinder>& display,
@@ -378,18 +371,6 @@
             reply->writeStrongBinder(display);
             return NO_ERROR;
         }
-        case BLANK: {
-            CHECK_INTERFACE(ISurfaceComposer, data, reply);
-            sp<IBinder> display = data.readStrongBinder();
-            blank(display);
-            return NO_ERROR;
-        }
-        case UNBLANK: {
-            CHECK_INTERFACE(ISurfaceComposer, data, reply);
-            sp<IBinder> display = data.readStrongBinder();
-            unblank(display);
-            return NO_ERROR;
-        }
         case GET_DISPLAY_CONFIGS: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             Vector<DisplayInfo> configs;
@@ -434,6 +415,13 @@
             reply->writeInt32(result);
             return NO_ERROR;
         }
+        case SET_POWER_MODE: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            sp<IBinder> 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 eedeca1..3bee3fc 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -655,12 +655,9 @@
     return ComposerService::getComposerService()->setActiveConfig(display, id);
 }
 
-void SurfaceComposerClient::blankDisplay(const sp<IBinder>& token) {
-    ComposerService::getComposerService()->blank(token);
-}
-
-void SurfaceComposerClient::unblankDisplay(const sp<IBinder>& token) {
-    ComposerService::getComposerService()->unblank(token);
+void SurfaceComposerClient::setDisplayPowerMode(const sp<IBinder>& 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 4ebe291..71377ed 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -70,9 +70,9 @@
       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 @@
     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 @@
 }
 
 // ----------------------------------------------------------------------------
-
-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 @@
     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 f750c6c..4c8ef02 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -147,12 +147,11 @@
     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 @@
     // 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 @@
     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 c3b2159..185dab2 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -759,19 +759,18 @@
     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 2f92672..c62b924 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -97,11 +97,8 @@
     // 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 9111dbb..edf867a 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -434,7 +434,7 @@
                 // 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);
         }
@@ -790,7 +790,7 @@
     const bool repaintEverything = mRepaintEverything;
     for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
         const sp<DisplayDevice>& 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()) {
@@ -857,7 +857,7 @@
 
     if (kIgnorePresentFences) {
         const sp<const DisplayDevice> hw(getDefaultDisplayDevice());
-        if (hw->isScreenAcquired()) {
+        if (hw->isDisplayOn()) {
             enableHardwareVsync();
         }
     }
@@ -892,7 +892,7 @@
             const sp<DisplayDevice>& 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);
 
@@ -988,7 +988,7 @@
     const bool repaintEverything = android_atomic_and(0, &mRepaintEverything);
     for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
         const sp<DisplayDevice>& 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));
 
@@ -2070,7 +2070,7 @@
     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);
@@ -2091,42 +2091,35 @@
     postMessageAsync(msg);  // we may be called from main thread, use async message
 }
 
+void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& 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<const DisplayDevice>& 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<const DisplayDevice>& 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
 
@@ -2134,56 +2127,38 @@
             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<IBinder>& display) {
-    class MessageScreenAcquired : public MessageBase {
+void SurfaceFlinger::setPowerMode(const sp<IBinder>& display, int mode) {
+    class MessageSetPowerMode: public MessageBase {
         SurfaceFlinger& mFlinger;
         sp<IBinder> mDisplay;
+        int mMode;
     public:
-        MessageScreenAcquired(SurfaceFlinger& flinger,
-                const sp<IBinder>& disp) : mFlinger(flinger), mDisplay(disp) { }
+        MessageSetPowerMode(SurfaceFlinger& flinger,
+                const sp<IBinder>& disp, int mode) : mFlinger(flinger),
+                    mDisplay(disp) { mMode = mode; }
         virtual bool handler() {
-            const sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay));
+            sp<DisplayDevice> 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<MessageBase> msg = new MessageScreenAcquired(*this, display);
-    postMessageSync(msg);
-}
-
-void SurfaceFlinger::blank(const sp<IBinder>& display) {
-    class MessageScreenReleased : public MessageBase {
-        SurfaceFlinger& mFlinger;
-        sp<IBinder> mDisplay;
-    public:
-        MessageScreenReleased(SurfaceFlinger& flinger,
-                const sp<IBinder>& disp) : mFlinger(flinger), mDisplay(disp) { }
-        virtual bool handler() {
-            const sp<DisplayDevice> 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<MessageBase> msg = new MessageScreenReleased(*this, display);
+    sp<MessageBase> msg = new MessageSetPowerMode(*this, display, mode);
     postMessageSync(msg);
 }
 
@@ -2441,8 +2416,8 @@
     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"
@@ -2534,10 +2509,9 @@
         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 cc01eb3..996a795 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -205,13 +205,10 @@
             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<IBinder>& display);
-    // called when screen is turning back on
-    virtual void unblank(const sp<IBinder>& display);
     virtual status_t getDisplayConfigs(const sp<IBinder>& display,
             Vector<DisplayInfo>* configs);
     virtual int getActiveConfig(const sp<IBinder>& display);
+    virtual void setPowerMode(const sp<IBinder>& display, int mode);
     virtual status_t setActiveConfig(const sp<IBinder>& display, int id);
     virtual status_t clearAnimationFrameStats();
     virtual status_t getAnimationFrameStats(FrameStats* outStats) const;
@@ -242,10 +239,8 @@
 
     // called on the main thread in response to initializeDisplays()
     void onInitializeDisplays();
-    // called on the main thread in response to blank()
-    void onScreenReleased(const sp<const DisplayDevice>& hw);
-    // called on the main thread in response to unblank()
-    void onScreenAcquired(const sp<const DisplayDevice>& hw);
+    // called on the main thread in response to setPowerMode()
+    void setPowerModeInternal(const sp<DisplayDevice>& hw, int mode);
 
     void handleMessageTransaction();
     void handleMessageInvalidate();