Merge "Fix issue #5063010: Loaders don't seem to be properly..."
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index 76534ef..e289fc1 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -20,6 +20,7 @@
 import java.net.Inet4Address;
 import java.net.Inet6Address;
 import java.net.UnknownHostException;
+import java.util.Collection;
 
 import android.util.Log;
 
@@ -235,4 +236,18 @@
             throw new IllegalArgumentException(e);
         }
     }
+
+    /**
+     * Create a string array of host addresses from a collection of InetAddresses
+     * @param addrs a Collection of InetAddresses
+     * @return an array of Strings containing their host addresses
+     */
+    public static String[] makeStrings(Collection<InetAddress> addrs) {
+        String[] result = new String[addrs.size()];
+        int i = 0;
+        for (InetAddress addr : addrs) {
+            result[i++] = addr.getHostAddress();
+        }
+        return result;
+    }
 }
diff --git a/drm/common/IDrmManagerService.cpp b/drm/common/IDrmManagerService.cpp
index 2d8e877..986f32c 100644
--- a/drm/common/IDrmManagerService.cpp
+++ b/drm/common/IDrmManagerService.cpp
@@ -110,11 +110,11 @@
     handle->extendedData.clear();
 }
 
-int BpDrmManagerService::addUniqueId(int uniqueId) {
+int BpDrmManagerService::addUniqueId(bool isNative) {
     LOGV("add uniqueid");
     Parcel data, reply;
     data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
-    data.writeInt32(uniqueId);
+    data.writeInt32(isNative);
     remote()->transact(ADD_UNIQUEID, data, &reply);
     return reply.readInt32();
 }
diff --git a/drm/drmserver/DrmManager.cpp b/drm/drmserver/DrmManager.cpp
index 1809619..3e4fe8c 100644
--- a/drm/drmserver/DrmManager.cpp
+++ b/drm/drmserver/DrmManager.cpp
@@ -49,32 +49,42 @@
 
 }
 
