Merge "Actually set the virtual display output buffer." into jb-mr2-dev
diff --git a/include/media/drm/DrmAPI.h b/include/media/drm/DrmAPI.h
index 81d1ec0..c89f2d6 100644
--- a/include/media/drm/DrmAPI.h
+++ b/include/media/drm/DrmAPI.h
@@ -22,6 +22,7 @@
 #include <utils/Vector.h>
 #include <utils/KeyedVector.h>
 #include <utils/RefBase.h>
+#include <utils/Mutex.h>
 #include <media/stagefright/foundation/ABase.h>
 
 //  Loadable DrmEngine shared libraries should define the entry points
@@ -34,7 +35,8 @@
 
 namespace android {
 
-    struct DrmPlugin;
+    class DrmPlugin;
+    class DrmPluginListener;
 
     // DRMs are implemented in DrmEngine plugins, which are dynamically
     // loadable shared libraries that implement the entry points
@@ -70,7 +72,7 @@
     class DrmPlugin {
     public:
         enum EventType {
-            kDrmPluginEventProvisionRequired,
+            kDrmPluginEventProvisionRequired = 1,
             kDrmPluginEventKeyNeeded,
             kDrmPluginEventKeyExpired,
             kDrmPluginEventVendorDefined
@@ -261,12 +263,46 @@
                                 bool &match) = 0;
 
 
+        status_t setListener(const sp<DrmPluginListener>& listener) {
+            Mutex::Autolock lock(mEventLock);
+            mListener = listener;
+            return OK;
+        }
 
-        // TODO: provide way to send an event
+    protected:
+        // Plugins call sendEvent to deliver events to the java app
+        void sendEvent(EventType eventType, int extra,
+                       Vector<uint8_t> const *sessionId,
+                       Vector<uint8_t> const *data);
+
     private:
+        Mutex mEventLock;
+        sp<DrmPluginListener> mListener;
+
         DISALLOW_EVIL_CONSTRUCTORS(DrmPlugin);
     };
 
+    class DrmPluginListener: virtual public RefBase
+    {
+    public:
+        virtual void sendEvent(DrmPlugin::EventType eventType, int extra,
+                               Vector<uint8_t> const *sesionId,
+                               Vector<uint8_t> const *data) = 0;
+    };
+
+    inline void DrmPlugin::sendEvent(EventType eventType, int extra,
+                                     Vector<uint8_t> const *sessionId,
+                                     Vector<uint8_t> const *data) {
+
+        mEventLock.lock();
+        sp<DrmPluginListener> listener = mListener;
+        mEventLock.unlock();
+
+        if (listener != NULL) {
+            listener->sendEvent(eventType, extra, sessionId, data);
+        }
+    }
+
 }  // namespace android
 
 #endif // DRM_API_H_
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 9ee3686..00bfa5a 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -27,9 +27,9 @@
 
 #include <EGL/egl.h>
 
+#include "../glestrace.h"
+
 #include "egldefs.h"
-#include "glestrace.h"
-#include "hooks.h"
 #include "Loader.h"
 
 // ----------------------------------------------------------------------------
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index a6e91e0..6ac8724 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -32,11 +32,11 @@
 #include <utils/CallStack.h>
 #include <utils/String8.h>
 
-#include "egldefs.h"
-#include "egl_impl.h"
+#include "../egl_impl.h"
+#include "../glestrace.h"
+
 #include "egl_tls.h"
-#include "glestrace.h"
-#include "hooks.h"
+#include "egldefs.h"
 #include "Loader.h"
 
 #include "egl_display.h"
@@ -387,7 +387,7 @@
 #define EGL_ENTRY(_r, _api, ...) #_api,
 
 char const * const gl_names[] = {
-    #include "entries.in"
+    #include "../entries.in"
     NULL
 };
 
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 1be4961..f6bc069 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -37,13 +37,11 @@
 #include <utils/String8.h>
 #include <utils/Trace.h>
 
-#include "egl_impl.h"
-#include "egl_tls.h"
-#include "glestrace.h"
-#include "hooks.h"
+#include "../egl_impl.h"
+#include "../glestrace.h"
+#include "../hooks.h"
 
 #include "egl_display.h"
-#include "egl_impl.h"
 #include "egl_object.h"
 #include "egl_tls.h"
 #include "egldefs.h"
diff --git a/opengl/libs/EGL/egl_cache.cpp b/opengl/libs/EGL/egl_cache.cpp
index 72655df..03397a9 100644
--- a/opengl/libs/EGL/egl_cache.cpp
+++ b/opengl/libs/EGL/egl_cache.cpp
@@ -14,9 +14,10 @@
  ** limitations under the License.
  */
 
+#include "../egl_impl.h"
+
 #include "egl_cache.h"
 #include "egl_display.h"
-#include "egl_impl.h"
 #include "egldefs.h"
 
 #include <fcntl.h>
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 59dd2d9..1955904 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -18,11 +18,12 @@
 
 #include <string.h>
 
