merge in jb-release history after reset to jb-dev
diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h
index f3c0ecb..7320e4d 100644
--- a/include/gui/ISurfaceComposer.h
+++ b/include/gui/ISurfaceComposer.h
@@ -67,6 +67,7 @@
         eTransparentRegionChanged   = 0x00000020,
         eVisibilityChanged          = 0x00000040,
         eFreezeTintChanged          = 0x00000080,
+        eCropChanged                = 0x00000100,
     };
 
     enum {
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index 1f90c59..50bdf71 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -72,6 +72,7 @@
     status_t    setAlpha(float alpha=1.0f);
     status_t    setMatrix(float dsdx, float dtdx, float dsdy, float dtdy);
     status_t    setFreezeTint(uint32_t tint);
+    status_t    setCrop(const Rect& crop);
 
     static status_t writeSurfaceToParcel(
             const sp<SurfaceControl>& control, Parcel* parcel);
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h
index d971031..3bd10de 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/include/gui/SurfaceComposerClient.h
@@ -127,6 +127,7 @@
     status_t    setMatrix(SurfaceID id, float dsdx, float dtdx, float dsdy, float dtdy);
     status_t    setPosition(SurfaceID id, float x, float y);
     status_t    setSize(SurfaceID id, uint32_t w, uint32_t h);
+    status_t    setCrop(SurfaceID id, const Rect& crop);
     status_t    destroySurface(SurfaceID sid);
 
 private:
diff --git a/include/media/openmax/OMX_Audio.h b/include/media/openmax/OMX_Audio.h
index a15e702..89ce0fc 100644
--- a/include/media/openmax/OMX_Audio.h
+++ b/include/media/openmax/OMX_Audio.h
@@ -106,6 +106,7 @@
     OMX_AUDIO_CodingWMA,         /**< Any variant of WMA encoded data */
     OMX_AUDIO_CodingRA,          /**< Any variant of RA encoded data */
     OMX_AUDIO_CodingMIDI,        /**< Any variant of MIDI encoded data */
+    OMX_AUDIO_CodingFLAC,        /**< Any variant of FLAC encoded data */
     OMX_AUDIO_CodingKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
     OMX_AUDIO_CodingVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_AUDIO_CodingMax = 0x7FFFFFFF
@@ -340,6 +341,19 @@
 } OMX_AUDIO_PARAM_VORBISTYPE;
 
 
