Pass display arg to blank/unblank

This allows us to blank and unblank displays other than the built-in
display (e.g. HDMI).

Bug: 7240511
Change-Id: I89ea13f9e497be74c3e1231d0c62fb558e93e0f8
diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h
index a20caf9..5d2d8d7 100644
--- a/include/gui/ISurfaceComposer.h
+++ b/include/gui/ISurfaceComposer.h
@@ -99,10 +99,10 @@
 
 
     /* triggers screen off and waits for it to complete */
-    virtual void blank() = 0;
+    virtual void blank(const sp<IBinder>& display) = 0;
 
     /* triggers screen on and waits for it to complete */
-    virtual void unblank() = 0;
+    virtual void unblank(const sp<IBinder>& display) = 0;
 
     /* returns information about a display
      * intended to be used to get information about built-in displays */
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 07d2b79..aff1b45 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -197,17 +197,19 @@
         return reply.readStrongBinder();
     }
 
-    virtual void blank()
+    virtual void blank(const sp<IBinder>& display)
     {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        data.writeStrongBinder(display);
         remote()->transact(BnSurfaceComposer::BLANK, data, &reply);
     }
 
-    virtual void unblank()
+    virtual void unblank(const sp<IBinder>& display)
     {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        data.writeStrongBinder(display);
         remote()->transact(BnSurfaceComposer::UNBLANK, data, &reply);
     }
 
@@ -320,11 +322,13 @@
         } break;
         case BLANK: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
-            blank();
+            sp<IBinder> display = data.readStrongBinder();
+            blank(display);
         } break;
         case UNBLANK: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
-            unblank();
+            sp<IBinder> display = data.readStrongBinder();
+            unblank(display);
         } break;
         case GET_DISPLAY_INFO: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 987cc64..960fb0e 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -646,17 +646,19 @@
     return (status_t)err;
 }
 