-int DrmManager::addUniqueId(int uniqueId) {
+int DrmManager::addUniqueId(bool isNative) {
     Mutex::Autolock _l(mLock);
-    if (0 == uniqueId) {
-        int temp = 0;
-        bool foundUniqueId = false;
-        srand(time(NULL));
 
-        while (!foundUniqueId) {
-            const int size = mUniqueIdVector.size();
-            temp = rand() % 100;
+    int temp = 0;
+    bool foundUniqueId = false;
+    const int size = mUniqueIdVector.size();
+    const int uniqueIdRange = 0xfff;
+    int maxLoopTimes = (uniqueIdRange - 1) / 2;
+    srand(time(NULL));
 
-            int index = 0;
-            for (; index < size; ++index) {
-                if (mUniqueIdVector.itemAt(index) == temp) {
-                    foundUniqueId = false;
-                    break;
-                }
-            }
-            if (index == size) {
-                foundUniqueId = true;
+    while (!foundUniqueId) {
+        temp = rand() & uniqueIdRange;
+
+        if (isNative) {
+            // set a flag to differentiate DrmManagerClient
+            // created from native side and java side
+            temp |= 0x1000;
+        }
+
+        int index = 0;
+        for (; index < size; ++index) {
+            if (mUniqueIdVector.itemAt(index) == temp) {
+                foundUniqueId = false;
+                break;
             }
         }
-        uniqueId = temp;
+        if (index == size) {
+            foundUniqueId = true;
+        }
+
+        maxLoopTimes --;
+        LOG_FATAL_IF(maxLoopTimes <= 0, "cannot find an unique ID for this session");
     }
-    mUniqueIdVector.push(uniqueId);
-    return uniqueId;
+
+    mUniqueIdVector.push(temp);
+    return temp;
 }
 
 void DrmManager::removeUniqueId(int uniqueId) {
diff --git a/drm/drmserver/DrmManagerService.cpp b/drm/drmserver/DrmManagerService.cpp
index 583669e..7ebcac3 100644
--- a/drm/drmserver/DrmManagerService.cpp
+++ b/drm/drmserver/DrmManagerService.cpp
@@ -78,8 +78,8 @@
     delete mDrmManager; mDrmManager = NULL;
 }
 
-int DrmManagerService::addUniqueId(int uniqueId) {
-    return mDrmManager->addUniqueId(uniqueId);
+int DrmManagerService::addUniqueId(bool isNative) {
+    return mDrmManager->addUniqueId(isNative);
 }
 
 void DrmManagerService::removeUniqueId(int uniqueId) {
diff --git a/drm/java/android/drm/DrmManagerClient.java b/drm/java/android/drm/DrmManagerClient.java
index f3a0343..9a7194c 100755
--- a/drm/java/android/drm/DrmManagerClient.java
+++ b/drm/java/android/drm/DrmManagerClient.java
@@ -248,9 +248,7 @@
         mEventHandler = new EventHandler(eventThread.getLooper());
 
         // save the unique id
-        mUniqueId = hashCode();
-
-        _initialize(mUniqueId, new WeakReference<DrmManagerClient>(this));
+        mUniqueId = _initialize(new WeakReference<DrmManagerClient>(this));
     }
 
     protected void finalize() {
@@ -794,7 +792,7 @@
     }
 
     // private native interfaces
-    private native void _initialize(int uniqueId, Object weak_this);
+    private native int _initialize(Object weak_this);
 
     private native void _finalize(int uniqueId);
 
diff --git a/drm/jni/android_drm_DrmManagerClient.cpp b/drm/jni/android_drm_DrmManagerClient.cpp
index e131839..80a8447 100644
--- a/drm/jni/android_drm_DrmManagerClient.cpp
+++ b/drm/jni/android_drm_DrmManagerClient.cpp
@@ -224,11 +224,12 @@
     return sp<DrmManagerClientImpl>(client);
 }
 
-static void android_drm_DrmManagerClient_initialize(
-        JNIEnv* env, jobject thiz, jint uniqueId, jobject weak_thiz) {
+static jint android_drm_DrmManagerClient_initialize(
+        JNIEnv* env, jobject thiz, jobject weak_thiz) {
     LOGV("initialize - Enter");
 
-    sp<DrmManagerClientImpl> drmManager = DrmManagerClientImpl::create(&uniqueId);
+    int uniqueId = 0;
+    sp<DrmManagerClientImpl> drmManager = DrmManagerClientImpl::create(&uniqueId, false);
     drmManager->addClient(uniqueId);
 
     // Set the listener to DrmManager
@@ -237,6 +238,8 @@
 
     setDrmManagerClientImpl(env, thiz, drmManager);
     LOGV("initialize - Exit");
+
+    return uniqueId;
 }
 
 static void android_drm_DrmManagerClient_finalize(JNIEnv* env, jobject thiz, jint uniqueId) {
@@ -711,7 +714,7 @@
 
 static JNINativeMethod nativeMethods[] = {
 
-    {"_initialize", "(ILjava/lang/Object;)V",
+    {"_initialize", "(Ljava/lang/Object;)I",
                                     (void*)android_drm_DrmManagerClient_initialize},
 
     {"_finalize", "(I)V",
diff --git a/drm/libdrmframework/DrmManagerClient.cpp b/drm/libdrmframework/DrmManagerClient.cpp
index b50199f..c9c0d57 100644
--- a/drm/libdrmframework/DrmManagerClient.cpp
+++ b/drm/libdrmframework/DrmManagerClient.cpp
@@ -24,7 +24,7 @@
 
 DrmManagerClient::DrmManagerClient():
         mUniqueId(0), mDrmManagerClientImpl(NULL) {
-    mDrmManagerClientImpl = DrmManagerClientImpl::create(&mUniqueId);
+    mDrmManagerClientImpl = DrmManagerClientImpl::create(&mUniqueId, true);
     mDrmManagerClientImpl->addClient(mUniqueId);
 }
 
diff --git a/drm/libdrmframework/DrmManagerClientImpl.cpp b/drm/libdrmframework/DrmManagerClientImpl.cpp
index a36bd4a..67f58ca 100644
--- a/drm/libdrmframework/DrmManagerClientImpl.cpp
+++ b/drm/libdrmframework/DrmManagerClientImpl.cpp
@@ -33,13 +33,10 @@
 sp<DrmManagerClientImpl::DeathNotifier> DrmManagerClientImpl::sDeathNotifier;
 const String8 DrmManagerClientImpl::EMPTY_STRING("");
 
-DrmManagerClientImpl* DrmManagerClientImpl::create(int* pUniqueId) {
-    if (0 == *pUniqueId) {
-        int uniqueId = getDrmManagerService()->addUniqueId(*pUniqueId);
-        *pUniqueId = uniqueId;
-    } else {
-        getDrmManagerService()->addUniqueId(*pUniqueId);
-    }
+DrmManagerClientImpl* DrmManagerClientImpl::create(
+        int* pUniqueId, bool isNative) {
+    *pUniqueId = getDrmManagerService()->addUniqueId(isNative);
+
     return new DrmManagerClientImpl();
 }
 
diff --git a/drm/libdrmframework/include/DrmManager.h b/drm/libdrmframework/include/DrmManager.h
index af2c2a8..ac2b946 100644
--- a/drm/libdrmframework/include/DrmManager.h
+++ b/drm/libdrmframework/include/DrmManager.h
@@ -53,7 +53,7 @@
     virtual ~DrmManager();
 
 public:
-    int addUniqueId(int uniqueId);
+    int addUniqueId(bool isNative);
 
     void removeUniqueId(int uniqueId);
 
diff --git a/drm/libdrmframework/include/DrmManagerClientImpl.h b/drm/libdrmframework/include/DrmManagerClientImpl.h
index 564896b..e3338d9 100644
--- a/drm/libdrmframework/include/DrmManagerClientImpl.h
+++ b/drm/libdrmframework/include/DrmManagerClientImpl.h
@@ -38,7 +38,7 @@
     DrmManagerClientImpl() { }
 
 public:
-    static DrmManagerClientImpl* create(int* pUniqueId);
+    static DrmManagerClientImpl* create(int* pUniqueId, bool isNative);
 
     static void remove(int uniqueId);
 
diff --git a/drm/libdrmframework/include/DrmManagerService.h b/drm/libdrmframework/include/DrmManagerService.h
index 227496a..9cb5804 100644
--- a/drm/libdrmframework/include/DrmManagerService.h
+++ b/drm/libdrmframework/include/DrmManagerService.h
@@ -46,7 +46,7 @@
     virtual ~DrmManagerService();
 
 public:
-    int addUniqueId(int uniqueId);
+    int addUniqueId(bool isNative);
 
     void removeUniqueId(int uniqueId);
 
diff --git a/drm/libdrmframework/include/IDrmManagerService.h b/drm/libdrmframework/include/IDrmManagerService.h
index 7727e55..b9618bb 100644
--- a/drm/libdrmframework/include/IDrmManagerService.h
+++ b/drm/libdrmframework/include/IDrmManagerService.h
@@ -81,7 +81,7 @@
     DECLARE_META_INTERFACE(DrmManagerService);
 
 public:
-    virtual int addUniqueId(int uniqueId) = 0;
+    virtual int addUniqueId(bool isNative) = 0;
 
     virtual void removeUniqueId(int uniqueId) = 0;
 
@@ -167,7 +167,7 @@
     BpDrmManagerService(const sp<IBinder>& impl)
             : BpInterface<IDrmManagerService>(impl) {}
 
-    virtual int addUniqueId(int uniqueId);
+    virtual int addUniqueId(bool isNative);
 
     virtual void removeUniqueId(int uniqueId);
 
diff --git a/drm/libdrmframework/plugins/common/include/DrmEngineBase.h b/drm/libdrmframework/plugins/common/include/DrmEngineBase.h
index b61e3d3..4a5afcf 100644
--- a/drm/libdrmframework/plugins/common/include/DrmEngineBase.h
+++ b/drm/libdrmframework/plugins/common/include/DrmEngineBase.h
@@ -143,7 +143,13 @@
      * Register a callback to be invoked when the caller required to
      * receive necessary information
      *
-     * @param[in] uniqueId Unique identifier for a session
+     * @param[in] uniqueId Unique identifier for a session. uniqueId is a random
+     *                     number generated in the DRM service. If the DrmManagerClient
+     *                     is created in native code, uniqueId will be a number ranged
+     *                     from 0x1000 to 0x1fff. If it comes from Java code, the uniqueId
+     *                     will be a number ranged from 0x00 to 0xfff. So bit 0x1000 in
+     *                     uniqueId could be used in DRM plugins to differentiate native
+     *                     OnInfoListener and Java OnInfoListener.
      * @param[in] infoListener Listener
      * @return status_t
      *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp
index 4a40a63..996acd5 100644
--- a/libs/hwui/GradientCache.cpp
+++ b/libs/hwui/GradientCache.cpp
@@ -181,11 +181,8 @@
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap->rowBytesAsPixels(), texture->height, 0,
             GL_RGBA, GL_UNSIGNED_BYTE, bitmap->getPixels());
 
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    texture->setFilter(GL_LINEAR, GL_LINEAR);
+    texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
 }
 
 }; // namespace uirenderer
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 3c2d80d..0c536b0 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -51,8 +51,6 @@
         texture.width = layerWidth;
         texture.height = layerHeight;
         colorFilter = NULL;
-        firstFilter = true;
-        firstWrap = true;
     }
 
     ~Layer() {
@@ -150,27 +148,11 @@
     }
 
     void setWrap(GLenum wrapS, GLenum wrapT, bool bindTexture = false, bool force = false) {
-        if (firstWrap || force || wrapS != texture.wrapS || wrapT != texture.wrapT) {
-            firstWrap = true;
-            texture.setWrap(wrapS, wrapT);
-            if (bindTexture) {
-                glBindTexture(renderTarget, texture.id);
-            }
-            glTexParameteri(renderTarget, GL_TEXTURE_WRAP_S, wrapS);
-            glTexParameteri(renderTarget, GL_TEXTURE_WRAP_T, wrapT);
-        }
+        texture.setWrap(wrapS, wrapT, bindTexture, force, renderTarget);
     }
 
     void setFilter(GLenum min, GLenum mag, bool bindTexture = false, bool force = false) {
-        if (firstFilter || force || min != texture.minFilter || mag != texture.magFilter) {
-            firstFilter = false;
-            texture.setFilter(min, mag);
-            if (bindTexture) {
-                glBindTexture(renderTarget, texture.id);
-            }
-            glTexParameteri(renderTarget, GL_TEXTURE_MIN_FILTER, min);
-            glTexParameteri(renderTarget, GL_TEXTURE_MAG_FILTER, mag);
-        }
+        texture.setFilter(min, mag,bindTexture, force, renderTarget);
     }
 
     inline bool isCacheable() {
@@ -296,8 +278,6 @@
      */
     mat4 texTransform;
 
-    bool firstFilter;
-    bool firstWrap;
 }; // struct Layer
 
 }; // namespace uirenderer
diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp
index 1a15e87..36083af 100644
--- a/libs/hwui/LayerCache.cpp
+++ b/libs/hwui/LayerCache.cpp
@@ -107,7 +107,7 @@
         layer->generateTexture();
         layer->bindTexture();
         layer->setFilter(GL_NEAREST, GL_NEAREST);
-        layer->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
+        layer->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, false);
         glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
 
 #if DEBUG_LAYERS
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 85a9762..e67abbd 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1293,16 +1293,16 @@
     SkXfermode::Mode mode;
     getAlphaAndMode(paint, &alpha, &mode);
 
-    setTextureWrapModes(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
-
     float x = left;
     float y = top;
 
+    GLenum filter = GL_LINEAR;
     bool ignoreTransform = false;
     if (mSnapshot->transform->isPureTranslate()) {
         x = (int) floorf(left + mSnapshot->transform->getTranslateX() + 0.5f);
         y = (int) floorf(top + mSnapshot->transform->getTranslateY() + 0.5f);
         ignoreTransform = true;
+        filter = GL_NEAREST;
     }
 
     setupDraw();
@@ -1315,7 +1315,11 @@
     setupDrawBlending(true, mode);
     setupDrawProgram();
     setupDrawModelView(x, y, x + texture->width, y + texture->height, ignoreTransform);
+
     setupDrawTexture(texture->id);
+    texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
+    texture->setFilter(filter, filter);
+
     setupDrawPureColorUniforms();
     setupDrawColorFilterUniforms();
     setupDrawShaderUniforms();
@@ -1379,7 +1383,9 @@
     Texture* texture = mCaches.textureCache.get(bitmap);
     if (!texture) return;
     const AutoTexture autoCleanup(texture);
-    setTextureWrapModes(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
+
+    texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, true);
+    texture->setFilter(GL_LINEAR, GL_LINEAR, true);
 
     int alpha;
     SkXfermode::Mode mode;
@@ -1462,7 +1468,7 @@
     Texture* texture = mCaches.textureCache.get(bitmap);
     if (!texture) return;
     const AutoTexture autoCleanup(texture);
-    setTextureWrapModes(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
+    texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, true);
 
     const float width = texture->width;
     const float height = texture->height;
@@ -1483,11 +1489,13 @@
         const float x = (int) floorf(dstLeft + mSnapshot->transform->getTranslateX() + 0.5f);
         const float y = (int) floorf(dstTop + mSnapshot->transform->getTranslateY() + 0.5f);
 
+        texture->setFilter(GL_NEAREST, GL_NEAREST, true);
         drawTextureMesh(x, y, x + (dstRight - dstLeft), y + (dstBottom - dstTop),
                 texture->id, alpha / 255.0f, mode, texture->blend,
                 &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0],
                 GL_TRIANGLE_STRIP, gMeshCount, false, true);
     } else {
+        texture->setFilter(GL_LINEAR, GL_LINEAR, true);
         drawTextureMesh(dstLeft, dstTop, dstRight, dstBottom, texture->id, alpha / 255.0f,
                 mode, texture->blend, &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0],
                 GL_TRIANGLE_STRIP, gMeshCount);
@@ -1507,7 +1515,8 @@
     Texture* texture = mCaches.textureCache.get(bitmap);
     if (!texture) return;
     const AutoTexture autoCleanup(texture);
-    setTextureWrapModes(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
+    texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, true);
+    texture->setFilter(GL_LINEAR, GL_LINEAR, true);
 
     int alpha;
     SkXfermode::Mode mode;
@@ -2411,16 +2420,18 @@
     SkXfermode::Mode mode;
     getAlphaAndMode(paint, &alpha, &mode);
 
-    setTextureWrapModes(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
+    texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, true);
 
     if (mSnapshot->transform->isPureTranslate()) {
         const float x = (int) floorf(left + mSnapshot->transform->getTranslateX() + 0.5f);
         const float y = (int) floorf(top + mSnapshot->transform->getTranslateY() + 0.5f);
 
+        texture->setFilter(GL_NEAREST, GL_NEAREST, true);
         drawTextureMesh(x, y, x + texture->width, y + texture->height, texture->id,
                 alpha / 255.0f, mode, texture->blend, (GLvoid*) NULL,
                 (GLvoid*) gMeshTextureOffset, GL_TRIANGLE_STRIP, gMeshCount, false, true);
     } else {
+        texture->setFilter(GL_LINEAR, GL_LINEAR, true);
         drawTextureMesh(left, top, right, bottom, texture->id, alpha / 255.0f, mode,
                 texture->blend, (GLvoid*) NULL, (GLvoid*) gMeshTextureOffset,
                 GL_TRIANGLE_STRIP, gMeshCount);
@@ -2550,22 +2561,5 @@
     return resultMode;
 }
 
-void OpenGLRenderer::setTextureWrapModes(Texture* texture, GLenum wrapS, GLenum wrapT) {
-    bool bound = false;
-    if (wrapS != texture->wrapS) {
-        glBindTexture(GL_TEXTURE_2D, texture->id);
-        bound = true;
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS);
-        texture->wrapS = wrapS;
-    }
-    if (wrapT != texture->wrapT) {
-        if (!bound) {
-            glBindTexture(GL_TEXTURE_2D, texture->id);
-        }
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT);
-        texture->wrapT = wrapT;
-    }
-}
-
 }; // namespace uirenderer
 }; // namespace android
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 0a3d5090..fa893f0 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -464,12 +464,6 @@
     }
 
     /**
-     * Sets the wrap modes for the specified texture. The wrap modes are modified
-     * only when needed.
-     */
-    inline void setTextureWrapModes(Texture* texture, GLenum wrapS, GLenum wrapT);
-
-    /**
      * Enable or disable blending as necessary. This function sets the appropriate
      * blend function based on the specified xfermode.
      */