+/** FLAC params */
+typedef struct OMX_AUDIO_PARAM_FLACTYPE {
+    OMX_U32 nSize;            /**< size of the structure in bytes */
+    OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+    OMX_U32 nPortIndex;       /**< port that this structure applies to */
+    OMX_U32 nChannels;        /**< Number of channels */
+    OMX_U32 nSampleRate;      /**< Sampling rate of the source data.  Use 0 for
+                                   unknown sampling rate. */
+    OMX_U32 nCompressionLevel;/**< FLAC compression level, from 0 (fastest compression)
+                                   to 8 (highest compression */
+} OMX_AUDIO_PARAM_FLACTYPE;
+
+
 /** WMA Version */
 typedef enum OMX_AUDIO_WMAFORMATTYPE {
   OMX_AUDIO_WMAFormatUnused = 0, /**< format unused or unknown */
diff --git a/include/media/openmax/OMX_Index.h b/include/media/openmax/OMX_Index.h
index c0b8d92..be9a1a6 100644
--- a/include/media/openmax/OMX_Index.h
+++ b/include/media/openmax/OMX_Index.h
@@ -135,6 +135,7 @@
     OMX_IndexParamAudioEvrc,                /**< reference: OMX_AUDIO_PARAM_EVRCTYPE */
     OMX_IndexParamAudioSmv,                 /**< reference: OMX_AUDIO_PARAM_SMVTYPE */
     OMX_IndexParamAudioVorbis,              /**< reference: OMX_AUDIO_PARAM_VORBISTYPE */
+    OMX_IndexParamAudioFlac,                /**< reference: OMX_AUDIO_PARAM_FLACTYPE */
 
     OMX_IndexConfigAudioMidiImmediateEvent, /**< reference: OMX_AUDIO_CONFIG_MIDIIMMEDIATEEVENTTYPE */
     OMX_IndexConfigAudioMidiControl,        /**< reference: OMX_AUDIO_CONFIG_MIDICONTROLTYPE */
diff --git a/include/private/gui/LayerState.h b/include/private/gui/LayerState.h
index ca277e0..9151c11 100644
--- a/include/private/gui/LayerState.h
+++ b/include/private/gui/LayerState.h
@@ -23,6 +23,7 @@
 #include <utils/Errors.h>
 
 #include <ui/Region.h>
+#include <ui/Rect.h>
 #include <gui/ISurface.h>
 
 namespace android {
@@ -40,6 +41,7 @@
     {
         matrix.dsdx = matrix.dtdy = 1.0f;
         matrix.dsdy = matrix.dtdx = 0.0f;
+        crop.makeInvalid();
     }
 
     status_t    write(Parcel& output) const;
@@ -64,6 +66,7 @@
             uint8_t         mask;
             uint8_t         reserved;
             matrix22_t      matrix;
+            Rect            crop;
             // non POD must be last. see write/read
             Region          transparentRegion;
 };
diff --git a/include/ui/Rect.h b/include/ui/Rect.h
index bd82061..308da7b 100644
--- a/include/ui/Rect.h
+++ b/include/ui/Rect.h
@@ -147,7 +147,7 @@
     // a ROT90 then the output rectangle is defined in a space extending to
     // (height, width).  Otherwise the output rectangle is in the same space as
     // the input.
-    Rect transform(uint32_t xform, int32_t width, int32_t height);
+    Rect transform(uint32_t xform, int32_t width, int32_t height) const;
 };
 
 ANDROID_BASIC_TYPES_TRAITS(Rect)
diff --git a/include/utils/Trace.h b/include/utils/Trace.h
index 984cd46..4219206 100644
--- a/include/utils/Trace.h
+++ b/include/utils/Trace.h
@@ -50,7 +50,8 @@
 #define ATRACE_TAG_ACTIVITY_MANAGER (1<<6)
 #define ATRACE_TAG_SYNC_MANAGER     (1<<7)
 #define ATRACE_TAG_AUDIO            (1<<8)
-#define ATRACE_TAG_LAST             ATRACE_TAG_AUDIO
+#define ATRACE_TAG_VIDEO            (1<<9)
+#define ATRACE_TAG_LAST             ATRACE_TAG_VIDEO
 
 #define ATRACE_TAG_VALID_MASK ((ATRACE_TAG_LAST - 1) | ATRACE_TAG_LAST)
 
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 059f313..d7590f0 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -164,6 +164,12 @@
     const sp<SurfaceComposerClient>& client(mClient);
     return client->setFreezeTint(mToken, tint);
 }
+status_t SurfaceControl::setCrop(const Rect& crop) {
+    status_t err = validate();
+    if (err < 0) return err;
+    const sp<SurfaceComposerClient>& client(mClient);
+    return client->setCrop(mToken, crop);
+}
 
 status_t SurfaceControl::validate() const
 {
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index ceb1ba6..8fa2167 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -125,6 +125,8 @@
             const sp<SurfaceComposerClient>& client, SurfaceID id,
             uint32_t tint);
     status_t setOrientation(int orientation);
+    status_t setCrop(const sp<SurfaceComposerClient>& client, SurfaceID id,
+            const Rect& crop);
 
     static void closeGlobalTransaction(bool synchronous) {
         Composer::getInstance().closeGlobalTransactionImpl(synchronous);
@@ -290,6 +292,17 @@
     return NO_ERROR;
 }
 
+status_t Composer::setCrop(const sp<SurfaceComposerClient>& client,
+        SurfaceID id, const Rect& crop) {
+    Mutex::Autolock _l(mLock);
+    layer_state_t* s = getLayerStateLocked(client, id);
+    if (!s)
+        return BAD_INDEX;
+    s->what |= ISurfaceComposer::eCropChanged;
+    s->crop = crop;
+    return NO_ERROR;
+}
+
 // ---------------------------------------------------------------------------
 
 SurfaceComposerClient::SurfaceComposerClient()
