Merge "Color theming for VectorDrawable, general clean up"
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index d6eafc6..4879c23 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1585,6 +1585,15 @@
 
         /** Resource identifier for the theme. */
         private int mThemeResId = 0;
+
+        // Needed by layoutlib.
+        /*package*/ long getNativeTheme() {
+            return mTheme;
+        }
+
+        /*package*/ int getAppliedStyleResId() {
+            return mThemeResId;
+        }
     }
 
     /**
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index d079349c..cf95657 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -59,13 +59,14 @@
 
 static jlong android_view_RenderNode_create(JNIEnv* env, jobject clazz) {
     RenderNode* displayList = new RenderNode();
+    displayList->incStrong(0);
     return reinterpret_cast<jlong>(displayList);
 }
 
 static void android_view_RenderNode_destroyDisplayList(JNIEnv* env,
         jobject clazz, jlong displayListPtr) {
     RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    RenderNode::destroyDisplayListDeferred(displayList);
+    displayList->decStrong(0);
 }
 
 // ----------------------------------------------------------------------------
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 477d691..df2123b 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -315,24 +315,15 @@
     pathCache.clearGarbage();
     patchCache.clearGarbage();
 
-    Vector<RenderNode*> displayLists;
     Vector<Layer*> layers;
 
     { // scope for the lock
         Mutex::Autolock _l(mGarbageLock);
-        displayLists = mDisplayListGarbage;
         layers = mLayerGarbage;
-        mDisplayListGarbage.clear();
         mLayerGarbage.clear();
     }
 
-    size_t count = displayLists.size();
-    for (size_t i = 0; i < count; i++) {
-        RenderNode* displayList = displayLists.itemAt(i);
-        delete displayList;
-    }
-
-    count = layers.size();
+    size_t count = layers.size();
     for (size_t i = 0; i < count; i++) {
         Layer* layer = layers.itemAt(i);
         delete layer;
@@ -345,11 +336,6 @@
     mLayerGarbage.push(layer);
 }
 
-void Caches::deleteDisplayListDeferred(RenderNode* displayList) {
-    Mutex::Autolock _l(mGarbageLock);
-    mDisplayListGarbage.push(displayList);
-}
-
 void Caches::flush(FlushMode mode) {
     FLUSH_LOGD("Flushing caches (mode %d)", mode);
 
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 50c5fef..ba3ccaf 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -166,11 +166,6 @@
      */
     void deleteLayerDeferred(Layer* layer);
 
-    /*
-     * Can be used to delete a display list from a non EGL thread.
-     */
-    void deleteDisplayListDeferred(RenderNode* layer);
-
     /**
      * Binds the VBO used to render simple textured quads.
      */
@@ -420,7 +415,6 @@
 
     mutable Mutex mGarbageLock;
     Vector<Layer*> mLayerGarbage;
-    Vector<RenderNode*> mDisplayListGarbage;
 
     DebugLevel mDebugLevel;
     bool mInitialized;
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index 5b4e03f..ce711b6 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -68,13 +68,13 @@
     mLayer->setColorFilter(mColorFilter);
     mLayer->setAlpha(mAlpha, mMode);
 
