Merge "Add a very simple helper function to log slow functions." into jb-mr1-dev
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
index 33b2f00..877b17c 100644
--- a/include/binder/Parcel.h
+++ b/include/binder/Parcel.h
@@ -22,10 +22,12 @@
 #include <utils/RefBase.h>
 #include <utils/String16.h>
 #include <utils/Vector.h>
+#include <utils/Flattenable.h>
 
 // ---------------------------------------------------------------------------
 namespace android {
 
+template <typename T> class LightFlattenable;
 class Flattenable;
 class IBinder;
 class IPCThreadState;
@@ -102,6 +104,10 @@
     status_t            writeWeakBinder(const wp<IBinder>& val);
     status_t            write(const Flattenable& val);
 
+    template<typename T>
+    status_t            write(const LightFlattenable<T>& val);
+
+
     // Place a native_handle into the parcel (the native_handle's file-
     // descriptors are dup'ed, so it is safe to delete the native_handle
     // when this function returns). 
@@ -153,6 +159,9 @@
     wp<IBinder>         readWeakBinder() const;
     status_t            read(Flattenable& val) const;
 
+    template<typename T>
+    status_t            read(LightFlattenable<T>& val) const;
+
     // Like Parcel.java's readExceptionCode().  Reads the first int32
     // off of a Parcel's header, returning 0 or the negative error
     // code on exceptions, but also deals with skipping over rich
@@ -267,6 +276,40 @@
 
 // ---------------------------------------------------------------------------
 
+template<typename T>
+status_t Parcel::write(const LightFlattenable<T>& val) {
+    size_t size(val.getSize());
+    if (!val.isFixedSize()) {
+        status_t err = writeInt32(size);
+        if (err != NO_ERROR) {
+            return err;
+        }
+    }
+    void* buffer = writeInplace(size);
+    return buffer == NULL ? NO_MEMORY :
+        val.flatten(buffer);
+}
+
+template<typename T>
+status_t Parcel::read(LightFlattenable<T>& val) const {
+    size_t size;
+    if (val.isFixedSize()) {
+        size = val.getSize();
+    } else {
+        int32_t s;
+        status_t err = readInt32(&s);
+        if (err != NO_ERROR) {
+            return err;
+        }
+        size = s;
+    }
+    void const* buffer = readInplace(size);
+    return buffer == NULL ? NO_MEMORY :
+        val.unflatten(buffer, size);
+}
+
+// ---------------------------------------------------------------------------
+
 inline TextOutput& operator<<(TextOutput& to, const Parcel& parcel)
 {
     parcel.print(to);
diff --git a/include/gui/Sensor.h b/include/gui/Sensor.h
index e59757a..2af2307 100644
--- a/include/gui/Sensor.h
+++ b/include/gui/Sensor.h
@@ -41,7 +41,7 @@
 
 // ----------------------------------------------------------------------------
 
-class Sensor : public ASensor, public Flattenable
+class Sensor : public ASensor, public LightFlattenable<Sensor>
 {
 public:
     enum {
@@ -54,7 +54,7 @@
 
             Sensor();
             Sensor(struct sensor_t const* hwSensor);
-    virtual ~Sensor();
+            ~Sensor();
 
     const String8& getName() const;
     const String8& getVendor() const;
@@ -68,13 +68,11 @@
     nsecs_t getMinDelayNs() const;
     int32_t getVersion() const;
 
-    // Flattenable interface
-    virtual size_t getFlattenedSize() const;
-    virtual size_t getFdCount() const;
-    virtual status_t flatten(void* buffer, size_t size,
-            int fds[], size_t count) const;
-    virtual status_t unflatten(void const* buffer, size_t size,
-            int fds[], size_t count);
+    // LightFlattenable protocol
+    inline bool isFixedSize() const { return false; }
+    size_t getSize() const;
+    status_t flatten(void* buffer) const;
+    status_t unflatten(void const* buffer, size_t size);
 
 private:
     String8 mName;
diff --git a/include/ui/Point.h b/include/ui/Point.h
index 1653120..1d7f64d 100644
--- a/include/ui/Point.h
+++ b/include/ui/Point.h
@@ -17,11 +17,12 @@
 #ifndef ANDROID_UI_POINT
 #define ANDROID_UI_POINT
 
+#include <utils/Flattenable.h>
 #include <utils/TypeHelpers.h>
 
 namespace android {
 
-class Point
+class Point : public LightFlattenablePod<Point>
 {
 public:
     int x;
diff --git a/include/ui/Rect.h b/include/ui/Rect.h
index c2c2675..47d37b6 100644
--- a/include/ui/Rect.h
+++ b/include/ui/Rect.h
@@ -17,6 +17,7 @@
 #ifndef ANDROID_UI_RECT
 #define ANDROID_UI_RECT
 
+#include <utils/Flattenable.h>
 #include <utils/TypeHelpers.h>
 #include <ui/Point.h>
 
@@ -24,7 +25,7 @@
 
 namespace android {
 
-class Rect : public ARect
+class Rect : public ARect, public LightFlattenablePod<Rect>
 {
 public:
     typedef ARect::value_type value_type;
diff --git a/include/ui/Region.h b/include/ui/Region.h
index f242f18..f0819af 100644
--- a/include/ui/Region.h
+++ b/include/ui/Region.h
@@ -23,6 +23,7 @@
 #include <utils/Vector.h>
 
 #include <ui/Rect.h>
+#include <utils/Flattenable.h>
 
 namespace android {
 // ---------------------------------------------------------------------------
@@ -30,13 +31,12 @@
 class String8;
 
 // ---------------------------------------------------------------------------
-class Region
+class Region : public LightFlattenable<Region>
 {
 public:
                         Region();
                         Region(const Region& rhs);
     explicit            Region(const Rect& rhs);
-    explicit            Region(const void* buffer);
                         ~Region();
                         
         Region& operator = (const Region& rhs);
@@ -122,12 +122,10 @@
             // be sorted in Y and X and must not make the region invalid.
             void        addRectUnchecked(int l, int t, int r, int b);
 
-            // flatten/unflatten a region to/from a raw buffer
-            ssize_t     write(void* buffer, size_t size) const;
-    static  ssize_t     writeEmpty(void* buffer, size_t size);
-
-            ssize_t     read(const void* buffer);
-    static  bool        isEmpty(void* buffer);
+    inline  bool        isFixedSize() const { return false; }
+            size_t      getSize() const;
+            status_t    flatten(void* buffer) const;
+            status_t    unflatten(void const* buffer, size_t size);
 
     void        dump(String8& out, const char* what, uint32_t flags=0) const;
     void        dump(const char* what, uint32_t flags=0) const;
diff --git a/include/utils/Flattenable.h b/include/utils/Flattenable.h
index 852be3b..e40d289 100644
--- a/include/utils/Flattenable.h
+++ b/include/utils/Flattenable.h
@@ -24,6 +24,11 @@
 
 namespace android {
 
+/*
+ * The Flattenable interface allows an object to serialize itself out
+ * to a byte-buffer and an array of file descriptors.
+ */
+
 class Flattenable
 {
 public:
@@ -56,6 +61,73 @@
 
 };
 
+/*
+ * LightFlattenable is a protocol allowing object to serialize themselves out
+ * to a byte-buffer.
+ *
+ * LightFlattenable objects must implement this protocol.
+ *
+ * LightFlattenable doesn't require the object to be virtual.
+ */
+template <typename T>
+class LightFlattenable {
+public:
+    // returns whether this object always flatten into the same size.
+    // for efficiency, this should always be inline.
+    inline bool isFixedSize() const;
+
+    // returns size in bytes of the flattened object. must be a constant.
+    inline size_t getSize() const;
+
+    // flattens the object into buffer.
+    inline status_t flatten(void* buffer) const;
+
+    // unflattens the object from buffer of given size.
+    inline status_t unflatten(void const* buffer, size_t size);
+};
+
+template <typename T>
+inline bool LightFlattenable<T>::isFixedSize() const {
+    return static_cast<T const*>(this)->T::isFixedSize();
+}
+template <typename T>
+inline size_t LightFlattenable<T>::getSize() const {
+    return static_cast<T const*>(this)->T::getSize();
+}
+template <typename T>
+inline status_t LightFlattenable<T>::flatten(void* buffer) const {
+    return static_cast<T const*>(this)->T::flatten(buffer);
+}
+template <typename T>
+inline status_t LightFlattenable<T>::unflatten(void const* buffer, size_t size) {
+    return static_cast<T*>(this)->T::unflatten(buffer, size);
+}
+
+/*
+ * LightFlattenablePod is an implementation of the LightFlattenable protocol
+ * for POD (plain-old-data) objects.
+ */
+template <typename T>
+class LightFlattenablePod : public LightFlattenable<T> {
+public:
+    inline bool isFixedSize() const {
+        return true;
+    }
+
+    inline size_t getSize() const {
+        return sizeof(T);
+    }
+    inline status_t flatten(void* buffer) const {
+        *reinterpret_cast<T*>(buffer) = *static_cast<T const*>(this);
+        return NO_ERROR;
+    }
+    inline status_t unflatten(void const* buffer, size_t) {
+        *static_cast<T*>(this) = *reinterpret_cast<T const*>(buffer);
+        return NO_ERROR;
+    }
+};
+
+
 }; // namespace android
 
 
diff --git a/libs/gui/ISensorServer.cpp b/libs/gui/ISensorServer.cpp
index 7111092..0b76f37 100644
--- a/libs/gui/ISensorServer.cpp
+++ b/libs/gui/ISensorServer.cpp
@@ -55,7 +55,7 @@
         int32_t n = reply.readInt32();
         v.setCapacity(n);
         while (n--) {
-            reply.read(static_cast<Flattenable&>(s));
+            reply.read(s);
             v.add(s);
         }
         return v;
@@ -84,7 +84,7 @@
             size_t n = v.size();
             reply->writeInt32(n);
             for (size_t i=0 ; i<n ; i++) {
-                reply->write(static_cast<const Flattenable&>(v[i]));
+                reply->write(v[i]);
             }
             return NO_ERROR;
         } break;
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 07f62c4..e2604f8 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -26,14 +26,7 @@
 {
     status_t err;
 
-    size_t len = transparentRegion.write(NULL, 0);
-    err = output.writeInt32(len);
-    if (err < NO_ERROR) return err;
-
-    void* buf = output.writeInplace(len);
-    if (buf == NULL) return NO_MEMORY;
-
-    err = transparentRegion.write(buf, len);
+    err = output.write(transparentRegion);
     if (err < NO_ERROR) return err;
 
     // NOTE: regions are at the end of the structure
@@ -46,11 +39,8 @@
 status_t layer_state_t::read(const Parcel& input)
 {
     status_t err;
-    size_t len = input.readInt32();
-    void const* buf = input.readInplace(len);
-    if (buf == NULL) return NO_MEMORY;
 
-    err = transparentRegion.read(buf);
+    err = input.read(transparentRegion);
     if (err < NO_ERROR) return err;
 
     // NOTE: regions are at the end of the structure
@@ -77,8 +67,8 @@
     output.writeInt32(what);
     output.writeInt32(layerStack);
     output.writeInt32(orientation);
-    memcpy(output.writeInplace(sizeof(Rect)), &viewport, sizeof(Rect));
-    memcpy(output.writeInplace(sizeof(Rect)), &frame, sizeof(Rect));
+    output.write(viewport);
+    output.write(frame);
     return NO_ERROR;
 }
 
@@ -88,8 +78,8 @@
     what = input.readInt32();
     layerStack = input.readInt32();
     orientation = input.readInt32();
-    memcpy(&viewport, input.readInplace(sizeof(Rect)), sizeof(Rect));
-    memcpy(&frame,    input.readInplace(sizeof(Rect)), sizeof(Rect));
+    input.read(viewport);
+    input.read(frame);
     return NO_ERROR;
 }
 
diff --git a/libs/gui/Sensor.cpp b/libs/gui/Sensor.cpp
index 5cc76b4..c52a88f 100644
--- a/libs/gui/Sensor.cpp
+++ b/libs/gui/Sensor.cpp
@@ -98,7 +98,7 @@
     return mVersion;
 }
 
-size_t Sensor::getFlattenedSize() const
+size_t Sensor::getSize() const
 {
     return  sizeof(int32_t) + ((mName.length() + 3) & ~3) +
             sizeof(int32_t) + ((mVendor.length() + 3) & ~3) +
@@ -107,11 +107,6 @@
             sizeof(int32_t);
 }
 
-size_t Sensor::getFdCount() const
-{
-    return 0;
-}
-
 static inline
 size_t write(void* buffer, size_t offset, const String8& value) {
     memcpy(static_cast<char*>(buffer) + offset, value.string(), value.length());
@@ -130,12 +125,8 @@
     return sizeof(int32_t);
 }
 
-status_t Sensor::flatten(void* buffer, size_t size,
-        int fds[], size_t count) const
+status_t Sensor::flatten(void* buffer) const
 {
-    if (size < Sensor::getFlattenedSize())
-        return -ENOMEM;
-
     size_t offset = 0;
     offset += write(buffer, offset, int32_t(mName.length()));
     offset += write(buffer, offset, mName);
@@ -149,7 +140,6 @@
     offset += write(buffer, offset, mResolution);
     offset += write(buffer, offset, mPower);
     offset += write(buffer, offset, mMinDelay);
-
     return NO_ERROR;
 }
 
@@ -171,8 +161,7 @@
     return sizeof(int32_t);
 }
 
-status_t Sensor::unflatten(void const* buffer, size_t size,
-        int fds[], size_t count)
+status_t Sensor::unflatten(void const* buffer, size_t size)
 {
     int32_t len;
     size_t offset = 0;
@@ -188,7 +177,6 @@
     offset += read(buffer, offset, &mResolution);
     offset += read(buffer, offset, &mPower);
     offset += read(buffer, offset, &mMinDelay);
-
     return NO_ERROR;
 }
 
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index 2c7cdf0..a3d8b01 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -66,12 +66,6 @@
 {
 }
 
-Region::Region(const void* buffer)
-{
-    status_t err = read(buffer);
-    ALOGE_IF(err<0, "error %s reading Region from buffer", strerror(err));
-}
-
 Region::~Region()
 {
 }
@@ -561,55 +555,33 @@
 
 // ----------------------------------------------------------------------------
 
-ssize_t Region::write(void* buffer, size_t size) const
-{
-#if VALIDATE_REGIONS
-    validate(*this, "write(buffer)");
-#endif
-    const size_t count = mStorage.size();
-    const size_t sizeNeeded = sizeof(int32_t) + (1+count)*sizeof(Rect);
-    if (buffer != NULL) {
-        if (sizeNeeded > size) return NO_MEMORY;
-        int32_t* const p = static_cast<int32_t*>(buffer);
-        *p = count;
-        memcpy(p+1, &mBounds, sizeof(Rect));
-        if (count) {
-            memcpy(p+5, mStorage.array(), count*sizeof(Rect));
+size_t Region::getSize() const {
+    return (mStorage.size() + 1) * sizeof(Rect);
+}
+
+status_t Region::flatten(void* buffer) const {
+    Rect* rects = reinterpret_cast<Rect*>(buffer);
+    *rects++ = mBounds;
+    memcpy(rects, mStorage.array(), mStorage.size() * sizeof(Rect));
+    return NO_ERROR;
+}
+
+status_t Region::unflatten(void const* buffer, size_t size) {
+    mStorage.clear();
+    if (size >= sizeof(Rect)) {
+        Rect const* rects = reinterpret_cast<Rect const*>(buffer);
+        mBounds = *rects++;
+        size -= sizeof(Rect);
+        size_t count = size / sizeof(Rect);
+        if (count > 0) {
+            ssize_t err = mStorage.insertAt(0, count);
+            if (err < 0) {
+                return status_t(err);
+            }
+            memcpy(mStorage.editArray(), rects, count*sizeof(Rect));
         }
     }
-    return ssize_t(sizeNeeded);
-}
-
-ssize_t Region::read(const void* buffer)
-{
-    int32_t const* const p = static_cast<int32_t const*>(buffer); 
-    const size_t count = *p;
-    memcpy(&mBounds, p+1, sizeof(Rect));
-    mStorage.clear();
-    if (count) {
-        mStorage.insertAt(0, count);
-        memcpy(mStorage.editArray(), p+5, count*sizeof(Rect));
-    }
-#if VALIDATE_REGIONS
-    validate(*this, "read(buffer)");
-#endif
-    return ssize_t(sizeof(int32_t) + (1+count)*sizeof(Rect));
-}
-
-ssize_t Region::writeEmpty(void* buffer, size_t size)
-{
-    const size_t sizeNeeded = sizeof(int32_t) + sizeof(Rect);
-    if (sizeNeeded > size) return NO_MEMORY;
-    int32_t* const p = static_cast<int32_t*>(buffer); 
-    memset(p, 0, sizeNeeded);
-    return ssize_t(sizeNeeded);
-}
-
-bool Region::isEmpty(void* buffer)
-{
-    int32_t const* const p = static_cast<int32_t const*>(buffer); 
-    Rect const* const b = reinterpret_cast<Rect const *>(p+1);
-    return b->isEmpty();
+    return NO_ERROR;
 }
 
 // ----------------------------------------------------------------------------
diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk
index 42aaa24..eea79f8 100644
--- a/opengl/libs/Android.mk
+++ b/opengl/libs/Android.mk
@@ -122,7 +122,7 @@
 	GLES2/gl2.cpp.arm 	\
 #
 
-LOCAL_SHARED_LIBRARIES += libcutils libEGL
+LOCAL_SHARED_LIBRARIES += libcutils libutils libEGL
 LOCAL_LDLIBS := -lpthread -ldl
 LOCAL_MODULE:= libGLESv2
 
diff --git a/opengl/libs/GLES2/gl2.cpp b/opengl/libs/GLES2/gl2.cpp
index 4345c2b..b00af1b 100644
--- a/opengl/libs/GLES2/gl2.cpp
+++ b/opengl/libs/GLES2/gl2.cpp
@@ -26,6 +26,9 @@
 #include <cutils/log.h>
 #include <cutils/properties.h>
 
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+#include <utils/Trace.h>
+
 #include "hooks.h"
 #include "egl_impl.h"
 
@@ -40,6 +43,7 @@
 #undef CALL_GL_API_RETURN
 
 #define DEBUG_CALL_GL_API 0
+#define SYSTRACE_CALL_GL_API 0
 
 #if USE_FAST_TLS_KEY
 
@@ -86,6 +90,13 @@
             ALOGD("[" #_api "] 0x%x", status); \
         }
 
+#elif SYSTRACE_CALL_GL_API
+
+    #define CALL_GL_API(_api, ...)                                       \
+        ATRACE_CALL();                                                   \
+        gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;  \
+        _c->_api(__VA_ARGS__);
+
 #else
 
     #define CALL_GL_API(_api, ...)                                       \
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index cdc8a9f..4cae692 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -79,8 +79,6 @@
       mDisplay(EGL_NO_DISPLAY),
       mSurface(EGL_NO_SURFACE),
       mContext(EGL_NO_CONTEXT),
-      mDpiX(), mDpiY(),
-      mDensity(),
       mDisplayWidth(), mDisplayHeight(), mFormat(),
       mFlags(),
       mPageFlipCount(),
@@ -103,18 +101,6 @@
     return mFlinger != NULL;
 }
 
-float DisplayDevice::getDpiX() const {
-    return mDpiX;
-}
-
-float DisplayDevice::getDpiY() const {
-    return mDpiY;
-}
-
-float DisplayDevice::getDensity() const {
-    return mDensity;
-}
-
 int DisplayDevice::getWidth() const {
     return mDisplayWidth;
 }
@@ -137,38 +123,6 @@
 
     int format;
     window->query(window, NATIVE_WINDOW_FORMAT, &format);
-    mDpiX = window->xdpi;
-    mDpiY = window->ydpi;
-
-    // TODO: Not sure if display density should handled by SF any longer
-    class Density {
-        static int getDensityFromProperty(char const* propName) {
-            char property[PROPERTY_VALUE_MAX];
-            int density = 0;
-            if (property_get(propName, property, NULL) > 0) {
-                density = atoi(property);
-            }
-            return density;
-        }
-    public:
-        static int getEmuDensity() {
-            return getDensityFromProperty("qemu.sf.lcd_density"); }
-        static int getBuildDensity()  {
-            return getDensityFromProperty("ro.sf.lcd_density"); }
-    };
-    // The density of the device is provided by a build property
-    mDensity = Density::getBuildDensity() / 160.0f;
-    if (mDensity == 0) {
-        // the build doesn't provide a density -- this is wrong!
-        // use xdpi instead
-        ALOGE("ro.sf.lcd_density must be defined as a build property");
-        mDensity = mDpiX / 160.0f;
-    }
-    if (Density::getEmuDensity()) {
-        // if "qemu.sf.lcd_density" is specified, it overrides everything
-        mDpiX = mDpiY = mDensity = Density::getEmuDensity();
-        mDensity /= 160.0f;
-    }
 
     /*
      * Create our display's surface
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 0229dad..e9ba5ff 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -77,9 +77,6 @@
     // be instantaneous, might involve copying the frame buffer around.
     void flip(const Region& dirty) const;
 
-    float       getDpiX() const;
-    float       getDpiY() const;
-    float       getDensity() const;
     int         getWidth() const;
     int         getHeight() const;
     PixelFormat getFormat() const;
@@ -144,9 +141,6 @@
     EGLDisplay      mDisplay;
     EGLSurface      mSurface;
     EGLContext      mContext;
-    float           mDpiX;
-    float           mDpiY;
-    float           mDensity;
     int             mDisplayWidth;
     int             mDisplayHeight;
     PixelFormat     mFormat;
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index f329136..6d33592 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -175,19 +175,6 @@
     }
 }
 
-float FramebufferSurface::getRefreshRate() const {
-    /* FIXME: REFRESH_RATE is a temporary HACK until we are able to report the
-     * refresh rate properly from the HAL. The WindowManagerService now relies
-     * on this value.
-     */
-#ifndef REFRESH_RATE
-    return fbDev->fps;
-#else
-    return REFRESH_RATE;
-#warning "refresh rate set via makefile to REFRESH_RATE"
-#endif
-}
-
 status_t FramebufferSurface::setUpdateRectangle(const Rect& r)
 {
     return INVALID_OPERATION;
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index 95feaa0..bfa500b 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -38,9 +38,6 @@
 
     static sp<FramebufferSurface> create();
 
-    // TODO: this should be coming from HWC
-    float getRefreshRate() const;
-
     bool isUpdateOnDemand() const { return false; }
     status_t setUpdateRectangle(const Rect& updateRect);
     status_t compositionComplete();
@@ -52,6 +49,13 @@
     // BufferQueue.  The new buffer is returned in the 'buffer' argument.
     status_t nextBuffer(sp<GraphicBuffer>* buffer);
 
+    // FIXME: currently there are information we can only get from the
+    // FB HAL, and FB HAL can only be instantiated once on some devices.
+    // Eventually this functionality will have to move in HWC or somewhere else.
+    const framebuffer_device_t* getFbHal() const {
+        return fbDev;
+    }
+
 private:
     FramebufferSurface();
     virtual ~FramebufferSurface(); // this class cannot be overloaded
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 49aba52..c9df7a4 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -179,7 +179,8 @@
 
 HWComposer::HWComposer(
         const sp<SurfaceFlinger>& flinger,
-        EventHandler& handler)
+        EventHandler& handler,
+        framebuffer_device_t const* fbDev)
     : mFlinger(flinger),
       mModule(0), mHwc(0), mCapacity(0),
       mNumOVLayers(0), mNumFBLayers(0),
@@ -238,19 +239,14 @@
         }
     }
 
-    if (mRefreshPeriod == 0) {
-        // for compatibility, we attempt to get the refresh rate from
-        // the FB HAL if we couldn't get it from the HWC HAL.
-        hw_module_t const* module;
-        if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
-            framebuffer_device_t* fbDev;
-            int err = framebuffer_open(module, &fbDev);
-            if (!err && fbDev) {
-                mRefreshPeriod = nsecs_t(1e9 / fbDev->fps);
-                framebuffer_close(fbDev);
-            }
+
+    if (fbDev) {
+        if (mRefreshPeriod == 0) {
+            mRefreshPeriod = nsecs_t(1e9 / fbDev->fps);
+            ALOGW("getting VSYNC period from fb HAL: %lld", mRefreshPeriod);
         }
-        ALOGW("getting VSYNC period from fb HAL: %lld", mRefreshPeriod);
+        mDpiX = fbDev->xdpi;
+        mDpiY = fbDev->ydpi;
     }
 
     if (mRefreshPeriod == 0) {
@@ -313,6 +309,14 @@
     return now - ((now - mLastHwVSync) %  mRefreshPeriod);
 }
 
+float HWComposer::getDpiX() const {
+    return mDpiX;
+}
+
+float HWComposer::getDpiY() const {
+    return mDpiY;
+}
+
 void HWComposer::eventControl(int event, int enabled) {
     status_t err = NO_ERROR;
     if (mHwc && mHwc->common.version >= HWC_DEVICE_API_VERSION_0_3) {
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 52171f3..ac2257e 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -36,6 +36,7 @@
 struct hwc_composer_device_1;
 struct hwc_display_contents_1;
 struct hwc_procs;
+struct framebuffer_device_t;
 
 namespace android {
 // ---------------------------------------------------------------------------
@@ -62,7 +63,11 @@
         MAX_DISPLAYS
     };
 
-    HWComposer(const sp<SurfaceFlinger>& flinger, EventHandler& handler);
+    HWComposer(
+            const sp<SurfaceFlinger>& flinger,
+            EventHandler& handler,
+            framebuffer_device_t const* fbDev);
+
     ~HWComposer();
 
     status_t initCheck() const;
@@ -194,6 +199,8 @@
 
     nsecs_t getRefreshPeriod() const;
     nsecs_t getRefreshTimestamp() const;
+    float getDpiX() const;
+    float getDpiY() const;
 
     // this class is only used to fake the VSync event on systems that don't
     // have it.
@@ -245,6 +252,8 @@
     cb_context*                     mCBContext;
     EventHandler&                   mEventHandler;
     nsecs_t                         mRefreshPeriod;
+    float                           mDpiX;
+    float                           mDpiY;
     size_t                          mVSyncCount;
     sp<VSyncThread>                 mVSyncThread;
     bool                            mDebugForceFakeVSync;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index f2b49e8..fbf2873 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -420,7 +420,9 @@
     mEventQueue.setEventThread(mEventThread);
 
     // initialize the H/W composer
-    mHwc = new HWComposer(this, *static_cast<HWComposer::EventHandler *>(this));
+    mHwc = new HWComposer(this,
+            *static_cast<HWComposer::EventHandler *>(this),
+            fbs->getFbHal());
 
     // initialize our drawing state
     mDrawingState = mCurrentState;
@@ -497,13 +499,48 @@
     if (uint32_t(dpy) >= 1) {
         return BAD_INDEX;
     }
+
+    const HWComposer& hwc(getHwComposer());
+    float xdpi = hwc.getDpiX();
+    float ydpi = hwc.getDpiY();
+
+    // TODO: Not sure if display density should handled by SF any longer
+    class Density {
+        static int getDensityFromProperty(char const* propName) {
+            char property[PROPERTY_VALUE_MAX];
+            int density = 0;
+            if (property_get(propName, property, NULL) > 0) {
+                density = atoi(property);
+            }
+            return density;
+        }
+    public:
+        static int getEmuDensity() {
+            return getDensityFromProperty("qemu.sf.lcd_density"); }
+        static int getBuildDensity()  {
+            return getDensityFromProperty("ro.sf.lcd_density"); }
+    };
+    // The density of the device is provided by a build property
+    float density = Density::getBuildDensity() / 160.0f;
+    if (density == 0) {
+        // the build doesn't provide a density -- this is wrong!
+        // use xdpi instead
+        ALOGE("ro.sf.lcd_density must be defined as a build property");
+        density = xdpi / 160.0f;
+    }
+    if (Density::getEmuDensity()) {
+        // if "qemu.sf.lcd_density" is specified, it overrides everything
+        xdpi = ydpi = density = Density::getEmuDensity();
+        density /= 160.0f;
+    }
+
     sp<const DisplayDevice> hw(getDefaultDisplayDevice());
     info->w = hw->getWidth();
     info->h = hw->getHeight();
-    info->xdpi = hw->getDpiX();
-    info->ydpi = hw->getDpiY();
-    info->fps = float(1e9 / getHwComposer().getRefreshPeriod());
-    info->density = hw->getDensity();
+    info->xdpi = xdpi;
+    info->ydpi = ydpi;
+    info->fps = float(1e9 / hwc.getRefreshPeriod());
+    info->density = density;
     info->orientation = hw->getOrientation();
     // TODO: this needs to go away (currently needed only by webkit)
     getPixelFormatInfo(hw->getFormat(), &info->pixelFormatInfo);
@@ -1709,6 +1746,8 @@
     getHwComposer().acquire();
     hw->acquireScreen();
     mEventThread->onScreenAcquired();
+    mVisibleRegionsDirty = true;
+    repaintEverything();
 }
 
 void SurfaceFlinger::onScreenReleased() {
@@ -1940,15 +1979,13 @@
             "  transaction-flags         : %08x\n"
             "  refresh-rate              : %f fps\n"
             "  x-dpi                     : %f\n"
-            "  y-dpi                     : %f\n"
-            "  density                   : %f\n",
+            "  y-dpi                     : %f\n",
             mLastSwapBufferTime/1000.0,
             mLastTransactionTime/1000.0,
             mTransactionFlags,
             1e9 / hwc.getRefreshPeriod(),
-            hw->getDpiX(),
-            hw->getDpiY(),
-            hw->getDensity());
+            hwc.getDpiX(),
+            hwc.getDpiY());
     result.append(buffer);
 
     snprintf(buffer, SIZE, "  eglSwapBuffers time: %f us\n",