@@ -398,6 +411,10 @@
 
 // ----------------------------------------------------------------------------
 
+status_t SurfaceComposerClient::setCrop(SurfaceID id, const Rect& crop) {
+    return getComposer().setCrop(this, id, crop);
+}
+
 status_t SurfaceComposerClient::setFreezeTint(SurfaceID id, uint32_t tint) {
     return getComposer().setFreezeTint(this, id, tint);
 }
diff --git a/libs/ui/Rect.cpp b/libs/ui/Rect.cpp
index 65fe5f9..c4dd55b 100644
--- a/libs/ui/Rect.cpp
+++ b/libs/ui/Rect.cpp
@@ -93,7 +93,7 @@
     return !(result->isEmpty());
 }
 
-Rect Rect::transform(uint32_t xform, int32_t width, int32_t height) {
+Rect Rect::transform(uint32_t xform, int32_t width, int32_t height) const {
     Rect result(*this);
     if (xform & HAL_TRANSFORM_FLIP_H) {
         result = Rect(width - result.right, result.top,
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index e936188..2899db7 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -141,47 +141,6 @@
 void Layer::validateVisibility(const Transform& globalTransform) {
     LayerBase::validateVisibility(globalTransform);
 
-    if (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_FREEZE &&
-            !mCurrentCrop.isEmpty()) {
-        // We need to shrink the window size to match the buffer crop
-        // rectangle.
-        const Layer::State& s(drawingState());
-        const Transform tr(globalTransform * s.transform);
-        float windowWidth = s.w;
-        float windowHeight = s.h;
-        float bufferWidth = mActiveBuffer->getWidth();
-        float bufferHeight = mActiveBuffer->getHeight();
-        if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
-            float tmp = bufferWidth;
-            bufferWidth = bufferHeight;
-            bufferHeight = tmp;
-        }
-        float xScale = float(windowWidth) / float(bufferWidth);
-        float yScale = float(windowHeight) / float(bufferHeight);
-
-        // Compute the crop in post-transform coordinates.
-        Rect crop(mCurrentCrop.transform(mCurrentTransform,
-                    mActiveBuffer->getWidth(), mActiveBuffer->getHeight()));
-
-        float left = ceil(xScale * float(crop.left));
-        float right = floor(xScale * float(crop.right));
-        float top = ceil(yScale * float(crop.top));
-        float bottom = floor(yScale * float(crop.bottom));
-
-        tr.transform(mVertices[0], left, top);
-        tr.transform(mVertices[1], left, bottom);
-        tr.transform(mVertices[2], right, bottom);
-        tr.transform(mVertices[3], right, top);
-
-        const DisplayHardware& hw(graphicPlane(0).displayHardware());
-        const uint32_t hw_h = hw.getHeight();
-        for (size_t i=0 ; i<4 ; i++)
-            mVertices[i][1] = hw_h - mVertices[i][1];
-
-        mTransformedBounds = tr.transform(
-                Rect(int(left), int(top), int(right), int(bottom)));
-    }
-
     // This optimization allows the SurfaceTexture to bake in
     // the rotation so hardware overlays can be used
     mSurfaceTexture->setTransformHint(getTransformHint());
@@ -259,6 +218,46 @@
     return NO_ERROR;
 }
 
+Rect Layer::computeBufferCrop() const {
+    // Start with the SurfaceTexture's buffer crop...
+    Rect crop;
+    if (!mCurrentCrop.isEmpty()) {
+        crop = mCurrentCrop;
+    } else  if (mActiveBuffer != NULL){
+        crop = Rect(mActiveBuffer->getWidth(), mActiveBuffer->getHeight());
+    } else {
+        crop = Rect(mTransformedBounds.width(), mTransformedBounds.height());
+    }
+
+    // ... then reduce that in the same proportions as the window crop reduces
+    // the window size.
+    const State& s(drawingState());
+    if (!s.crop.isEmpty()) {
+        // Transform the window crop to match the buffer coordinate system,
+        // which means using the inverse of the current transform set on the
+        // SurfaceTexture.
+        uint32_t invTransform = mCurrentTransform;
+        int winWidth = s.w;
+        int winHeight = s.h;
+        if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+            invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
+                    NATIVE_WINDOW_TRANSFORM_FLIP_H;
+            winWidth = s.h;
+            winHeight = s.w;
+        }
+        Rect winCrop = s.crop.transform(invTransform, s.w, s.h);
+
+        float xScale = float(crop.width()) / float(winWidth);
+        float yScale = float(crop.height()) / float(winHeight);
+        crop.left += int(ceil(float(winCrop.left) * xScale));
+        crop.top += int(ceil(float(winCrop.top) * yScale));
+        crop.right -= int(ceil(float(winWidth - winCrop.right) * xScale));
+        crop.bottom -= int(ceil(float(winHeight - winCrop.bottom) * yScale));
+    }
+
+    return crop;
+}
+
 void Layer::setGeometry(hwc_layer_t* hwcl)
 {
     LayerBaseClient::setGeometry(hwcl);
@@ -293,23 +292,11 @@
         hwcl->transform = finalTransform;
     }
 
-    if (isCropped()) {
-        hwcl->sourceCrop.left   = mCurrentCrop.left;
-        hwcl->sourceCrop.top    = mCurrentCrop.top;
-        hwcl->sourceCrop.right  = mCurrentCrop.right;
-        hwcl->sourceCrop.bottom = mCurrentCrop.bottom;
-    } else {
-        const sp<GraphicBuffer>& buffer(mActiveBuffer);
-        hwcl->sourceCrop.left   = 0;
-        hwcl->sourceCrop.top    = 0;
-        if (buffer != NULL) {
-            hwcl->sourceCrop.right  = buffer->width;
-            hwcl->sourceCrop.bottom = buffer->height;
-        } else {
-            hwcl->sourceCrop.right  = mTransformedBounds.width();
-            hwcl->sourceCrop.bottom = mTransformedBounds.height();
-        }
-    }
+    Rect crop = computeBufferCrop();
+    hwcl->sourceCrop.left   = crop.left;
+    hwcl->sourceCrop.top    = crop.top;
+    hwcl->sourceCrop.right  = crop.right;
+    hwcl->sourceCrop.bottom = crop.bottom;
 }
 
 void Layer::setPerFrameData(hwc_layer_t* hwcl) {
@@ -541,6 +528,7 @@
             mCurrentTransform = transform;
             mCurrentScalingMode = scalingMode;
             mFlinger->invalidateHwcGeometry();
+            recomputeVisibleRegions = true;
         }
 
         uint32_t bufWidth  = mActiveBuffer->getWidth();
@@ -549,6 +537,7 @@
             if (bufWidth != uint32_t(oldActiveBuffer->width) ||
                 bufHeight != uint32_t(oldActiveBuffer->height)) {
                 mFlinger->invalidateHwcGeometry();
+                recomputeVisibleRegions = true;
             }
         }
 
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 1188621..393599f 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -101,6 +101,7 @@
     uint32_t getEffectiveUsage(uint32_t usage) const;
     uint32_t getTransformHint() const;
     bool isCropped() const;