-    if (mDisplayList) {
+    if (mDisplayList.get()) {
         if (mWidth != mLayer->layer.getWidth() || mHeight != mLayer->layer.getHeight()) {
             success = LayerRenderer::resizeLayer(mLayer, mWidth, mHeight);
         }
         mLayer->setBlend(mBlend);
         mDisplayList->updateProperties();
-        mLayer->updateDeferred(mDisplayList,
+        mLayer->updateDeferred(mDisplayList.get(),
                 mDirtyRect.left, mDirtyRect.top, mDirtyRect.right, mDirtyRect.bottom);
         mDirtyRect.setEmpty();
         mDisplayList = 0;
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index 10fa264..ce08c2d 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -101,7 +101,7 @@
     // Layer type specific properties
     // displayList and surfaceTexture are mutually exclusive, only 1 may be set
     // dirtyRect is only valid if displayList is set
-    RenderNode* mDisplayList;
+    sp<RenderNode> mDisplayList;
     Rect mDirtyRect;
     sp<GLConsumer> mSurfaceTexture;
     SkMatrix* mTransform;
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index 9e6a96d..a5d8dcb 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -29,6 +29,13 @@
 namespace android {
 namespace uirenderer {
 
+DisplayListData::DisplayListData() : projectionReceiveIndex(-1), functorCount(0), hasDrawOps(false) {
+}
+
+DisplayListData::~DisplayListData() {
+    cleanupResources();
+}
+
 void DisplayListData::cleanupResources() {
     Caches& caches = Caches::getInstance();
     caches.unregisterFunctors(functorCount);
@@ -91,5 +98,12 @@
     layers.clear();
 }
 
+void DisplayListData::addChild(DrawDisplayListOp* op) {
+    LOG_ALWAYS_FATAL_IF(!op->renderNode(), "DrawDisplayListOp with no render node!");
+
+    mChildren.push(op);
+    mReferenceHolders.push(op->renderNode());
+}
+
 }; // namespace uirenderer
 }; // namespace android
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index df5cba6..fe70d13 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -41,6 +41,7 @@
 #include "Matrix.h"
 #include "DeferredDisplayList.h"
 #include "RenderProperties.h"
+#include "utils/VirtualLightRefBase.h"
 
 class SkBitmap;
 class SkPaint;
@@ -106,8 +107,8 @@
  */
 class DisplayListData {
 public:
-    DisplayListData() : projectionReceiveIndex(-1), functorCount(0), hasDrawOps(false) {}
-    virtual ~DisplayListData() { cleanupResources(); }
+    DisplayListData();
+    ~DisplayListData();
 
     // allocator into which all ops were allocated
     LinearAllocator allocator;
@@ -115,9 +116,6 @@
     // pointers to all ops within display list, pointing into allocator data
     Vector<DisplayListOp*> displayListOps;
 
-    // list of children display lists for quick, non-drawing traversal
-    Vector<DrawDisplayListOp*> children;
-
     // index of DisplayListOp restore, after which projected descendents should be drawn
     int projectionReceiveIndex;
 
@@ -139,7 +137,15 @@
         return !displayListOps.size();
     }
 
+    void addChild(DrawDisplayListOp* childOp);
+    const Vector<DrawDisplayListOp*>& children() { return mChildren; }
+
 private:
+    Vector< sp<VirtualLightRefBase> > mReferenceHolders;
+
+    // list of children display lists for quick, non-drawing traversal
+    Vector<DrawDisplayListOp*> mChildren;
+
     void cleanupResources();
 };
 
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 5fa8f1d..06f675e 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1523,6 +1523,8 @@
 
     virtual const char* name() { return "DrawDisplayList"; }
 
+    RenderNode* renderNode() { return mDisplayList; }
+
 private:
     RenderNode* mDisplayList;
     const int mFlags;
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 78c97e1..a84aa6b 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -191,7 +191,7 @@
     DrawDisplayListOp* op = new (alloc()) DrawDisplayListOp(displayList,
             flags, *currentTransform());
     addDrawOp(op);
-    mDisplayListData->children.push(op);
+    mDisplayListData->addChild(op);
     if (displayList->isProjectionReceiver()) {
         mDisplayListData->projectionReceiveIndex = mDisplayListData->displayListOps.size() - 1;
     }
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 27409a2..bfe4eda 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -140,6 +140,15 @@
     }
 }
 
