Merge "Bugreport broadcasts are only useful to owners." into jb-mr2-dev
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index e16abef..6936a7f 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -70,12 +70,13 @@
 DisplayDevice::DisplayDevice(
         const sp<SurfaceFlinger>& flinger,
         DisplayType type,
+        int32_t hwcId,
         bool isSecure,
         const wp<IBinder>& displayToken,
         const sp<DisplaySurface>& displaySurface,
         EGLConfig config)
     : mFlinger(flinger),
-      mType(type), mHwcDisplayId(-1),
+      mType(type), mHwcDisplayId(hwcId),
       mDisplayToken(displayToken),
       mDisplaySurface(displaySurface),
       mDisplay(EGL_NO_DISPLAY),
@@ -91,7 +92,48 @@
       mOrientation()
 {
     mNativeWindow = new Surface(mDisplaySurface->getIGraphicBufferProducer());
-    init(config);
+    ANativeWindow* const window = mNativeWindow.get();
+
+    int format;
+    window->query(window, NATIVE_WINDOW_FORMAT, &format);
+
+    /*
+     * Create our display's surface
+     */
+
+    EGLSurface surface;
+    EGLint w, h;
+    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    surface = eglCreateWindowSurface(display, config, window, NULL);
+    eglQuerySurface(display, surface, EGL_WIDTH,  &mDisplayWidth);
+    eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight);
+
+    mDisplay = display;
+    mSurface = surface;
+    mFormat  = format;
+    mPageFlipCount = 0;
+    mViewport.makeInvalid();
+    mFrame.makeInvalid();
+
+    // virtual displays are always considered enabled
+    mScreenAcquired = (mType >= DisplayDevice::DISPLAY_VIRTUAL);
+
+    // Name the display.  The name will be replaced shortly if the display
+    // was created with createDisplay().
+    switch (mType) {
+        case DISPLAY_PRIMARY:
+            mDisplayName = "Built-in Screen";
+            break;
+        case DISPLAY_EXTERNAL:
+            mDisplayName = "HDMI Screen";
+            break;
+        default:
+            mDisplayName = "Virtual Screen";    // e.g. Overlay #n
+            break;
+    }
+
+    // initialize the display orientation transform.
+    setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
 }
 
 DisplayDevice::~DisplayDevice() {
@@ -121,55 +163,6 @@
     return mSurface;
 }
 