+    Rect computeBufferCrop() const;
     static bool getOpacityForFormat(uint32_t format);
 
     // -----------------------------------------------------------------------
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index 694ecde..81031b1 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -93,6 +93,7 @@
     mCurrentState.flags         = layerFlags;
     mCurrentState.sequence      = 0;
     mCurrentState.transform.set(0, 0);
+    mCurrentState.crop.makeInvalid();
 
     // drawing state & current state are identical
     mDrawingState = mCurrentState;
@@ -172,6 +173,14 @@
     requestTransaction();
     return true;
 }
+bool LayerBase::setCrop(const Rect& crop) {
+    if (mCurrentState.crop == crop)
+        return false;
+    mCurrentState.sequence++;
+    mCurrentState.crop = crop;
+    requestTransaction();
+    return true;
+}
 
 Rect LayerBase::visibleBounds() const
 {
@@ -229,15 +238,18 @@
     const bool transformed = tr.transformed();
     const DisplayHardware& hw(graphicPlane(0).displayHardware());
     const uint32_t hw_h = hw.getHeight();
+    const Rect& crop(s.crop);
 
-    uint32_t w = s.w;
-    uint32_t h = s.h;
+    Rect win(s.w, s.h);
+    if (!crop.isEmpty()) {
+        win.intersect(crop, &win);
+    }
 
     mNumVertices = 4;
-    tr.transform(mVertices[0], 0, 0);
-    tr.transform(mVertices[1], 0, h);
-    tr.transform(mVertices[2], w, h);
-    tr.transform(mVertices[3], w, 0);
+    tr.transform(mVertices[0], win.left,  win.top);
+    tr.transform(mVertices[1], win.left,  win.bottom);
+    tr.transform(mVertices[2], win.right, win.bottom);
+    tr.transform(mVertices[3], win.right, win.top);
     for (size_t i=0 ; i<4 ; i++)
         mVertices[i][1] = hw_h - mVertices[i][1];
 
@@ -260,7 +272,7 @@
     mOrientation = tr.getOrientation();
     mPlaneOrientation = planeTransform.getOrientation();
     mTransform = tr;
-    mTransformedBounds = tr.makeBounds(w, h);
+    mTransformedBounds = tr.transform(win);
 }
 
 void LayerBase::lockPageFlip(bool& recomputeVisibleRegions) {
@@ -391,15 +403,27 @@
         GLfloat v;
     };
 