-status_t HWComposer::release() const {
+status_t HWComposer::release(int disp) const {
+    LOG_FATAL_IF(disp >= HWC_NUM_DISPLAY_TYPES);
     if (mHwc) {
-        mHwc->eventControl(mHwc, HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0);
-        return (status_t)mHwc->blank(mHwc, 0, 1);
+        mHwc->eventControl(mHwc, disp, HWC_EVENT_VSYNC, 0);
+        return (status_t)mHwc->blank(mHwc, disp, 1);
     }
     return NO_ERROR;
 }
 
-status_t HWComposer::acquire() const {
+status_t HWComposer::acquire(int disp) const {
+    LOG_FATAL_IF(disp >= HWC_NUM_DISPLAY_TYPES);
     if (mHwc) {
-        return (status_t)mHwc->blank(mHwc, 0, 0);
+        return (status_t)mHwc->blank(mHwc, disp, 0);
     }
     return NO_ERROR;
 }
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 8f66651..633ca9c 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -92,10 +92,10 @@
     status_t commit();
 
     // release hardware resources and blank screen
-    status_t release() const;
+    status_t release(int disp) const;
 
     // acquire hardware resources and unblank screen
-    status_t acquire() const;
+    status_t acquire(int disp) const;
 
     // create a work list for numLayers layer. sets HWC_GEOMETRY_CHANGED.
     status_t createWorkList(int32_t id, size_t numLayers);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 5f06105..8cfaa31 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -490,11 +490,11 @@
                         static_cast< sp<ISurfaceTexture> >(fbs->getBufferQueue()));
             sp<DisplayDevice> hw = new DisplayDevice(this,
                     type, token, stc, fbs, mEGLConfig);
-
             if (i > DisplayDevice::DISPLAY_PRIMARY) {
-                // FIXME: currently we don't really handle blank/unblank
+                // FIXME: currently we don't get blank/unblank requests
                 // for displays other than the main display, so we always
                 // assume a connected display is unblanked.
+                ALOGD("marking display %d as acquired/unblanked", i);
                 hw->acquireScreen();
             }
             mDisplays.add(token, hw);
@@ -1972,59 +1972,94 @@
 
 
 void SurfaceFlinger::onScreenAcquired(const sp<const DisplayDevice>& hw) {
-    ALOGD("Screen about to return, flinger = %p", this);
-    getHwComposer().acquire();
+    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");
+        return;
+    }
+
     hw->acquireScreen();
-    if (hw->getDisplayType() == DisplayDevice::DISPLAY_PRIMARY) {
-        // FIXME: eventthread only knows about the main display right now
-        mEventThread->onScreenAcquired();
+    int32_t type = hw->getDisplayType();
+    if (type < DisplayDevice::NUM_DISPLAY_TYPES) {
+        // built-in display, tell the HWC
+        getHwComposer().acquire(type);
+
+        if (type == DisplayDevice::DISPLAY_PRIMARY) {
+            // FIXME: eventthread only knows about the main display right now
+            mEventThread->onScreenAcquired();
+        }
     }
     mVisibleRegionsDirty = true;
     repaintEverything();
 }
 
 void SurfaceFlinger::onScreenReleased(const sp<const DisplayDevice>& hw) {
-    ALOGD("About to give-up screen, flinger = %p", this);
-    if (hw->isScreenAcquired()) {
-        if (hw->getDisplayType() == DisplayDevice::DISPLAY_PRIMARY) {
+    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_DISPLAY_TYPES) {
+        if (type == DisplayDevice::DISPLAY_PRIMARY) {
             // FIXME: eventthread only knows about the main display right now
             mEventThread->onScreenReleased();
         }
-        hw->releaseScreen();
-        getHwComposer().release();
-        mVisibleRegionsDirty = true;
-        // from this point on, SF will stop drawing
+
+        // built-in display, tell the HWC
+        getHwComposer().release(type);
+    }
+    mVisibleRegionsDirty = true;
+    // from this point on, SF will stop drawing on this display
+}
+
+void SurfaceFlinger::unblank(const sp<IBinder>& display) {
+    class MessageScreenAcquired : public MessageBase {
+        SurfaceFlinger* mFlinger;
+        const sp<DisplayDevice>& mHw;
+    public:
+        MessageScreenAcquired(SurfaceFlinger* flinger,
+                const sp<DisplayDevice>& hw) : mFlinger(flinger), mHw(hw) { }
+        virtual bool handler() {
+            mFlinger->onScreenAcquired(mHw);
+            return true;
+        }
+    };
+    const sp<DisplayDevice>& hw = getDisplayDevice(display);
+    if (hw == NULL) {
+        ALOGE("Attempt to unblank null display %p", display.get());
+    } else if (hw->getDisplayType() >= DisplayDevice::NUM_DISPLAY_TYPES) {
+        ALOGW("Attempt to unblank virtual display");
+    } else {
+        sp<MessageBase> msg = new MessageScreenAcquired(this, hw);
+        postMessageSync(msg);
     }
 }
 
-void SurfaceFlinger::unblank() {
-    class MessageScreenAcquired : public MessageBase {
-        SurfaceFlinger* flinger;
-    public:
-        MessageScreenAcquired(SurfaceFlinger* flinger) : flinger(flinger) { }
-        virtual bool handler() {
-            // FIXME: should this be per-display?
-            flinger->onScreenAcquired(flinger->getDefaultDisplayDevice());
-            return true;
-        }
-    };
-    sp<MessageBase> msg = new MessageScreenAcquired(this);
-    postMessageSync(msg);
-}
-
-void SurfaceFlinger::blank() {
+void SurfaceFlinger::blank(const sp<IBinder>& display) {
     class MessageScreenReleased : public MessageBase {
-        SurfaceFlinger* flinger;
+        SurfaceFlinger* mFlinger;
+        const sp<DisplayDevice>& mHw;
     public:
-        MessageScreenReleased(SurfaceFlinger* flinger) : flinger(flinger) { }
+        MessageScreenReleased(SurfaceFlinger* flinger,
+                const sp<DisplayDevice>& hw) : mFlinger(flinger), mHw(hw) { }
         virtual bool handler() {
-            // FIXME: should this be per-display?
-            flinger->onScreenReleased(flinger->getDefaultDisplayDevice());
+            mFlinger->onScreenReleased(mHw);
             return true;
         }
     };
-    sp<MessageBase> msg = new MessageScreenReleased(this);
-    postMessageSync(msg);
+    const sp<DisplayDevice>& hw = getDisplayDevice(display);
+    if (hw == NULL) {
+        ALOGE("Attempt to blank null display %p", display.get());
+    } else if (hw->getDisplayType() >= DisplayDevice::NUM_DISPLAY_TYPES) {
+        ALOGW("Attempt to blank virtual display");
+    } else {
+        sp<MessageBase> msg = new MessageScreenReleased(this, hw);
+        postMessageSync(msg);
+    }
 }
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index e5b939d..8272848 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -196,9 +196,9 @@
         uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ,
         uint32_t maxLayerZ);
     // called when screen needs to turn off
-    virtual void blank();
+    virtual void blank(const sp<IBinder>& display);
     // called when screen is turning back on
-    virtual void unblank();
+    virtual void unblank(const sp<IBinder>& display);
     virtual status_t getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info);
     virtual void connectDisplay(const sp<ISurfaceTexture>& display);