+#include "../egl_impl.h"
+
 #include "egl_cache.h"
 #include "egl_display.h"
 #include "egl_object.h"
 #include "egl_tls.h"
-#include "egl_impl.h"
 #include "Loader.h"
 #include <cutils/properties.h>
 
diff --git a/opengl/libs/EGL/egl_display.h b/opengl/libs/EGL/egl_display.h
index 8bb32f4..754085c 100644
--- a/opengl/libs/EGL/egl_display.h
+++ b/opengl/libs/EGL/egl_display.h
@@ -31,7 +31,7 @@
 #include <utils/String8.h>
 
 #include "egldefs.h"
-#include "hooks.h"
+#include "../hooks.h"
 
 // ----------------------------------------------------------------------------
 namespace android {
diff --git a/opengl/libs/EGL/egl_tls.h b/opengl/libs/EGL/egl_tls.h
index 2442ca0..56c5dba 100644
--- a/opengl/libs/EGL/egl_tls.h
+++ b/opengl/libs/EGL/egl_tls.h
@@ -22,7 +22,6 @@
 #include <EGL/egl.h>
 
 #include "egldefs.h"
-#include "hooks.h"
 
 // ----------------------------------------------------------------------------
 namespace android {
diff --git a/opengl/libs/EGL/egldefs.h b/opengl/libs/EGL/egldefs.h
index c900c1c..1cfe561 100644
--- a/opengl/libs/EGL/egldefs.h
+++ b/opengl/libs/EGL/egldefs.h
@@ -17,7 +17,7 @@
 #ifndef ANDROID_EGLDEFS_H
 #define ANDROID_EGLDEFS_H
 
-#include "hooks.h"
+#include "../hooks.h"
 
 #define VERSION_MAJOR 1
 #define VERSION_MINOR 4
diff --git a/opengl/libs/EGL/getProcAddress.cpp b/opengl/libs/EGL/getProcAddress.cpp
index 1909232..c160aa0 100644
--- a/opengl/libs/EGL/getProcAddress.cpp
+++ b/opengl/libs/EGL/getProcAddress.cpp
@@ -21,7 +21,6 @@
 #include <cutils/log.h>
 
 #include "egldefs.h"
-#include "hooks.h"
 
 // ----------------------------------------------------------------------------
 namespace android {
diff --git a/opengl/libs/GLES2/gl2.cpp b/opengl/libs/GLES2/gl2.cpp
index dd454bd..fad2176 100644
--- a/opengl/libs/GLES2/gl2.cpp
+++ b/opengl/libs/GLES2/gl2.cpp
@@ -27,8 +27,8 @@
 #include <cutils/log.h>
 #include <cutils/properties.h>
 
-#include "hooks.h"
-#include "egl_impl.h"
+#include "../hooks.h"
+#include "../egl_impl.h"
 
 using namespace android;
 
diff --git a/opengl/libs/GLES_CM/gl.cpp b/opengl/libs/GLES_CM/gl.cpp
index 8ac8ff9..a5bbdc6 100644
--- a/opengl/libs/GLES_CM/gl.cpp
+++ b/opengl/libs/GLES_CM/gl.cpp
@@ -26,8 +26,8 @@
 #include <cutils/log.h>
 #include <cutils/properties.h>
 
-#include "hooks.h"
-#include "egl_impl.h"
+#include "../hooks.h"
+#include "../egl_impl.h"
 
 using namespace android;
 
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 6936a7f..68b0b7f 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -143,6 +143,15 @@
     }
 }
 
+void DisplayDevice::disconnect(HWComposer& hwc) {
+    if (mHwcDisplayId >= 0) {
+        hwc.disconnectDisplay(mHwcDisplayId);
+        if (mHwcDisplayId >= DISPLAY_VIRTUAL)
+            hwc.freeDisplayId(mHwcDisplayId);
+        mHwcDisplayId = -1;
+    }
+}
+
 bool DisplayDevice::isValid() const {
     return mFlinger != NULL;
 }
@@ -419,11 +428,11 @@
     const Transform& tr(mGlobalTransform);
     snprintf(buffer, SIZE,
         "+ DisplayDevice: %s\n"
-        "   type=%x, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), "
+        "   type=%x, hwcId=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), "
         "flips=%u, isSecure=%d, secureVis=%d, acquired=%d, numLayers=%u\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,
+        mDisplayName.string(), mType, mHwcDisplayId,
         mLayerStack, mDisplayWidth, mDisplayHeight, mNativeWindow.get(),
         mOrientation, tr.getType(), getPageFlipCount(),
         mIsSecure, mSecureLayerVisible, mScreenAcquired, mVisibleLayersSortedByZ.size(),
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index d4a6daa..377d924 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -146,6 +146,9 @@
     bool isScreenAcquired() const;
     bool canDraw() const;
 
+    // release HWC resources (if any) for removable displays
+    void disconnect(HWComposer& hwc);
+
     /* ------------------------------------------------------------------------
      * Debugging
      */
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index a68ddd8..a29c068 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -954,17 +954,17 @@
         result.appendFormat("  mDebugForceFakeVSync=%d\n", mDebugForceFakeVSync);
         for (size_t i=0 ; i<mNumDisplays ; i++) {
             const DisplayData& disp(mDisplayData[i]);
+            if (!disp.connected)
+                continue;
 
             const Vector< sp<Layer> >& visibleLayersSortedByZ =
                     mFlinger->getLayerSortedByZForHwcDisplay(i);
 
-            if (disp.connected) {
-                result.appendFormat(
-                        "  Display[%d] : %ux%u, xdpi=%f, ydpi=%f, refresh=%lld\n",
-                        i, disp.width, disp.height, disp.xdpi, disp.ydpi, disp.refresh);
-            }
+            result.appendFormat(
+                    "  Display[%d] : %ux%u, xdpi=%f, ydpi=%f, refresh=%lld\n",
+                    i, disp.width, disp.height, disp.xdpi, disp.ydpi, disp.refresh);
 
-            if (disp.list && disp.connected) {
+            if (disp.list) {
                 result.appendFormat(
                         "  numHwLayers=%u, flags=%08x\n",
                         disp.list->numHwLayers, disp.list->flags);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 5c7cf07..9102f5c 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1102,12 +1102,14 @@
                         // Call makeCurrent() on the primary display so we can
                         // be sure that nothing associated with this display
                         // is current.
-                        const sp<const DisplayDevice> hw(getDefaultDisplayDevice());
-                        DisplayDevice::makeCurrent(mEGLDisplay, hw, mEGLContext);
-                        mDisplays.removeItem(draw.keyAt(i));
-                        getHwComposer().disconnectDisplay(draw[i].type);
+                        const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDevice());
+                        DisplayDevice::makeCurrent(mEGLDisplay, defaultDisplay, mEGLContext);
+                        sp<DisplayDevice> hw(getDisplayDevice(draw.keyAt(i)));
+                        if (hw != NULL)
+                            hw->disconnect(getHwComposer());
                         if (draw[i].type < DisplayDevice::NUM_DISPLAY_TYPES)
                             mEventThread->onHotplugReceived(draw[i].type, false);
+                        mDisplays.removeItem(draw.keyAt(i));
                     } else {
                         ALOGW("trying to remove the main display");
                     }
@@ -1120,6 +1122,9 @@
                         // recreating the DisplayDevice, so we just remove it
                         // from the drawing state, so that it get re-added
                         // below.
+                        sp<DisplayDevice> hw(getDisplayDevice(display));
+                        if (hw != NULL)
+                            hw->disconnect(getHwComposer());
                         mDisplays.removeItem(display);
                         mDrawingState.displays.removeItemsAt(i);
                         dc--; i--;
@@ -1150,9 +1155,13 @@
                     const DisplayDeviceState& state(curr[i]);
 
                     sp<DisplaySurface> dispSurface;
-                    int32_t hwcDisplayId = allocateHwcDisplayId(state.type);
+                    int32_t hwcDisplayId = -1;
                     if (state.isVirtualDisplay()) {
+                        // Virtual displays without a surface are dormant:
+                        // they have external state (layer stack, projection,
+                        // etc.) but no internal state (i.e. a DisplayDevice).
                         if (state.surface != NULL) {
+                            hwcDisplayId = allocateHwcDisplayId(state.type);
                             dispSurface = new VirtualDisplaySurface(
                                     *mHwc, hwcDisplayId, state.surface,
                                     state.displayName);
@@ -1162,7 +1171,7 @@
                                 "adding a supported display, but rendering "
                                 "surface is provided (%p), ignoring it",
                                 state.surface.get());
-
+                        hwcDisplayId = allocateHwcDisplayId(state.type);
                         // for supported (by hwc) displays we provide our
                         // own rendering surface
                         dispSurface = new FramebufferSurface(*mHwc, state.type);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index f0e6deb..57ee8b9 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -108,9 +108,6 @@
     // utility function to delete a texture on the main thread
     void deleteTextureAsync(GLuint texture);
 
-    // allocate a h/w composer display id
-    int32_t allocateHwcDisplayId(DisplayDevice::DisplayType type);
-
     // enable/disable h/w composer event
     // TODO: this should be made accessible only to EventThread
     void eventControl(int disp, int event, int enabled);
@@ -338,6 +335,9 @@
     // region of all screens presenting this layer stack.
     void invalidateLayerStack(uint32_t layerStack, const Region& dirty);
 
+    // allocate a h/w composer display id
+    int32_t allocateHwcDisplayId(DisplayDevice::DisplayType type);
+
     /* ------------------------------------------------------------------------
      * H/W composer
      */