diff --git a/libs/hwui/ShapeCache.h b/libs/hwui/ShapeCache.h
index f4d9686..33953be 100644
--- a/libs/hwui/ShapeCache.h
+++ b/libs/hwui/ShapeCache.h
@@ -624,11 +624,8 @@
     glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, texture->width, texture->height, 0,
             GL_ALPHA, GL_UNSIGNED_BYTE, bitmap.getPixels());
 
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    texture->setFilter(GL_LINEAR, GL_LINEAR);
+    texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
 }
 
 }; // namespace uirenderer
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 8878c70..1a60dca 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -77,14 +77,7 @@
 
 void SkiaShader::bindTexture(Texture* texture, GLenum wrapS, GLenum wrapT) {
     glBindTexture(GL_TEXTURE_2D, texture->id);
-    if (wrapS != texture->wrapS) {
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS);
-        texture->wrapS = wrapS;
-    }
-    if (wrapT != texture->wrapT) {
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT);
-        texture->wrapT = wrapT;
-    }
+    texture->setWrap(wrapS, wrapT);
 }
 
 void SkiaShader::computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView) {
@@ -151,6 +144,9 @@
 
     // Uniforms
     bindTexture(texture, mWrapS, mWrapT);
+    GLenum filter = textureTransform.isPureTranslate() ? GL_NEAREST : GL_LINEAR;
+    texture->setFilter(filter, filter);
+
     glUniform1i(program->getUniform("bitmapSampler"), textureSlot);
     glUniformMatrix4fv(program->getUniform("textureTransform"), 1,
             GL_FALSE, &textureTransform.data[0]);
diff --git a/libs/hwui/TextDropShadowCache.cpp b/libs/hwui/TextDropShadowCache.cpp
index 8f6f860..a3ee63b 100644
--- a/libs/hwui/TextDropShadowCache.cpp
+++ b/libs/hwui/TextDropShadowCache.cpp
@@ -137,11 +137,8 @@
         glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, texture->width, texture->height, 0,
                 GL_ALPHA, GL_UNSIGNED_BYTE, shadow.image);
 
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+        texture->setFilter(GL_LINEAR, GL_LINEAR);
+        texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
 
         if (size < mMaxSize) {
             if (mDebugEnabled) {
diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h
index c6ae326..48229b6 100644
--- a/libs/hwui/Texture.h
+++ b/libs/hwui/Texture.h
@@ -35,16 +35,45 @@
 
         minFilter = GL_NEAREST;
         magFilter = GL_NEAREST;
+
+        firstFilter = true;
+        firstWrap = true;
     }
 
-    void setWrap(GLenum wrapS, GLenum wrapT) {
-        this->wrapS = wrapS;
-        this->wrapT = wrapT;
+    void setWrap(GLenum wrapS, GLenum wrapT, bool bindTexture = false, bool force = false,
+            GLenum renderTarget = GL_TEXTURE_2D) {
+
+        if (firstWrap || force || wrapS != this->wrapS || wrapT != this->wrapT) {
+            firstWrap = true;
+
+            this->wrapS = wrapS;
+            this->wrapT = wrapT;
+
+            if (bindTexture) {
+                glBindTexture(renderTarget, id);
+            }
+
+            glTexParameteri(renderTarget, GL_TEXTURE_WRAP_S, wrapS);
+            glTexParameteri(renderTarget, GL_TEXTURE_WRAP_T, wrapT);
+        }
     }
 
-    void setFilter(GLenum min, GLenum mag) {
-        minFilter = min;
-        magFilter = mag;
+    void setFilter(GLenum min, GLenum mag, bool bindTexture = false, bool force = false,
+            GLenum renderTarget = GL_TEXTURE_2D) {
+
+        if (firstFilter || force || min != minFilter || mag != magFilter) {
+            firstFilter = false;
+
+            minFilter = min;
+            magFilter = mag;
+
+            if (bindTexture) {
+                glBindTexture(renderTarget, id);
+            }
+
+            glTexParameteri(renderTarget, GL_TEXTURE_MIN_FILTER, min);
+            glTexParameteri(renderTarget, GL_TEXTURE_MAG_FILTER, mag);
+        }
     }
 
     /**
@@ -87,6 +116,10 @@
      */
     GLenum minFilter;
     GLenum magFilter;
+
+private:
+    bool firstFilter;
+    bool firstWrap;
 }; // struct Texture
 
 class AutoTexture {
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index 3752874..f926fdd 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -219,11 +219,8 @@
         break;
     }
 
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    texture->setFilter(GL_LINEAR, GL_LINEAR);
+    texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
 }
 
 void TextureCache::uploadLoFiTexture(bool resize, SkBitmap* bitmap,
diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp
index cb6c246..6cf01c8 100644
--- a/libs/utils/ResourceTypes.cpp
+++ b/libs/utils/ResourceTypes.cpp
@@ -4346,7 +4346,8 @@
                 | (0x0000ffff & (entryIndex));
             resource_name resName;
             if (!this->getResourceName(resID, &resName)) {
-                return UNKNOWN_ERROR;
+                LOGW("idmap: resource 0x%08x has spec but lacks values, skipping\n", resID);
+                continue;
             }
 
             const String16 overlayType(resName.type, resName.typeLen);
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 02a955b..3e037c1 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -78,7 +78,8 @@
         SaveImageInBackgroundData> {
     private static final String TAG = "SaveImageInBackgroundTask";
     private static final String SCREENSHOTS_DIR_NAME = "Screenshots";
-    private static final String SCREENSHOT_FILE_PATH_TEMPLATE = "%s/%s/Screenshot_%s-%d.png";
+    private static final String SCREENSHOT_FILE_NAME_TEMPLATE = "Screenshot_%s.png";
+    private static final String SCREENSHOT_FILE_PATH_TEMPLATE = "%s/%s/%s";
 
     @Override
     protected SaveImageInBackgroundData doInBackground(SaveImageInBackgroundData... params) {
@@ -89,18 +90,18 @@
 
         try {
             long currentTime = System.currentTimeMillis();
-            String date = new SimpleDateFormat("MM-dd-yy-kk-mm-ss").format(new Date(currentTime));
+            String date = new SimpleDateFormat("yyyy-MM-dd-kk-mm-ss").format(new Date(currentTime));
             String imageDir = Environment.getExternalStoragePublicDirectory(
                     Environment.DIRECTORY_PICTURES).getAbsolutePath();
-            String imageFilePath = String.format(SCREENSHOT_FILE_PATH_TEMPLATE,
-                    imageDir, SCREENSHOTS_DIR_NAME,
-                    date, currentTime % 1000);
+            String imageFileName = String.format(SCREENSHOT_FILE_NAME_TEMPLATE, date);
+            String imageFilePath = String.format(SCREENSHOT_FILE_PATH_TEMPLATE, imageDir,
+                    SCREENSHOTS_DIR_NAME, imageFileName);
 
             // Save the screenshot to the MediaStore
             ContentValues values = new ContentValues();
             values.put(MediaStore.Images.ImageColumns.DATA, imageFilePath);
-            values.put(MediaStore.Images.ImageColumns.TITLE, "Screenshot");
-            values.put(MediaStore.Images.ImageColumns.DISPLAY_NAME, "Screenshot");
+            values.put(MediaStore.Images.ImageColumns.TITLE, imageFileName);
+            values.put(MediaStore.Images.ImageColumns.DISPLAY_NAME, imageFileName);
             values.put(MediaStore.Images.ImageColumns.DATE_TAKEN, currentTime);
             values.put(MediaStore.Images.ImageColumns.DATE_ADDED, currentTime);
             values.put(MediaStore.Images.ImageColumns.DATE_MODIFIED, currentTime);
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 79c0675..0843948 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -1926,7 +1926,8 @@
     }
 
     // Caller must grab mDnsLock.
-    private boolean updateDns(String network, Collection<InetAddress> dnses, String domains) {
+    private boolean updateDns(String network, String iface,
+            Collection<InetAddress> dnses, String domains) {
         boolean changed = false;
         int last = 0;
         if (dnses.size() == 0 && mDefaultDns != null) {
@@ -1962,6 +1963,14 @@
         }
         mNumDnsEntries = last;
 
+        if (changed) {
+            try {
+                mNetd.setDnsServersForInterface(iface, NetworkUtils.makeStrings(dnses));
+                mNetd.setDefaultInterfaceForDns(iface);
+            } catch (Exception e) {
+                Slog.e(TAG, "exception setting default dns interface: " + e);
+            }
+        }
         if (!domains.equals(SystemProperties.get("net.dns.search"))) {
             SystemProperties.set("net.dns.search", domains);
             changed = true;
@@ -1981,10 +1990,16 @@
                 String network = nt.getNetworkInfo().getTypeName();
                 synchronized (mDnsLock) {
                     if (!mDnsOverridden) {
-                        changed = updateDns(network, dnses, "");
+                        changed = updateDns(network, p.getInterfaceName(), dnses, "");
                     }
                 }
             } else {
+                try {
+                    mNetd.setDnsServersForInterface(Integer.toString(netType),
+                            NetworkUtils.makeStrings(dnses));
+                } catch (Exception e) {
+                    Slog.e(TAG, "exception setting dns servers: " + e);
+                }
                 // set per-pid dns for attached secondary nets
                 List pids = mNetRequestersPids[netType];
                 for (int y=0; y< pids.size(); y++) {
@@ -2686,7 +2701,7 @@
             // Apply DNS changes.
             boolean changed = false;
             synchronized (mDnsLock) {
-                changed = updateDns("VPN", addresses, domains);
+                changed = updateDns("VPN", "VPN", addresses, domains);
                 mDnsOverridden = true;
             }
             if (changed) {
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 5d7a48f..8031c4e 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -469,6 +469,24 @@
                     record = mToastQueue.get(index);
                     record.update(duration);
                 } else {
+                    // Limit the number of toasts that any given package except the android
+                    // package can enqueue.  Prevents DOS attacks and deals with leaks.
+                    if (!"android".equals(pkg)) {
+                        int count = 0;
+                        final int N = mToastQueue.size();
+                        for (int i=0; i<N; i++) {
+                             final ToastRecord r = mToastQueue.get(i);
+                             if (r.pkg.equals(pkg)) {
+                                 count++;
+                                 if (count >= MAX_PACKAGE_NOTIFICATIONS) {
+                                     Slog.e(TAG, "Package has already posted " + count
+                                            + " toasts. Not showing more. Package=" + pkg);
+                                     return;
+                                 }
+                             }
+                        }
+                    }
+
                     record = new ToastRecord(callingPid, pkg, callback, duration);
                     mToastQueue.add(record);
                     index = mToastQueue.size() - 1;
diff --git a/services/java/com/android/server/VibratorService.java b/services/java/com/android/server/VibratorService.java
index c39dc80..de25747 100755
--- a/services/java/com/android/server/VibratorService.java
+++ b/services/java/com/android/server/VibratorService.java
@@ -383,6 +383,12 @@
             if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
                 synchronized (mVibrations) {
                     doCancelVibrateLocked();
+
+                    int size = mVibrations.size();
+                    for(int i = 0; i < size; i++) {
+                        unlinkVibration(mVibrations.get(i));
+                    }
+
                     mVibrations.clear();
                 }
             }
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateClassAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateClassAdapter.java
index 49ddf1d..0e24cc0 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateClassAdapter.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateClassAdapter.java
@@ -117,8 +117,10 @@
 
         int accessDelegate = access;
         // change access to public for the original one
-        access &= ~(Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE);
-        access |= Opcodes.ACC_PUBLIC;
+        if (Main.sOptions.generatePublicAccess) {
+            access &= ~(Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE);
+            access |= Opcodes.ACC_PUBLIC;
+        }
 
         MethodVisitor mwOriginal = super.visitMethod(access, name + ORIGINAL_SUFFIX,
                                                      desc, signature, exceptions);
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
index ce48069..9bf52c7 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
@@ -37,7 +37,7 @@
  * which does:
  * <pre>
  * $ make layoutlib_create &lt;bunch of framework jars&gt;
- * $ out/host/linux-x86/framework/bin/layoutlib_create \
+ * $ java -jar out/host/linux-x86/framework/layoutlib_create.jar \
  *        out/host/common/obj/JAVA_LIBRARIES/temp_layoutlib_intermediates/javalib.jar \
  *        out/target/common/obj/JAVA_LIBRARIES/core_intermediates/classes.jar \
  *        out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar
@@ -45,6 +45,12 @@
  */
 public class Main {
 
+    public static class Options {
+        public boolean generatePublicAccess = true;
+    }
+
+    public static final Options sOptions = new Options();
+
     public static void main(String[] args) {
 
         Log log = new Log();
@@ -53,7 +59,7 @@
         String[] osDestJar = { null };
 
         if (!processArgs(log, args, osJarPath, osDestJar)) {
-            log.error("Usage: layoutlib_create [-v] output.jar input.jar ...");
+            log.error("Usage: layoutlib_create [-v] [-p] output.jar input.jar ...");
             System.exit(1);
         }
 
@@ -136,6 +142,8 @@
             String s = args[i];
             if (s.equals("-v")) {
                 log.setVerbose(true);
+            } else if (s.equals("-p")) {
+                sOptions.generatePublicAccess = false;
             } else if (!s.startsWith("-")) {
                 if (osDestJar[0] == null) {
                     osDestJar[0] = s;
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/TransformClassAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/TransformClassAdapter.java
index f2d9755..5a0a44a4 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/TransformClassAdapter.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/TransformClassAdapter.java
@@ -72,8 +72,10 @@
         name = mClassName;
 
         // remove protected or private and set as public
-        access = access & ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED);
-        access |= Opcodes.ACC_PUBLIC;
+        if (Main.sOptions.generatePublicAccess) {
+            access = access & ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED);
+            access |= Opcodes.ACC_PUBLIC;
+        }
         // remove final
         access = access & ~Opcodes.ACC_FINAL;
         // note: leave abstract classes as such
@@ -87,8 +89,10 @@
     @Override
     public void visitInnerClass(String name, String outerName, String innerName, int access) {
         // remove protected or private and set as public
-        access = access & ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED);
-        access |= Opcodes.ACC_PUBLIC;
+        if (Main.sOptions.generatePublicAccess) {
+            access = access & ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED);
+            access |= Opcodes.ACC_PUBLIC;
+        }
         // remove final
         access = access & ~Opcodes.ACC_FINAL;
         // note: leave abstract classes as such
@@ -117,8 +121,10 @@
         String methodSignature = mClassName.replace('/', '.') + "#" + name;
 
         // change access to public
-        access &= ~(Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE);
-        access |= Opcodes.ACC_PUBLIC;
+        if (Main.sOptions.generatePublicAccess) {
+            access &= ~(Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE);
+            access |= Opcodes.ACC_PUBLIC;
+        }
 
         // remove final
         access = access & ~Opcodes.ACC_FINAL;
@@ -155,9 +161,10 @@
     public FieldVisitor visitField(int access, String name, String desc, String signature,
             Object value) {
         // change access to public
-        access &= ~(Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE);
-        access |= Opcodes.ACC_PUBLIC;
-
+        if (Main.sOptions.generatePublicAccess) {
+            access &= ~(Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE);
+            access |= Opcodes.ACC_PUBLIC;
+        }
         return super.visitField(access, name, desc, signature, value);
     }