-void DisplayDevice::init(EGLConfig config)
-{
-    ANativeWindow* const window = mNativeWindow.get();
-
-    int format;
-    window->query(window, NATIVE_WINDOW_FORMAT, &format);
-
-    /*
-     * Create our display's surface
-     */
-
-    EGLSurface surface;
-    EGLint w, h;
-    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-    surface = eglCreateWindowSurface(display, config, window, NULL);
-    eglQuerySurface(display, surface, EGL_WIDTH,  &mDisplayWidth);
-    eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight);
-
-    mDisplay = display;
-    mSurface = surface;
-    mFormat  = format;
-    mPageFlipCount = 0;
-    mViewport.makeInvalid();
-    mFrame.makeInvalid();
-
-    // external displays are always considered enabled
-    mScreenAcquired = (mType >= DisplayDevice::NUM_DISPLAY_TYPES);
-
-    // get an h/w composer ID
-    mHwcDisplayId = mFlinger->allocateHwcDisplayId(mType);
-
-    // Name the display.  The name will be replaced shortly if the display
-    // was created with createDisplay().
-    switch (mType) {
-        case DISPLAY_PRIMARY:
-            mDisplayName = "Built-in Screen";
-            break;
-        case DISPLAY_EXTERNAL:
-            mDisplayName = "HDMI Screen";
-            break;
-        default:
-            mDisplayName = "Virtual Screen";    // e.g. Overlay #n
-            break;
-    }
-
-    // initialize the display orientation transform.
-    setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
-}
-
 void DisplayDevice::setDisplayName(const String8& displayName) {
     if (!displayName.isEmpty()) {
         // never override the name with an empty name
@@ -235,8 +228,7 @@
 
 void DisplayDevice::onSwapBuffersCompleted(HWComposer& hwc) const {
     if (hwc.initCheck() == NO_ERROR) {
-        sp<Fence> fence = hwc.getAndResetReleaseFence(mType);
-        mDisplaySurface->onFrameCommitted(fence);
+        mDisplaySurface->onFrameCommitted();
     }
 }
 
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index d8f55b4..d4a6daa 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -72,6 +72,7 @@
     DisplayDevice(
             const sp<SurfaceFlinger>& flinger,
             DisplayType type,
+            int32_t hwcId,  // negative for non-HWC-composited displays
             bool isSecure,
             const wp<IBinder>& displayToken,
             const sp<DisplaySurface>& displaySurface,
@@ -152,8 +153,6 @@
     void dump(String8& result, char* buffer, size_t SIZE) const;
 
 private:
-    void init(EGLConfig config);
-
     /*
      *  Constants, set during initialization
      */
diff --git a/services/surfaceflinger/DisplayHardware/DisplaySurface.h b/services/surfaceflinger/DisplayHardware/DisplaySurface.h
index bc717a9..2eca3cb 100644
--- a/services/surfaceflinger/DisplayHardware/DisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/DisplaySurface.h
@@ -49,10 +49,9 @@
     virtual status_t advanceFrame() = 0;
 
     // onFrameCommitted is called after the frame has been committed to the
-    // hardware composer and a release fence is available for the buffer.
-    // Further operations on the buffer can be queued as long as they wait for
-    // the fence to signal.
-    virtual void onFrameCommitted(const sp<Fence>& fence) = 0;
+    // hardware composer. The surface collects the release fence for this
+    // frame's buffer.
+    virtual void onFrameCommitted() = 0;
 
     virtual void dump(String8& result) const = 0;
 
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index c35ac95..1936893 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -140,7 +140,8 @@
     }
 }
 
-void FramebufferSurface::onFrameCommitted(const sp<Fence>& fence) {
+void FramebufferSurface::onFrameCommitted() {
+    sp<Fence> fence = mHwc.getAndResetReleaseFence(mDisplayType);
     if (fence->isValid() &&
             mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT) {
         status_t err = addReleaseFence(mCurrentBufferSlot, fence);
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index 164f81f..2fde789 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -43,7 +43,7 @@
 
     virtual status_t compositionComplete();
     virtual status_t advanceFrame();
-    virtual void onFrameCommitted(const sp<Fence>& fence);
+    virtual void onFrameCommitted();
 
     // Implementation of DisplaySurface::dump(). Note that ConsumerBase also
     // has a non-virtual dump() with the same signature.
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 9d32410..497593b 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -657,15 +657,12 @@
             mLists[0]->sur = eglGetCurrentSurface(EGL_DRAW);
         }
 
-        // For virtual displays, the framebufferTarget buffer also serves as
-        // the HWC output buffer, so we need to copy the buffer handle and
-        // dup() the acquire fence.
         for (size_t i=VIRTUAL_DISPLAY_ID_BASE; i<mNumDisplays; i++) {
             DisplayData& disp(mDisplayData[i]);
-            if (disp.framebufferTarget) {
-                mLists[i]->outbuf = disp.framebufferTarget->handle;
+            if (disp.outbufHandle) {
+                mLists[i]->outbuf = disp.outbufHandle;
                 mLists[i]->outbufAcquireFenceFd =
-                        dup(disp.framebufferTarget->acquireFenceFd);
+                        disp.outbufAcquireFence->dup();
             }
         }
 
@@ -706,17 +703,15 @@
 
 void HWComposer::disconnectDisplay(int disp) {
     LOG_ALWAYS_FATAL_IF(disp < 0 || disp == HWC_DISPLAY_PRIMARY);
-    if (disp >= HWC_NUM_DISPLAY_TYPES) {
-        // nothing to do for these yet
-        return;
-    }
     DisplayData& dd(mDisplayData[disp]);
-    if (dd.list != NULL) {
-        free(dd.list);
-        dd.list = NULL;
-        dd.framebufferTarget = NULL;    // points into dd.list
-        dd.fbTargetHandle = NULL;
-    }
+    free(dd.list);
+    dd.list = NULL;
+    dd.framebufferTarget = NULL;    // points into dd.list
+    dd.fbTargetHandle = NULL;
+    dd.outbufHandle = NULL;
+    dd.lastRetireFence = Fence::NO_FENCE;
+    dd.lastDisplayFence = Fence::NO_FENCE;
+    dd.outbufAcquireFence = Fence::NO_FENCE;
 }
 
 int HWComposer::getVisualID() const {
@@ -765,6 +760,25 @@
     }
 }
 
+status_t HWComposer::setOutputBuffer(int32_t id, const sp<Fence>& acquireFence,
+        const sp<GraphicBuffer>& buf) {
+    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+        return BAD_INDEX;
+    if (id < VIRTUAL_DISPLAY_ID_BASE)
+        return INVALID_OPERATION;
+
+    DisplayData& disp(mDisplayData[id]);
+    disp.outbufHandle = buf->handle;
+    disp.outbufAcquireFence = acquireFence;
+    return NO_ERROR;
+}
+
+sp<Fence> HWComposer::getLastRetireFence(int32_t id) {
+    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+        return Fence::NO_FENCE;
+    return mDisplayData[id].lastRetireFence;
+}
+
 /*
  * Helper template to implement a concrete HWCLayer
  * This holds the pointer to the concrete hwc layer type
@@ -1071,6 +1085,7 @@
     capacity(0), list(NULL),
     framebufferTarget(NULL), fbTargetHandle(0),
     lastRetireFence(Fence::NO_FENCE), lastDisplayFence(Fence::NO_FENCE),
+    outbufHandle(NULL), outbufAcquireFence(Fence::NO_FENCE),
     events(0)
 {}
 
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 346526a..58f7e8f 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -128,6 +128,17 @@
     int fbCompositionComplete();
     void fbDump(String8& result);
 
+    // Set the output buffer and acquire fence for a virtual display.
+    // Returns INVALID_OPERATION if id is not a virtual display.
+    status_t setOutputBuffer(int32_t id, const sp<Fence>& acquireFence,
+            const sp<GraphicBuffer>& buf);
+
+    // Get the retire fence for the last committed frame. This fence will
+    // signal when the h/w composer is completely finished with the frame.
+    // For physical displays, it is no longer being displayed. For virtual
+    // displays, writes to the output buffer are complete.
+    sp<Fence> getLastRetireFence(int32_t id);
+
     /*
      * Interface to hardware composer's layers functionality.
      * This abstracts the HAL interface to layers which can evolve in
@@ -306,6 +317,8 @@
         sp<Fence> lastRetireFence;  // signals when the last set op retires
         sp<Fence> lastDisplayFence; // signals when the last set op takes
                                     // effect on screen
+        buffer_handle_t outbufHandle;
+        sp<Fence> outbufAcquireFence;
 
         // protected by mEventControlLock
         int32_t events;
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 255b77f..d2b3edb 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -21,24 +21,30 @@
 namespace android {
 // ---------------------------------------------------------------------------
 
-VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int disp,
+VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId,
         const sp<IGraphicBufferProducer>& sink, const String8& name)
 :   mHwc(hwc),
-    mDisplayId(disp),
-    mSource(new BufferQueueInterposer(sink, name)),
+    mDisplayId(dispId),
     mName(name)
-{}
+{
+    if (mDisplayId >= 0) {
+        mInterposer = new BufferQueueInterposer(sink, name);
+        mSourceProducer = mInterposer;
+    } else {
+        mSourceProducer = sink;
+    }
+}
 
 VirtualDisplaySurface::~VirtualDisplaySurface() {
     if (mAcquiredBuffer != NULL) {
-        status_t result = mSource->releaseBuffer(Fence::NO_FENCE);
+        status_t result = mInterposer->releaseBuffer(Fence::NO_FENCE);
         ALOGE_IF(result != NO_ERROR, "VirtualDisplaySurface \"%s\": "
                 "failed to release buffer: %d", mName.string(), result);
     }
 }
 
 sp<IGraphicBufferProducer> VirtualDisplaySurface::getIGraphicBufferProducer() const {
-    return mSource;
+    return mSourceProducer;
 }
 
 status_t VirtualDisplaySurface::compositionComplete() {
@@ -46,6 +52,9 @@
 }
 
 status_t VirtualDisplaySurface::advanceFrame() {
+    if (mInterposer == NULL)
+        return NO_ERROR;
+
     Mutex::Autolock lock(mMutex);
     status_t result = NO_ERROR;
 
@@ -57,12 +66,12 @@
     }
 
     sp<Fence> fence;
-    result = mSource->acquireBuffer(&mAcquiredBuffer, &fence);
+    result = mInterposer->acquireBuffer(&mAcquiredBuffer, &fence);
     if (result == BufferQueueInterposer::NO_BUFFER_AVAILABLE) {
-        result = mSource->pullEmptyBuffer();
+        result = mInterposer->pullEmptyBuffer();
         if (result != NO_ERROR)
             return result;
-        result = mSource->acquireBuffer(&mAcquiredBuffer, &fence);
+        result = mInterposer->acquireBuffer(&mAcquiredBuffer, &fence);
     }
     if (result != NO_ERROR)
         return result;
@@ -70,10 +79,25 @@
     return mHwc.fbPost(mDisplayId, fence, mAcquiredBuffer);
 }
 
-void VirtualDisplaySurface::onFrameCommitted(const sp<Fence>& fence) {
+void VirtualDisplaySurface::onFrameCommitted() {
+    if (mInterposer == NULL)
+        return;
+
     Mutex::Autolock lock(mMutex);
     if (mAcquiredBuffer != NULL) {
-        status_t result = mSource->releaseBuffer(fence);
+        // fbFence signals when reads from the framebuffer are finished
+        // outFence signals when writes to the output buffer are finished
+        // It's unlikely that there will be an implementation where fbFence
+        // signals after outFence (in fact they'll typically be the same
+        // sync_pt), but just to be pedantic we merge them so the sink will
+        // be sure to wait until both are complete.
+        sp<Fence> fbFence = mHwc.getAndResetReleaseFence(mDisplayId);
+        sp<Fence> outFence = mHwc.getLastRetireFence(mDisplayId);
+        sp<Fence> fence = Fence::merge(
+                String8::format("HWC done: %.21s", mName.string()),
+                fbFence, outFence);
+
+        status_t result = mInterposer->releaseBuffer(fence);
         ALOGE_IF(result != NO_ERROR, "VirtualDisplaySurface \"%s\": "
                 "failed to release buffer: %d", mName.string(), result);
         mAcquiredBuffer.clear();
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index 1347680..0706e75 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -45,12 +45,18 @@
  * eglSwapBuffers doesn't immediately dequeue a buffer for the next frame,
  * since we can't rely on being able to dequeue more than one buffer at a time.
  *
+ * This class also has a passthrough mode, where it doesn't use a
+ * BufferQueueInterposer and never sends buffers to HWC. Instead, OpenGL ES
+ * output buffers are queued directly to the virtual display sink; this class
+ * is inactive after construction. This mode is used when the HWC doesn't
+ * support compositing for virtual displays.
+ *
  * TODO(jessehall): Add a libgui test that ensures that EGL/GLES do lazy
  * dequeBuffers; we've wanted to require that for other reasons anyway.
  */
 class VirtualDisplaySurface : public DisplaySurface {
 public:
-    VirtualDisplaySurface(HWComposer& hwc, int disp,
+    VirtualDisplaySurface(HWComposer& hwc, int32_t dispId,
             const sp<IGraphicBufferProducer>& sink,
             const String8& name);
 
@@ -58,7 +64,7 @@
 
     virtual status_t compositionComplete();
     virtual status_t advanceFrame();
-    virtual void onFrameCommitted(const sp<Fence>& fence);
+    virtual void onFrameCommitted();
     virtual void dump(String8& result) const;
 
 private:
@@ -66,10 +72,14 @@
 
     // immutable after construction
     HWComposer& mHwc;
-    int mDisplayId;
-    sp<BufferQueueInterposer> mSource;
+    int32_t mDisplayId;
     String8 mName;
 
+    // with HWC support, both of these point to the same object.
+    // otherwise, mInterposer is NULL and mSourceProducer is the sink.
+    sp<BufferQueueInterposer> mInterposer;
+    sp<IGraphicBufferProducer> mSourceProducer;
+
     // mutable, must be synchronized with mMutex
     Mutex mMutex;
     sp<GraphicBuffer> mAcquiredBuffer;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 0e5d602..0a210f7 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -510,7 +510,8 @@
             wp<IBinder> token = mBuiltinDisplays[i];
 
             sp<DisplayDevice> hw = new DisplayDevice(this,
-                    type, isSecure, token, new FramebufferSurface(*mHwc, i),
+                    type, allocateHwcDisplayId(type), isSecure, token,
+                    new FramebufferSurface(*mHwc, i),
                     mEGLConfig);
             if (i > DisplayDevice::DISPLAY_PRIMARY) {
                 // FIXME: currently we don't get blank/unblank requests
@@ -1149,10 +1150,11 @@
                     const DisplayDeviceState& state(curr[i]);
 
                     sp<DisplaySurface> dispSurface;
+                    int32_t hwcDisplayId = allocateHwcDisplayId(state.type);
                     if (state.isVirtualDisplay()) {
                         if (state.surface != NULL) {
                             dispSurface = new VirtualDisplaySurface(
-                                    *mHwc, state.type, state.surface,
+                                    *mHwc, hwcDisplayId, state.surface,
                                     state.displayName);
                         }
                     } else {
@@ -1169,8 +1171,8 @@
                     const wp<IBinder>& display(curr.keyAt(i));
                     if (dispSurface != NULL) {
                         sp<DisplayDevice> hw = new DisplayDevice(this,
-                                state.type, state.isSecure, display,
-                                dispSurface, mEGLConfig);
+                                state.type, hwcDisplayId, state.isSecure,
+                                display, dispSurface, mEGLConfig);
                         hw->setLayerStack(state.layerStack);
                         hw->setProjection(state.orientation,
                                 state.viewport, state.frame);
@@ -2381,9 +2383,21 @@
 }
 
 const Vector< sp<Layer> >&
-SurfaceFlinger::getLayerSortedByZForHwcDisplay(int disp) {
+SurfaceFlinger::getLayerSortedByZForHwcDisplay(int id) {
     // Note: mStateLock is held here
-    return getDisplayDevice( getBuiltInDisplay(disp) )->getVisibleLayersSortedByZ();
+    wp<IBinder> dpy;
+    for (size_t i=0 ; i<mDisplays.size() ; i++) {
+        if (mDisplays.valueAt(i)->getHwcDisplayId() == id) {
+            dpy = mDisplays.keyAt(i);
+            break;
+        }
+    }
+    if (dpy == NULL) {
+        ALOGE("getLayerSortedByZForHwcDisplay: invalid hwc display id %d", id);
+        // Just use the primary display so we have something to return
+        dpy = getBuiltInDisplay(DisplayDevice::DISPLAY_PRIMARY);
+    }
+    return getDisplayDevice(dpy)->getVisibleLayersSortedByZ();
 }
 
 bool SurfaceFlinger::startDdmConnection()
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 1017560..f0e6deb 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -122,7 +122,7 @@
 
     // for debugging only
     // TODO: this should be made accessible only to HWComposer
-    const Vector< sp<Layer> >& getLayerSortedByZForHwcDisplay(int disp);
+    const Vector< sp<Layer> >& getLayerSortedByZForHwcDisplay(int id);
 
 private:
     friend class Client;