+void Layer::updateDeferred(RenderNode* displayList,
+        int left, int top, int right, int bottom) {
+    requireRenderer();
+    this->displayList = displayList;
+    const Rect r(left, top, right, bottom);
+    dirtyRect.unionWith(r);
+    deferredUpdateScheduled = true;
+}
+
 void Layer::setPaint(const SkPaint* paint) {
     OpenGLRenderer::getAlphaAndModeDirect(paint, &alpha, &mode);
     setColorFilter((paint) ? paint->getColorFilter() : NULL);
@@ -244,7 +253,7 @@
     renderer->prepareDirty(dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom,
             !isBlend());
 
-    renderer->drawDisplayList(displayList, dirtyRect, RenderNode::kReplayFlag_ClipChildren);
+    renderer->drawDisplayList(displayList.get(), dirtyRect, RenderNode::kReplayFlag_ClipChildren);
 
     renderer->finish();
 
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index b428404..5375b45 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -19,6 +19,7 @@
 
 #include <cutils/compiler.h>
 #include <sys/types.h>
+#include <utils/StrongPointer.h>
 
 #include <GLES2/gl2.h>
 
@@ -85,13 +86,7 @@
     }
 
     void updateDeferred(RenderNode* displayList,
-            int left, int top, int right, int bottom) {
-        requireRenderer();
-        this->displayList = displayList;
-        const Rect r(left, top, right, bottom);
-        dirtyRect.unionWith(r);
-        deferredUpdateScheduled = true;
-    }
+            int left, int top, int right, int bottom);
 
     inline uint32_t getWidth() const {
         return texture.width;
@@ -294,7 +289,7 @@
      */
     bool deferredUpdateScheduled;
     OpenGLRenderer* renderer;
-    RenderNode* displayList;
+    sp<RenderNode> displayList;
     Rect dirtyRect;
     bool debugDrawUpdate;
     bool hasDrawnSinceUpdate;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index e1f484d..9dbcd36 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -537,7 +537,7 @@
 
 bool OpenGLRenderer::updateLayer(Layer* layer, bool inFrame) {
     if (layer->deferredUpdateScheduled && layer->renderer &&
-            layer->displayList && layer->displayList->isRenderable()) {
+            layer->displayList.get() && layer->displayList->isRenderable()) {
         ATRACE_CALL();
 
         Rect& dirty = layer->dirtyRect;
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 663b67e..5010076 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -59,17 +59,6 @@
     delete mDisplayListData;
 }
 
-void RenderNode::destroyDisplayListDeferred(RenderNode* displayList) {
-    if (displayList) {
-        if (Caches::hasInstance()) {
-            DISPLAY_LIST_LOGD("Deferring display list destruction");
-            Caches::getInstance().deleteDisplayListDeferred(displayList);
-        } else {
-            delete displayList;
-        }
-    }
-}
-
 void RenderNode::setData(DisplayListData* data) {
     delete mDisplayListData;
     mDisplayListData = data;
@@ -104,8 +93,8 @@
     }
 
     if (mDisplayListData) {
-        for (size_t i = 0; i < mDisplayListData->children.size(); i++) {
-            RenderNode* childNode = mDisplayListData->children[i]->mDisplayList;
+        for (size_t i = 0; i < mDisplayListData->children().size(); i++) {
+            RenderNode* childNode = mDisplayListData->children()[i]->mDisplayList;
             childNode->updateProperties();
         }
     }
@@ -118,8 +107,8 @@
         return true;
     }
 
-    for (size_t i = 0; i < mDisplayListData->children.size(); i++) {
-        RenderNode* childNode = mDisplayListData->children[i]->mDisplayList;
+    for (size_t i = 0; i < mDisplayListData->children().size(); i++) {
+        RenderNode* childNode = mDisplayListData->children()[i]->mDisplayList;
         if (childNode->hasFunctors()) {
             return true;
         }
@@ -248,8 +237,8 @@
     // TODO: create temporary DDLOp and call computeOrderingImpl on top DisplayList so that
     // transform properties are applied correctly to top level children
     if (mDisplayListData == NULL) return;
-    for (unsigned int i = 0; i < mDisplayListData->children.size(); i++) {
-        DrawDisplayListOp* childOp = mDisplayListData->children[i];
+    for (unsigned int i = 0; i < mDisplayListData->children().size(); i++) {
+        DrawDisplayListOp* childOp = mDisplayListData->children()[i];
         childOp->mDisplayList->computeOrderingImpl(childOp,
                 &mProjectedNodes, &mat4::identity());
     }
@@ -277,11 +266,11 @@
         opState->mSkipInOrderDraw = false;
     }
 
-    if (mDisplayListData->children.size() > 0) {
+    if (mDisplayListData->children().size() > 0) {
         const bool isProjectionReceiver = mDisplayListData->projectionReceiveIndex >= 0;
         bool haveAppliedPropertiesToProjection = false;
-        for (unsigned int i = 0; i < mDisplayListData->children.size(); i++) {
-            DrawDisplayListOp* childOp = mDisplayListData->children[i];
+        for (unsigned int i = 0; i < mDisplayListData->children().size(); i++) {
+            DrawDisplayListOp* childOp = mDisplayListData->children()[i];
             RenderNode* child = childOp->mDisplayList;
 
             Vector<DrawDisplayListOp*>* projectionChildren = NULL;
@@ -375,10 +364,10 @@
 }
 
 void RenderNode::buildZSortedChildList(Vector<ZDrawDisplayListOpPair>& zTranslatedNodes) {
-    if (mDisplayListData == NULL || mDisplayListData->children.size() == 0) return;
+    if (mDisplayListData == NULL || mDisplayListData->children().size() == 0) return;
 
-    for (unsigned int i = 0; i < mDisplayListData->children.size(); i++) {
-        DrawDisplayListOp* childOp = mDisplayListData->children[i];
+    for (unsigned int i = 0; i < mDisplayListData->children().size(); i++) {
+        DrawDisplayListOp* childOp = mDisplayListData->children()[i];
         RenderNode* child = childOp->mDisplayList;
         float childZ = child->properties().getTranslationZ();
 
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index fb5336d..fd0fabc 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -41,6 +41,7 @@
 #include "DeferredDisplayList.h"
 #include "DisplayList.h"
 #include "RenderProperties.h"
+#include "utils/VirtualLightRefBase.h"
 
 class SkBitmap;
 class SkPaint;
@@ -76,7 +77,7 @@
  * recorded stream of canvas operations is refreshed. The DisplayList (and its properties) stay
  * attached.
  */
-class RenderNode {
+class RenderNode : public VirtualLightRefBase {
 public:
     ANDROID_API RenderNode();
     ANDROID_API ~RenderNode();
@@ -86,7 +87,6 @@
         kReplayFlag_ClipChildren = 0x1
     };
 
-    ANDROID_API static void destroyDisplayListDeferred(RenderNode* displayList);
     ANDROID_API static void outputLogBuffer(int fd);
 
     ANDROID_API void setData(DisplayListData* newData);
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 1e9089a..7b509a2 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -30,7 +30,19 @@
 namespace uirenderer {
 namespace renderthread {
 
-DrawFrameTask::DrawFrameTask() : mContext(0), mRenderNode(0) {
+SetDisplayListData::SetDisplayListData() : mNewData(0) {}
+
+SetDisplayListData::SetDisplayListData(RenderNode* node, DisplayListData* newData)
+        : mTargetNode(node), mNewData(newData) {
+}
+
+SetDisplayListData::~SetDisplayListData() {}
+
+void SetDisplayListData::apply() const {
+    mTargetNode->setData(mNewData);
+}
+
+DrawFrameTask::DrawFrameTask() : mContext(0), mTaskMode(MODE_INVALID), mRenderNode(0) {
 }
 
 DrawFrameTask::~DrawFrameTask() {
@@ -41,13 +53,15 @@
 }
 
 void DrawFrameTask::setDisplayListData(RenderNode* renderNode, DisplayListData* newData) {
-    SetDisplayListData setter;
-    setter.targetNode = renderNode;
-    setter.newData = newData;
+    LOG_ALWAYS_FATAL_IF(!mContext, "Lifecycle violation, there's no context to setDisplayListData with!");
+
+    SetDisplayListData setter(renderNode, newData);
     mDisplayListDataUpdates.push(setter);
 }
 
 void DrawFrameTask::addLayer(DeferredLayerUpdater* layer) {
+    LOG_ALWAYS_FATAL_IF(!mContext, "Lifecycle violation, there's no context to addLayer with!");
+
     mLayers.push(layer);
 }
 
@@ -61,6 +75,8 @@
 }
 
 void DrawFrameTask::setRenderNode(RenderNode* renderNode) {
+    LOG_ALWAYS_FATAL_IF(!mContext, "Lifecycle violation, there's no context to setRenderNode with!");
+
     mRenderNode = renderNode;
 }
 
@@ -69,37 +85,55 @@
 }
 
 void DrawFrameTask::drawFrame(RenderThread* renderThread) {
-    LOG_ALWAYS_FATAL_IF(!mRenderNode, "Cannot drawFrame with no render node!");
+    LOG_ALWAYS_FATAL_IF(!mRenderNode.get(), "Cannot drawFrame with no render node!");
     LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!");
 
-    AutoMutex _lock(mLock);
-    renderThread->queue(this);
-    mSignal.wait(mLock);
+    postAndWait(renderThread, MODE_FULL);
 
     // Reset the single-frame data
     mDirty.setEmpty();
     mRenderNode = 0;
 }
 
+void DrawFrameTask::flushStateChanges(RenderThread* renderThread) {
+    LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!");
+
+    postAndWait(renderThread, MODE_STATE_ONLY);
+}
+
+void DrawFrameTask::postAndWait(RenderThread* renderThread, TaskMode mode) {
+    LOG_ALWAYS_FATAL_IF(mode == MODE_INVALID, "That's not a real mode, silly!");
+
+    mTaskMode = mode;
+    AutoMutex _lock(mLock);
+    renderThread->queue(this);
+    mSignal.wait(mLock);
+}
+
 void DrawFrameTask::run() {
     ATRACE_NAME("DrawFrame");
 
     syncFrameState();
 
+    if (mTaskMode == MODE_STATE_ONLY) {
+        unblockUiThread();
+        return;
+    }
+
     // Grab a copy of everything we need
     Rect dirtyCopy(mDirty);
-    RenderNode* renderNode = mRenderNode;
+    sp<RenderNode> renderNode = mRenderNode;
     CanvasContext* context = mContext;
 
     // This is temporary until WebView has a solution for syncing frame state
-    bool canUnblockUiThread = !requiresSynchronousDraw(renderNode);
+    bool canUnblockUiThread = !requiresSynchronousDraw(renderNode.get());
 
     // From this point on anything in "this" is *UNSAFE TO ACCESS*
     if (canUnblockUiThread) {
         unblockUiThread();
     }
 
-    drawRenderNode(context, renderNode, &dirtyCopy);
+    drawRenderNode(context, renderNode.get(), &dirtyCopy);
 
     if (!canUnblockUiThread) {
         unblockUiThread();
@@ -111,12 +145,16 @@
 
     for (size_t i = 0; i < mDisplayListDataUpdates.size(); i++) {
         const SetDisplayListData& setter = mDisplayListDataUpdates[i];
-        setter.targetNode->setData(setter.newData);
+        setter.apply();
     }
     mDisplayListDataUpdates.clear();
 
     mContext->processLayerUpdates(&mLayers);
-    mRenderNode->updateProperties();
+
+    // If we don't have an mRenderNode this is a state flush only
+    if (mRenderNode.get()) {
+        mRenderNode->updateProperties();
+    }
 }
 
 void DrawFrameTask::unblockUiThread() {
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index 5450dd5..4e9b244 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -18,6 +18,7 @@
 
 #include <utils/Condition.h>
 #include <utils/Mutex.h>
+#include <utils/StrongPointer.h>
 #include <utils/Vector.h>
 
 #include "RenderTask.h"
@@ -36,9 +37,16 @@
 class CanvasContext;
 class RenderThread;
 
-struct SetDisplayListData {
-    RenderNode* targetNode;
-    DisplayListData* newData;
+class SetDisplayListData {
+public:
+    // This ctor exists for Vector's usage
+    SetDisplayListData();
+    SetDisplayListData(RenderNode* node, DisplayListData* newData);
+    ~SetDisplayListData();
+    void apply() const;
+private:
+    sp<RenderNode> mTargetNode;
+    DisplayListData* mNewData;
 };
 
 /*
@@ -61,10 +69,18 @@
     void setRenderNode(RenderNode* renderNode);
     void setDirty(int left, int top, int right, int bottom);
     void drawFrame(RenderThread* renderThread);
+    void flushStateChanges(RenderThread* renderThread);
 
     virtual void run();
 
 private:
+    enum TaskMode {
+        MODE_INVALID,
+        MODE_FULL,
+        MODE_STATE_ONLY,
+    };
+
+    void postAndWait(RenderThread* renderThread, TaskMode mode);
     void syncFrameState();
     void unblockUiThread();
     static void drawRenderNode(CanvasContext* context, RenderNode* renderNode, Rect* dirty);
@@ -81,7 +97,8 @@
     /*********************************************
      *  Single frame data
      *********************************************/
-    RenderNode* mRenderNode;
+    TaskMode mTaskMode;
+    sp<RenderNode> mRenderNode;
     Rect mDirty;
     Vector<SetDisplayListData> mDisplayListDataUpdates;
 
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index cd711b0..43182d5 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -75,6 +75,9 @@
 
 void RenderProxy::destroyContext() {
     if (mContext) {
+        // Flush any pending changes to ensure all garbage is destroyed
+        mDrawFrameTask.flushStateChanges(&mRenderThread);
+
         SETUP_TASK(destroyContext);
         args->context = mContext;
         mContext = 0;
@@ -138,6 +141,10 @@
 }
 
 void RenderProxy::destroyCanvas() {
+    // If the canvas is being destroyed we won't be drawing again anytime soon
+    // So flush any pending state changes to allow for resource cleanup.
+    mDrawFrameTask.flushStateChanges(&mRenderThread);
+
     SETUP_TASK(destroyCanvas);
     args->context = mContext;
     post(task);
diff --git a/libs/hwui/utils/VirtualLightRefBase.h b/libs/hwui/utils/VirtualLightRefBase.h
new file mode 100644
index 0000000..b545aab
--- /dev/null
+++ b/libs/hwui/utils/VirtualLightRefBase.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef VIRTUALLIGHTREFBASE_H
+#define VIRTUALLIGHTREFBASE_H
+
+#include <utils/RefBase.h>
+
+namespace android {
+namespace uirenderer {
+
+// This is a wrapper around LightRefBase that simply enforces a virtual
+// destructor to eliminate the template requirement of LightRefBase
+class VirtualLightRefBase : public LightRefBase<VirtualLightRefBase> {
+public:
+    virtual ~VirtualLightRefBase() {}
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* VIRTUALLIGHTREFBASE_H */
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
old mode 100644
new mode 100755
index 33b12c5..d596472
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -522,13 +522,6 @@
         if (fullscreen == toOpaque) {
             return false;
         }
-        AttributeCache.Entry ent =
-                AttributeCache.instance().get(packageName, realTheme, styleable.Window, userId);
-        if (ent == null
-                || !ent.array.getBoolean(styleable.Window_windowIsTranslucent, false)
-                || ent.array.getBoolean(styleable.Window_windowIsFloating, false)) {
-            return false;
-        }
 
         // Keep track of the number of fullscreen activities in this task.
         task.numFullscreen += toOpaque ? +1 : -1;
@@ -956,8 +949,8 @@
         // for another app to start, then we have paused dispatching
         // for this activity.
         ActivityRecord r = this;
-        final ActivityStack stack = task.stack;
         if (r.waitingVisible) {
+            final ActivityStack stack = mStackSupervisor.getFocusedStack();
             // Hmmm, who might we be waiting for?
             r = stack.mResumedActivity;
             if (r == null) {
diff --git a/tools/layoutlib/bridge/src/android/content/res/AssetManager_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/AssetManager_Delegate.java
new file mode 100644
index 0000000..914a359
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/content/res/AssetManager_Delegate.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.res;
+
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+/**
+ * Delegate used to provide implementation of a select few native methods of {@link AssetManager}
+ * <p/>
+ * Through the layoutlib_create tool, the original native methods of AssetManager have been replaced
+ * by calls to methods of the same name in this delegate class.
+ *
+ */
+public class AssetManager_Delegate {
+
+    @LayoutlibDelegate
+    /*package*/ static long newTheme(AssetManager manager) {
+        return Resources_Theme_Delegate.getDelegateManager()
+                .addNewDelegate(new Resources_Theme_Delegate());
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static void deleteTheme(AssetManager manager, long theme) {
+        Resources_Theme_Delegate.getDelegateManager().removeJavaReferenceFor(theme);
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static void applyThemeStyle(long theme, int styleRes, boolean force) {
+        Resources_Theme_Delegate.getDelegateManager().getDelegate(theme).force = force;
+    }
+}
diff --git a/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java
index c9d615c..31d1594 100644
--- a/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java
@@ -16,7 +16,13 @@
 
 package android.content.res;
 
+import com.android.annotations.Nullable;
+import com.android.ide.common.rendering.api.ResourceReference;
+import com.android.ide.common.rendering.api.StyleResourceValue;
+import com.android.layoutlib.bridge.android.BridgeContext;
+import com.android.layoutlib.bridge.impl.DelegateManager;
 import com.android.layoutlib.bridge.impl.RenderSessionImpl;
+import com.android.resources.ResourceType;
 import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
 
 import android.content.res.Resources.NotFoundException;
@@ -25,7 +31,7 @@
 import android.util.TypedValue;
 
 /**
- * Delegate used to provide new implementation of a select few methods of {@link Resources$Theme}
+ * Delegate used to provide new implementation of a select few methods of {@link Resources.Theme}
  *
  * Through the layoutlib_create tool, the original  methods of Theme have been replaced
  * by calls to methods of the same name in this delegate class.
@@ -33,11 +39,28 @@
  */
 public class Resources_Theme_Delegate {
 
+    // Whether to use the Theme.mThemeResId as primary theme.
+    boolean force;
+
+    // ---- delegate manager ----
+
+    private static final DelegateManager<Resources_Theme_Delegate> sManager =
+            new DelegateManager<Resources_Theme_Delegate>(Resources_Theme_Delegate.class);
+
+    public static DelegateManager<Resources_Theme_Delegate> getDelegateManager() {
+        return sManager;
+    }
+
+    // ---- delegate methods. ----
+
     @LayoutlibDelegate
     /*package*/ static TypedArray obtainStyledAttributes(
             Resources thisResources, Theme thisTheme,
             int[] attrs) {
-        return RenderSessionImpl.getCurrentContext().obtainStyledAttributes(attrs);
+        boolean changed = setupResources(thisTheme);
+        TypedArray ta = RenderSessionImpl.getCurrentContext().obtainStyledAttributes(attrs);
+        restoreResources(changed);
+        return ta;
     }
 
     @LayoutlibDelegate
@@ -45,15 +68,21 @@
             Resources thisResources, Theme thisTheme,
             int resid, int[] attrs)
             throws NotFoundException {
-        return RenderSessionImpl.getCurrentContext().obtainStyledAttributes(resid, attrs);
+        boolean changed = setupResources(thisTheme);
+        TypedArray ta = RenderSessionImpl.getCurrentContext().obtainStyledAttributes(resid, attrs);
+        restoreResources(changed);
+        return ta;
     }
 
     @LayoutlibDelegate
     /*package*/ static TypedArray obtainStyledAttributes(
             Resources thisResources, Theme thisTheme,
             AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) {
-        return RenderSessionImpl.getCurrentContext().obtainStyledAttributes(
-                set, attrs, defStyleAttr, defStyleRes);
+        boolean changed = setupResources(thisTheme);
+        TypedArray ta = RenderSessionImpl.getCurrentContext().obtainStyledAttributes(set, attrs,
+                defStyleAttr, defStyleRes);
+        restoreResources(changed);
+        return ta;
     }
 
     @LayoutlibDelegate
@@ -61,7 +90,45 @@
             Resources thisResources, Theme thisTheme,
             int resid, TypedValue outValue,
             boolean resolveRefs) {
-        return RenderSessionImpl.getCurrentContext().resolveThemeAttribute(
+        boolean changed = setupResources(thisTheme);
+        boolean found =  RenderSessionImpl.getCurrentContext().resolveThemeAttribute(
                 resid, outValue, resolveRefs);
+        restoreResources(changed);
+        return found;
+    }
+
+    // ---- private helper methods ----
+
+    private static boolean setupResources(Theme thisTheme) {
+        Resources_Theme_Delegate themeDelegate = sManager.getDelegate(thisTheme.getNativeTheme());
+        StyleResourceValue style = resolveStyle(thisTheme.getAppliedStyleResId());
+        if (style != null) {
+            RenderSessionImpl.getCurrentContext().getRenderResources()
+                    .applyStyle(style, themeDelegate.force);
+            return true;
+        }
+        return false;
+    }
+
+    private static void restoreResources(boolean changed) {
+        if (changed) {
+            RenderSessionImpl.getCurrentContext().getRenderResources().clearStyles();
+        }
+    }
+
+    @Nullable
+    private static StyleResourceValue resolveStyle(int nativeResid) {
+        if (nativeResid == 0) {
+            return null;
+        }
+        BridgeContext context = RenderSessionImpl.getCurrentContext();
+        ResourceReference theme = context.resolveId(nativeResid);
+        if (theme.isFramework()) {
+            return (StyleResourceValue) context.getRenderResources()
+                    .getFrameworkResource(ResourceType.STYLE, theme.getName());
+        } else {
+            return (StyleResourceValue) context.getRenderResources()
+                    .getProjectResource(ResourceType.STYLE, theme.getName());
+        }
     }
 }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index b9294ab..9ee2f60 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -16,6 +16,7 @@
 
 package com.android.layoutlib.bridge.android;
 
+import com.android.annotations.Nullable;
 import com.android.ide.common.rendering.api.ILayoutPullParser;
 import com.android.ide.common.rendering.api.IProjectCallback;
 import com.android.ide.common.rendering.api.LayoutLog;
@@ -109,7 +110,7 @@
     // maps for dynamically generated id representing style objects (StyleResourceValue)
     private Map<Integer, StyleResourceValue> mDynamicIdToStyleMap;
     private Map<StyleResourceValue, Integer> mStyleToDynamicIdMap;
-    private int mDynamicIdGenerator = 0x01030000; // Base id for framework R.style
+    private int mDynamicIdGenerator = 0x02030000; // Base id for R.style in custom namespace
 
     // cache for TypedArray generated from IStyleResourceValue object
     private Map<int[], Map<Integer, TypedArray>> mTypedArrayCache;
@@ -315,6 +316,11 @@
             }
         }
 
+        // The base value for R.style is 0x01030000 and the custom style is 0x02030000.
+        // So, if the second byte is 03, it's probably a style.
+        if ((id >> 16 & 0xFF) == 0x03) {
+            return getStyleByDynamicId(id);
+        }
         return null;
     }
 
@@ -455,7 +461,10 @@
 
     @Override
     public final TypedArray obtainStyledAttributes(int[] attrs) {
-        return createStyleBasedTypedArray(mRenderResources.getCurrentTheme(), attrs);
+        // No style is specified here, so create the typed array based on the default theme
+        // and the styles already applied to it. A null value of style indicates that the default
+        // theme should be used.
+        return createStyleBasedTypedArray(null, attrs);
     }
 
     @Override
@@ -723,11 +732,13 @@
 
     /**
      * Creates a {@link BridgeTypedArray} by filling the values defined by the int[] with the
-     * values found in the given style.
+     * values found in the given style. If no style is specified, the default theme, along with the
+     * styles applied to it are used.
+     *
      * @see #obtainStyledAttributes(int, int[])
      */
-    private BridgeTypedArray createStyleBasedTypedArray(StyleResourceValue style, int[] attrs)
-            throws Resources.NotFoundException {
+    private BridgeTypedArray createStyleBasedTypedArray(@Nullable StyleResourceValue style,
+            int[] attrs) throws Resources.NotFoundException {
 
         List<Pair<String, Boolean>> attributes = searchAttrs(attrs);
 
@@ -740,8 +751,14 @@
 
             if (attribute != null) {
                 // look for the value in the given style
-                ResourceValue resValue = mRenderResources.findItemInStyle(style,
-                        attribute.getFirst(), attribute.getSecond());
+                ResourceValue resValue;
+                if (style != null) {
+                    resValue = mRenderResources.findItemInStyle(style, attribute.getFirst(),
+                            attribute.getSecond());
+                } else {
+                    resValue = mRenderResources.findItemInTheme(attribute.getFirst(),
+                            attribute.getSecond());
+                }
 
                 if (resValue != null) {
                     // resolve it to make sure there are no references left.
@@ -756,7 +773,6 @@
         return ta;
     }
 
-
     /**
      * The input int[] attrs is a list of attributes. The returns a list of information about
      * each attributes. The information is (name, isFramework)
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 4236038..e0c05de 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -126,6 +126,9 @@
         "android.content.res.Resources$Theme#obtainStyledAttributes",
         "android.content.res.Resources$Theme#resolveAttribute",
         "android.content.res.Resources#localeToLanguageTag",
+        "android.content.res.AssetManager#newTheme",
+        "android.content.res.AssetManager#deleteTheme",
+        "android.content.res.AssetManager#applyThemeStyle",
         "android.content.res.TypedArray#getValueAt",
         "android.graphics.BitmapFactory#finishDecode",
         "android.os.Handler#sendMessageAtTime",