+    Rect crop(s.w, s.h);
+    if (!s.crop.isEmpty()) {
+        crop = s.crop;
+    }
+    GLfloat left = GLfloat(crop.left) / GLfloat(s.w);
+    GLfloat top = GLfloat(crop.top) / GLfloat(s.h);
+    GLfloat right = GLfloat(crop.right) / GLfloat(s.w);
+    GLfloat bottom = GLfloat(crop.bottom) / GLfloat(s.h);
+
     TexCoords texCoords[4];
-    texCoords[0].u = 0;
-    texCoords[0].v = 1;
-    texCoords[1].u = 0;
-    texCoords[1].v = 0;
-    texCoords[2].u = 1;
-    texCoords[2].v = 0;
-    texCoords[3].u = 1;
-    texCoords[3].v = 1;
+    texCoords[0].u = left;
+    texCoords[0].v = top;
+    texCoords[1].u = left;
+    texCoords[1].v = bottom;
+    texCoords[2].u = right;
+    texCoords[2].v = bottom;
+    texCoords[3].u = right;
+    texCoords[3].v = top;
+    for (int i = 0; i < 4; i++) {
+        texCoords[i].v = 1.0f - texCoords[i].v;
+    }
 
     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
     glVertexPointer(2, GL_FLOAT, 0, mVertices);
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index d123d9b..31f6dfd 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -78,6 +78,7 @@
                 uint32_t        tint;
                 Transform       transform;
                 Region          transparentRegion;
+                Rect            crop;
             };
 
     virtual void setName(const String8& name);
@@ -91,6 +92,7 @@
             bool setMatrix(const layer_state_t::matrix22_t& matrix);
             bool setTransparentRegionHint(const Region& opaque);
             bool setFlags(uint8_t flags, uint8_t mask);
+            bool setCrop(const Rect& crop);
             
             void commitTransaction();
             bool requestTransaction();
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 0d4d2b9..35a7fd5 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1352,6 +1352,10 @@
             if (layer->setFlags(s.flags, s.mask))
                 flags |= eTraversalNeeded;
         }
+        if (what & eCropChanged) {
+            if (layer->setCrop(s.crop))
+                flags |= eTraversalNeeded;
+        }
     }
     return flags;
 }