Merge "Fix race condition in fallback key processing."
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index ad96686..da12d46 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6421,6 +6421,12 @@
             mPrivateFlags &= ~DRAWING_CACHE_VALID;
             final ViewParent p = mParent;
             final AttachInfo ai = mAttachInfo;
+            if (p != null && ai != null && ai.mHardwareAccelerated) {
+                // fast-track for GL-enabled applications; just invalidate the whole hierarchy
+                // with a null dirty rect, which tells the ViewRoot to redraw everything
+                p.invalidateChild(this, null);
+                return;
+            }
             if (p != null && ai != null) {
                 final int scrollX = mScrollX;
                 final int scrollY = mScrollY;
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index e655192..af0e866 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -459,6 +459,16 @@
          device is data-only. -->
     <bool name="config_voice_capable">true</bool>
 
+    <!-- Flag indicating whether the current device allows sms service.
+         If true, this means that the device supports both sending and
+         receiving sms via the telephony network.
+         This can be overridden to false for "data only" devices
+         which can't send and receive sms message.
+
+         Note: Disable SMS also disable voicemail waiting sms,
+               cell broadcasting sms, and MMS. -->
+    <bool name="config_sms_capable">true</bool>
+
     <!-- IP address of the dns server to use if nobody else suggests one -->
     <string name="config_default_dns_server">8.8.8.8</string>
 
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index b357973..8bfc8d4 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -268,7 +268,7 @@
     const GLuint previousFbo = mSnapshot->fbo;
     const int count = saveSnapshot(flags);
 
-    if (!mSnapshot->invisible) {
+    if (!mSnapshot->isIgnored()) {
         int alpha = 255;
         SkXfermode::Mode mode;
 
@@ -385,13 +385,17 @@
 
     if (bounds.isEmpty() || bounds.getWidth() > mCaches.maxTextureSize ||
             bounds.getHeight() > mCaches.maxTextureSize) {
-        snapshot->invisible = true;
+        if (fboLayer) {
+            snapshot->invisible = true;
+        } else {
+            snapshot->empty = true;
+        }
     } else {
         snapshot->invisible = snapshot->invisible || (alpha <= ALPHA_THRESHOLD && fboLayer);
     }
 
     // Bail out if we won't draw in this snapshot
-    if (snapshot->invisible) {
+    if (snapshot->invisible || snapshot->empty) {
         return false;
     }
 
@@ -731,7 +735,7 @@
 }
 
 void OpenGLRenderer::clearLayerRegions() {
-    if (mLayers.size() == 0 || mSnapshot->invisible) return;
+    if (mLayers.size() == 0 || mSnapshot->isIgnored()) return;
 
     Rect clipRect(*mSnapshot->clipRect);
     clipRect.snapToPixelBoundaries();
@@ -809,7 +813,7 @@
 }
 
 bool OpenGLRenderer::quickReject(float left, float top, float right, float bottom) {
-    if (mSnapshot->invisible) {
+    if (mSnapshot->isIgnored()) {
         return true;
     }
 
@@ -988,7 +992,7 @@
 
 void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) {
     // TODO: Should do quickReject for each line
-    if (mSnapshot->invisible) return;
+    if (mSnapshot->isIgnored()) return;
 
     const bool isAA = paint->isAntiAlias();
     const float strokeWidth = paint->getStrokeWidth() * 0.5f;
@@ -1112,7 +1116,7 @@
 
 void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
     // No need to check against the clip, we fill the clip region
-    if (mSnapshot->invisible) return;
+    if (mSnapshot->isIgnored()) return;
 
     Rect& clip(*mSnapshot->clipRect);
     clip.snapToPixelBoundaries();
@@ -1150,7 +1154,7 @@
     if (text == NULL || count == 0 || (paint->getAlpha() == 0 && paint->getXfermode() == NULL)) {
         return;
     }
-    if (mSnapshot->invisible) return;
+    if (mSnapshot->isIgnored()) return;
 
     paint->setAntiAlias(true);
 
@@ -1253,7 +1257,7 @@
 }
 
 void OpenGLRenderer::drawPath(SkPath* path, SkPaint* paint) {
-    if (mSnapshot->invisible) return;
+    if (mSnapshot->isIgnored()) return;
 
     GLuint textureUnit = 0;
     glActiveTexture(gTextureUnits[textureUnit]);
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index 9f78063..9898df4 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -43,7 +43,7 @@
  */
 class Snapshot: public LightRefBase<Snapshot> {
 public:
-    Snapshot(): flags(0), previous(NULL), layer(NULL), fbo(0), invisible(false) {
+    Snapshot(): flags(0), previous(NULL), layer(NULL), fbo(0), invisible(false), empty(false) {
         transform = &mTransformRoot;
         clipRect = &mClipRectRoot;
         region = NULL;
@@ -55,7 +55,7 @@
      */
     Snapshot(const sp<Snapshot>& s, int saveFlags):
             flags(0), previous(s), layer(NULL), fbo(s->fbo),
-            invisible(s->invisible), viewport(s->viewport), height(s->height) {
+            invisible(s->invisible), empty(false), viewport(s->viewport), height(s->height) {
         if (saveFlags & SkCanvas::kMatrix_SaveFlag) {
             mTransformRoot.load(*s->transform);
             transform = &mTransformRoot;
@@ -203,6 +203,10 @@
         flags |= Snapshot::kFlagClipSet | Snapshot::kFlagDirtyLocalClip;
     }
 
+    bool isIgnored() const {
+        return invisible || empty;
+    }
+
     /**
      * Dirty flags.
      */
@@ -225,11 +229,18 @@
 
     /**
      * Indicates that this snapshot is invisible and nothing should be drawn
-     * inside it.
+     * inside it. This flag is set only when the layer clips drawing to its
+     * bounds and is passed to subsequent snapshots.
      */
     bool invisible;
 
     /**
+     * If set to true, the layer will not be composited. This is similar to
+     * invisible but this flag is not passed to subsequent snapshots.
+     */
+    bool empty;
+
+    /**
      * Current viewport.
      */
     Rect viewport;
diff --git a/media/mtp/MtpDevice.cpp b/media/mtp/MtpDevice.cpp
index 8ad39dc..e058a5a 100644
--- a/media/mtp/MtpDevice.cpp
+++ b/media/mtp/MtpDevice.cpp
@@ -49,7 +49,8 @@
         mDeviceInfo(NULL),
         mID(usb_device_get_unique_id(device)),
         mSessionID(0),
-        mTransactionID(0)
+        mTransactionID(0),
+        mReceivedResponse(false)
 {
 }
 
@@ -513,6 +514,7 @@
 
 bool MtpDevice::sendRequest(MtpOperationCode operation) {
     LOGV("sendRequest: %s\n", MtpDebug::getOperationCodeName(operation));
+    mReceivedResponse = false;
     mRequest.setOperationCode(operation);
     if (mTransactionID > 0)
         mRequest.setTransactionID(mTransactionID++);
@@ -535,6 +537,14 @@
     int ret = mData.read(mEndpointIn);
     LOGV("readData returned %d\n", ret);
     if (ret >= MTP_CONTAINER_HEADER_SIZE) {
+        if (mData.getContainerType() == MTP_CONTAINER_TYPE_RESPONSE) {
+            LOGD("got response packet instead of data packet");
+            // we got a response packet rather than data
+            // copy it to mResponse
+            mResponse.copyFrom(mData);
+            mReceivedResponse = true;
+            return false;
+        }
         mData.dump();
         return true;
     }
@@ -552,12 +562,15 @@
 
 MtpResponseCode MtpDevice::readResponse() {
     LOGV("readResponse\n");
+    if (mReceivedResponse) {
+        mReceivedResponse = false;
+        return mResponse.getResponseCode();
+    }
     int ret = mResponse.read(mEndpointIn);
     if (ret >= MTP_CONTAINER_HEADER_SIZE) {
         mResponse.dump();
         return mResponse.getResponseCode();
-    }
-    else {
+    } else {
         LOGD("readResponse failed\n");
         return -1;
     }
diff --git a/media/mtp/MtpDevice.h b/media/mtp/MtpDevice.h
index 6ffbd24..67bb85f 100644
--- a/media/mtp/MtpDevice.h
+++ b/media/mtp/MtpDevice.h
@@ -53,6 +53,8 @@
     MtpRequestPacket        mRequest;
     MtpDataPacket           mData;
     MtpResponsePacket       mResponse;
+    // set to true if we received a response packet instead of a data packet
+    bool                    mReceivedResponse;
 
     // to ensure only one MTP transaction at a time
     Mutex                   mMutex;
diff --git a/media/mtp/MtpPacket.cpp b/media/mtp/MtpPacket.cpp
index bd6196f..a885249 100644
--- a/media/mtp/MtpPacket.cpp
+++ b/media/mtp/MtpPacket.cpp
@@ -84,6 +84,13 @@
     LOGV("\n");
 }
 
+void MtpPacket::copyFrom(const MtpPacket& src) {
+    int length = src.mPacketSize;
+    allocate(length);
+    mPacketSize = length;
+    memcpy(mBuffer, src.mBuffer, length);
+}
+
 uint16_t MtpPacket::getUInt16(int offset) const {
     return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset];
 }
@@ -113,6 +120,10 @@
     putUInt16(MTP_CONTAINER_CODE_OFFSET, code);
 }
 
+uint16_t MtpPacket::getContainerType() const {
+    return getUInt16(MTP_CONTAINER_TYPE_OFFSET);
+}
+
 MtpTransactionID MtpPacket::getTransactionID() const {
     return getUInt32(MTP_CONTAINER_TRANSACTION_ID_OFFSET);
 }
diff --git a/media/mtp/MtpPacket.h b/media/mtp/MtpPacket.h
index 9c8d6da..73963a3 100644
--- a/media/mtp/MtpPacket.h
+++ b/media/mtp/MtpPacket.h
@@ -43,10 +43,13 @@
 
     void                allocate(int length);
     void                dump();
+    void                copyFrom(const MtpPacket& src);
 
     uint16_t            getContainerCode() const;
     void                setContainerCode(uint16_t code);
 
+    uint16_t            getContainerType() const;
+
     MtpTransactionID    getTransactionID() const;
     void                setTransactionID(MtpTransactionID id);