Merge "Update wifi display device name when renamed." into jb-mr1-dev
diff --git a/core/java/android/server/search/SearchManagerService.java b/core/java/android/server/search/SearchManagerService.java
index de4dd88..affeb90 100644
--- a/core/java/android/server/search/SearchManagerService.java
+++ b/core/java/android/server/search/SearchManagerService.java
@@ -283,6 +283,8 @@
 
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+
         IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
         synchronized (mSearchables) {
             for (int i = 0; i < mSearchables.size(); i++) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 946965b..158e0c0 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -10515,9 +10515,6 @@
      * <p>Causes the Runnable to be added to the message queue.
      * The runnable will be run on the user interface thread.</p>
      *
-     * <p>This method can be invoked from outside of the UI thread
-     * only when this View is attached to a window.</p>
-     *
      * @param action The Runnable that will be executed.
      *
      * @return Returns true if the Runnable was successfully placed in to the
@@ -10542,9 +10539,6 @@
      * after the specified amount of time elapses.
      * The runnable will be run on the user interface thread.</p>
      *
-     * <p>This method can be invoked from outside of the UI thread
-     * only when this View is attached to a window.</p>
-     *
      * @param action The Runnable that will be executed.
      * @param delayMillis The delay (in milliseconds) until the Runnable
      *        will be executed.
@@ -10573,9 +10567,6 @@
      * <p>Causes the Runnable to execute on the next animation time step.
      * The runnable will be run on the user interface thread.</p>
      *
-     * <p>This method can be invoked from outside of the UI thread
-     * only when this View is attached to a window.</p>
-     *
      * @param action The Runnable that will be executed.
      *
      * @see #postOnAnimationDelayed
@@ -10597,9 +10588,6 @@
      * after the specified amount of time elapses.
      * The runnable will be run on the user interface thread.</p>
      *
-     * <p>This method can be invoked from outside of the UI thread
-     * only when this View is attached to a window.</p>
-     *
      * @param action The Runnable that will be executed.
      * @param delayMillis The delay (in milliseconds) until the Runnable
      *        will be executed.
@@ -10621,9 +10609,6 @@
     /**
      * <p>Removes the specified Runnable from the message queue.</p>
      *
-     * <p>This method can be invoked from outside of the UI thread
-     * only when this View is attached to a window.</p>
-     *
      * @param action The Runnable to remove from the message handling queue
      *
      * @return true if this view could ask the Handler to remove the Runnable,
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index cc536f2..2b50091 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -2427,17 +2427,39 @@
 }
 
 status_t OpenGLRenderer::drawArc(float left, float top, float right, float bottom,
-        float startAngle, float sweepAngle, bool useCenter, SkPaint* paint) {
-    if (mSnapshot->isIgnored()) return DrawGlInfo::kStatusDone;
-
-    if (fabs(sweepAngle) >= 360.0f) {
-        return drawOval(left, top, right, bottom, paint);
+        float startAngle, float sweepAngle, bool useCenter, SkPaint* p) {
+    if (mSnapshot->isIgnored() || quickRejectPreStroke(left, top, right, bottom, p)) {
+        return DrawGlInfo::kStatusDone;
     }
 
-    mCaches.activeTexture(0);
-    const PathTexture* texture = mCaches.arcShapeCache.getArc(right - left, bottom - top,
-            startAngle, sweepAngle, useCenter, paint);
-    return drawShape(left, top, texture, paint);
+    if (fabs(sweepAngle) >= 360.0f) {
+        return drawOval(left, top, right, bottom, p);
+    }
+
+    // TODO: support fills (accounting for concavity if useCenter && sweepAngle > 180)
+    if (p->getStyle() != SkPaint::kStroke_Style || p->getPathEffect() != 0 || p->getStrokeCap() != SkPaint::kButt_Cap) {
+        mCaches.activeTexture(0);
+        const PathTexture* texture = mCaches.arcShapeCache.getArc(right - left, bottom - top,
+                startAngle, sweepAngle, useCenter, p);
+        return drawShape(left, top, texture, p);
+    }
+
+    SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
+    if (p->getStyle() == SkPaint::kStrokeAndFill_Style) {
+        rect.outset(p->getStrokeWidth() / 2, p->getStrokeWidth() / 2);
+    }
+
+    SkPath path;
+    if (useCenter) {
+        path.moveTo(rect.centerX(), rect.centerY());
+    }
+    path.arcTo(rect, startAngle, sweepAngle, !useCenter);
+    if (useCenter) {
+        path.close();
+    }
+    drawConvexPath(path, p);
+
+    return DrawGlInfo::kStatusDrew;
 }
 
 // See SkPaintDefaults.h
diff --git a/libs/hwui/PathRenderer.cpp b/libs/hwui/PathRenderer.cpp
index 58d6cb8..dd13d79 100644
--- a/libs/hwui/PathRenderer.cpp
+++ b/libs/hwui/PathRenderer.cpp
@@ -80,11 +80,24 @@
  *
  * Note that we can't add and normalize the two vectors, that would result in a rectangle having an
  * offset of (sqrt(2)/2, sqrt(2)/2) at each corner, instead of (1, 1)
+ *
+ * NOTE: assumes angles between normals 90 degrees or less
  */
 inline vec2 totalOffsetFromNormals(const vec2& normalA, const vec2& normalB) {
     return (normalA + normalB) / (1 + fabs(normalA.dot(normalB)));
 }
 
+inline void scaleOffsetForStrokeWidth(vec2& offset, float halfStrokeWidth,
+        float inverseScaleX, float inverseScaleY) {
+    if (halfStrokeWidth == 0.0f) {
+        // hairline - compensate for scale
+        offset.x *= 0.5f * inverseScaleX;
+        offset.y *= 0.5f * inverseScaleY;
+    } else {
+        offset *= halfStrokeWidth;
+    }
+}
+
 void getFillVerticesFromPerimeter(const Vector<Vertex>& perimeter, VertexBuffer& vertexBuffer) {
     Vertex* buffer = vertexBuffer.alloc<Vertex>(perimeter.size());
 
@@ -119,13 +132,7 @@
         nextNormal.normalize();
 
         vec2 totalOffset = totalOffsetFromNormals(lastNormal, nextNormal);
-        if (halfStrokeWidth == 0.0f) {
-            // hairline - compensate for scale
-            totalOffset.x *= 0.5f * inverseScaleX;
-            totalOffset.y *= 0.5f * inverseScaleY;
-        } else {
-            totalOffset *= halfStrokeWidth;
-        }
+        scaleOffsetForStrokeWidth(totalOffset, halfStrokeWidth, inverseScaleX, inverseScaleY);
 
         Vertex::set(&buffer[currentIndex++],
                 current->position[0] + totalOffset.x,
@@ -145,6 +152,55 @@
     copyVertex(&buffer[currentIndex++], &buffer[1]);
 }
 
+void getStrokeVerticesFromUnclosedVertices(const Vector<Vertex>& vertices, float halfStrokeWidth,
+        VertexBuffer& vertexBuffer, float inverseScaleX, float inverseScaleY) {
+    Vertex* buffer = vertexBuffer.alloc<Vertex>(vertices.size() * 2);
+
+    int currentIndex = 0;
+    const Vertex* current = &(vertices[0]);
+    vec2 lastNormal;
+    for (unsigned int i = 0; i < vertices.size() - 1; i++) {
+        const Vertex* next = &(vertices[i + 1]);
+        vec2 nextNormal(next->position[1] - current->position[1],
+                current->position[0] - next->position[0]);
+        nextNormal.normalize();
+
+        vec2 totalOffset;
+        if (i == 0) {
+            totalOffset = nextNormal;
+        } else {
+            totalOffset = totalOffsetFromNormals(lastNormal, nextNormal);
+        }
+        scaleOffsetForStrokeWidth(totalOffset, halfStrokeWidth, inverseScaleX, inverseScaleY);
+
+        Vertex::set(&buffer[currentIndex++],
+                current->position[0] + totalOffset.x,
+                current->position[1] + totalOffset.y);
+
+        Vertex::set(&buffer[currentIndex++],
+                current->position[0] - totalOffset.x,
+                current->position[1] - totalOffset.y);
+
+        current = next;
+        lastNormal = nextNormal;
+    }
+
+    vec2 totalOffset = lastNormal;
+    scaleOffsetForStrokeWidth(totalOffset, halfStrokeWidth, inverseScaleX, inverseScaleY);
+
+    Vertex::set(&buffer[currentIndex++],
+            current->position[0] + totalOffset.x,
+            current->position[1] + totalOffset.y);
+    Vertex::set(&buffer[currentIndex++],
+            current->position[0] - totalOffset.x,
+            current->position[1] - totalOffset.y);
+#if VERTEX_DEBUG
+    for (unsigned int i = 0; i < vertexBuffer.getSize(); i++) {
+        ALOGD("point at %f %f", buffer[i].position[0], buffer[i].position[1]);
+    }
+#endif
+}
+
 void getFillVerticesFromPerimeterAA(const Vector<Vertex>& perimeter, VertexBuffer& vertexBuffer,
          float inverseScaleX, float inverseScaleY) {
     AlphaVertex* buffer = vertexBuffer.alloc<AlphaVertex>(perimeter.size() * 3 + 2);
@@ -202,11 +258,167 @@
 
 #if VERTEX_DEBUG
     for (unsigned int i = 0; i < vertexBuffer.getSize(); i++) {
-        ALOGD("point at %f %f", buffer[i].position[0], buffer[i].position[1]);
+        ALOGD("point at %f %f, alpha %f", buffer[i].position[0], buffer[i].position[1], buffer[i].alpha);
     }
 #endif
 }
 
+
+void getStrokeVerticesFromUnclosedVerticesAA(const Vector<Vertex>& vertices, float halfStrokeWidth,
+        VertexBuffer& vertexBuffer, float inverseScaleX, float inverseScaleY) {
+    AlphaVertex* buffer = vertexBuffer.alloc<AlphaVertex>(6 * vertices.size() + 2);
+
+    // avoid lines smaller than hairline since they break triangle based sampling. instead reducing
+    // alpha value (TODO: support different X/Y scale)
+    float maxAlpha = 1.0f;
+    if (halfStrokeWidth != 0 && inverseScaleX == inverseScaleY &&
+            halfStrokeWidth * inverseScaleX < 0.5f) {
+        maxAlpha *= (2 * halfStrokeWidth) / inverseScaleX;
+        halfStrokeWidth = 0.0f;
+    }
+
+    // there is no outer/inner here, using them for consistency with below approach
+    int offset = 2 * (vertices.size() - 2);
+    int currentAAOuterIndex = 2;
+    int currentAAInnerIndex = 2 * offset + 5; // reversed
+    int currentStrokeIndex = currentAAInnerIndex + 7;
+
+    const Vertex* last = &(vertices[0]);
+    const Vertex* current = &(vertices[1]);
+    vec2 lastNormal(current->position[1] - last->position[1],
+            last->position[0] - current->position[0]);
+    lastNormal.normalize();
+
+    {
+        // start cap
+        vec2 totalOffset = lastNormal;
+        vec2 AAOffset = totalOffset;
+        AAOffset.x *= 0.5f * inverseScaleX;
+        AAOffset.y *= 0.5f * inverseScaleY;
+
+        vec2 innerOffset = totalOffset;
+        scaleOffsetForStrokeWidth(innerOffset, halfStrokeWidth, inverseScaleX, inverseScaleY);
+        vec2 outerOffset = innerOffset + AAOffset;
+        innerOffset -= AAOffset;
+
+        // TODO: support square cap by changing this offset to incorporate halfStrokeWidth
+        vec2 capAAOffset(AAOffset.y, -AAOffset.x);
+        AlphaVertex::set(&buffer[0],
+                last->position[0] + outerOffset.x + capAAOffset.x,
+                last->position[1] + outerOffset.y + capAAOffset.y,
+                0.0f);
+        AlphaVertex::set(&buffer[1],
+                last->position[0] + innerOffset.x - capAAOffset.x,
+                last->position[1] + innerOffset.y - capAAOffset.y,
+                maxAlpha);
+
+        AlphaVertex::set(&buffer[2 * offset + 6],
+                last->position[0] - outerOffset.x + capAAOffset.x,
+                last->position[1] - outerOffset.y + capAAOffset.y,
+                0.0f);
+        AlphaVertex::set(&buffer[2 * offset + 7],
+                last->position[0] - innerOffset.x - capAAOffset.x,
+                last->position[1] - innerOffset.y - capAAOffset.y,
+                maxAlpha);
+        copyAlphaVertex(&buffer[2 * offset + 8], &buffer[0]);
+        copyAlphaVertex(&buffer[2 * offset + 9], &buffer[1]);
+        copyAlphaVertex(&buffer[2 * offset + 10], &buffer[1]); // degenerate tris (the only two!)
+        copyAlphaVertex(&buffer[2 * offset + 11], &buffer[2 * offset + 7]);
+    }
+
+    for (unsigned int i = 1; i < vertices.size() - 1; i++) {
+        const Vertex* next = &(vertices[i + 1]);
+        vec2 nextNormal(next->position[1] - current->position[1],
+                current->position[0] - next->position[0]);
+        nextNormal.normalize();
+
+        vec2 totalOffset = totalOffsetFromNormals(lastNormal, nextNormal);
+        vec2 AAOffset = totalOffset;
+        AAOffset.x *= 0.5f * inverseScaleX;
+        AAOffset.y *= 0.5f * inverseScaleY;
+
+        vec2 innerOffset = totalOffset;
+        scaleOffsetForStrokeWidth(innerOffset, halfStrokeWidth, inverseScaleX, inverseScaleY);
+        vec2 outerOffset = innerOffset + AAOffset;
+        innerOffset -= AAOffset;
+
+        AlphaVertex::set(&buffer[currentAAOuterIndex++],
+                current->position[0] + outerOffset.x,
+                current->position[1] + outerOffset.y,
+                0.0f);
+        AlphaVertex::set(&buffer[currentAAOuterIndex++],
+                current->position[0] + innerOffset.x,
+                current->position[1] + innerOffset.y,
+                maxAlpha);
+
+        AlphaVertex::set(&buffer[currentStrokeIndex++],
+                current->position[0] + innerOffset.x,
+                current->position[1] + innerOffset.y,
+                maxAlpha);
+        AlphaVertex::set(&buffer[currentStrokeIndex++],
+                current->position[0] - innerOffset.x,
+                current->position[1] - innerOffset.y,
+                maxAlpha);
+
+        AlphaVertex::set(&buffer[currentAAInnerIndex--],
+                current->position[0] - innerOffset.x,
+                current->position[1] - innerOffset.y,
+                maxAlpha);
+        AlphaVertex::set(&buffer[currentAAInnerIndex--],
+                current->position[0] - outerOffset.x,
+                current->position[1] - outerOffset.y,
+                0.0f);
+
+        last = current;
+        current = next;
+        lastNormal = nextNormal;
+    }
+
+    {
+        // end cap
+        vec2 totalOffset = lastNormal;
+        vec2 AAOffset = totalOffset;
+        AAOffset.x *= 0.5f * inverseScaleX;
+        AAOffset.y *= 0.5f * inverseScaleY;
+
+        vec2 innerOffset = totalOffset;
+        scaleOffsetForStrokeWidth(innerOffset, halfStrokeWidth, inverseScaleX, inverseScaleY);
+        vec2 outerOffset = innerOffset + AAOffset;
+        innerOffset -= AAOffset;
+
+        // TODO: support square cap by changing this offset to incorporate halfStrokeWidth
+        vec2 capAAOffset(-AAOffset.y, AAOffset.x);
+
+        AlphaVertex::set(&buffer[offset + 2],
+                current->position[0] + outerOffset.x + capAAOffset.x,
+                current->position[1] + outerOffset.y + capAAOffset.y,
+                0.0f);
+        AlphaVertex::set(&buffer[offset + 3],
+                current->position[0] + innerOffset.x - capAAOffset.x,
+                current->position[1] + innerOffset.y - capAAOffset.y,
+                maxAlpha);
+
+        AlphaVertex::set(&buffer[offset + 4],
+                current->position[0] - outerOffset.x + capAAOffset.x,
+                current->position[1] - outerOffset.y + capAAOffset.y,
+                0.0f);
+        AlphaVertex::set(&buffer[offset + 5],
+                current->position[0] - innerOffset.x - capAAOffset.x,
+                current->position[1] - innerOffset.y - capAAOffset.y,
+                maxAlpha);
+
+        copyAlphaVertex(&buffer[vertexBuffer.getSize() - 2], &buffer[offset + 3]);
+        copyAlphaVertex(&buffer[vertexBuffer.getSize() - 1], &buffer[offset + 5]);
+    }
+
+#if VERTEX_DEBUG
+    for (unsigned int i = 0; i < vertexBuffer.getSize(); i++) {
+        ALOGD("point at %f %f, alpha %f", buffer[i].position[0], buffer[i].position[1], buffer[i].alpha);
+    }
+#endif
+}
+
+
 void getStrokeVerticesFromPerimeterAA(const Vector<Vertex>& perimeter, float halfStrokeWidth,
         VertexBuffer& vertexBuffer, float inverseScaleX, float inverseScaleY) {
     AlphaVertex* buffer = vertexBuffer.alloc<AlphaVertex>(6 * perimeter.size() + 8);
@@ -242,13 +454,7 @@
         AAOffset.y *= 0.5f * inverseScaleY;
 
         vec2 innerOffset = totalOffset;
-        if (halfStrokeWidth == 0.0f) {
-            // hairline! - compensate for scale
-            innerOffset.x *= 0.5f * inverseScaleX;
-            innerOffset.y *= 0.5f * inverseScaleY;
-        } else {
-            innerOffset *= halfStrokeWidth;
-        }
+        scaleOffsetForStrokeWidth(innerOffset, halfStrokeWidth, inverseScaleX, inverseScaleY);
         vec2 outerOffset = innerOffset + AAOffset;
         innerOffset -= AAOffset;
 
@@ -296,6 +502,12 @@
     copyAlphaVertex(&buffer[currentAAInnerIndex++], &buffer[2 * offset]);
     copyAlphaVertex(&buffer[currentAAInnerIndex++], &buffer[2 * offset + 1]);
     // don't need to create last degenerate tri
+
+#if VERTEX_DEBUG
+    for (unsigned int i = 0; i < vertexBuffer.getSize(); i++) {
+        ALOGD("point at %f %f, alpha %f", buffer[i].position[0], buffer[i].position[1], buffer[i].alpha);
+    }
+#endif
 }
 
 void PathRenderer::convexPathVertices(const SkPath &path, const SkPaint* paint,
@@ -320,7 +532,10 @@
             threshInvScaleY *= bounds.height() / (bounds.height() + paint->getStrokeWidth());
         }
     }
-    convexPathPerimeterVertices(path, threshInvScaleX * threshInvScaleX,
+
+    // force close if we're filling the path, since fill path expects closed perimeter.
+    bool forceClose = style != SkPaint::kStroke_Style;
+    bool wasClosed = convexPathPerimeterVertices(path, forceClose, threshInvScaleX * threshInvScaleX,
             threshInvScaleY * threshInvScaleY, tempVertices);
 
     if (!tempVertices.size()) {
@@ -337,11 +552,22 @@
     if (style == SkPaint::kStroke_Style) {
         float halfStrokeWidth = paint->getStrokeWidth() * 0.5f;
         if (!isAA) {
-            getStrokeVerticesFromPerimeter(tempVertices, halfStrokeWidth, vertexBuffer,
-                    inverseScaleX, inverseScaleY);
+            if (wasClosed) {
+                getStrokeVerticesFromPerimeter(tempVertices, halfStrokeWidth, vertexBuffer,
+                        inverseScaleX, inverseScaleY);
+            } else {
+                getStrokeVerticesFromUnclosedVertices(tempVertices, halfStrokeWidth, vertexBuffer,
+                        inverseScaleX, inverseScaleY);
+            }
+
         } else {
-            getStrokeVerticesFromPerimeterAA(tempVertices, halfStrokeWidth, vertexBuffer,
-                    inverseScaleX, inverseScaleY);
+            if (wasClosed) {
+                getStrokeVerticesFromPerimeterAA(tempVertices, halfStrokeWidth, vertexBuffer,
+                        inverseScaleX, inverseScaleY);
+            } else {
+                getStrokeVerticesFromUnclosedVerticesAA(tempVertices, halfStrokeWidth, vertexBuffer,
+                        inverseScaleX, inverseScaleY);
+            }
         }
     } else {
         // For kStrokeAndFill style, the path should be adjusted externally, as it will be treated as a fill here.
@@ -354,19 +580,27 @@
 }
 
 
-void PathRenderer::convexPathPerimeterVertices(const SkPath& path,
+void pushToVector(Vector<Vertex>& vertices, float x, float y) {
+    // TODO: make this not yuck
+    vertices.push();
+    Vertex* newVertex = &(vertices.editArray()[vertices.size() - 1]);
+    Vertex::set(newVertex, x, y);
+}
+
+bool PathRenderer::convexPathPerimeterVertices(const SkPath& path, bool forceClose,
         float sqrInvScaleX, float sqrInvScaleY, Vector<Vertex>& outputVertices) {
     ATRACE_CALL();
 
-    SkPath::Iter iter(path, true);
-    SkPoint pos;
+    // TODO: to support joins other than sharp miter, join vertices should be labelled in the
+    // perimeter, or resolved into more vertices. Reconsider forceClose-ing in that case.
+    SkPath::Iter iter(path, forceClose);
     SkPoint pts[4];
     SkPath::Verb v;
     Vertex* newVertex = 0;
     while (SkPath::kDone_Verb != (v = iter.next(pts))) {
             switch (v) {
                 case SkPath::kMove_Verb:
-                    pos = pts[0];
+                    pushToVector(outputVertices, pts[0].x(), pts[0].y());
                     ALOGV("Move to pos %f %f", pts[0].x(), pts[0].y());
                     break;
                 case SkPath::kClose_Verb:
@@ -377,10 +611,7 @@
                             pts[0].x(), pts[0].y(),
                             pts[1].x(), pts[1].y());
 
-                    // TODO: make this not yuck
-                    outputVertices.push();
-                    newVertex = &(outputVertices.editArray()[outputVertices.size() - 1]);
-                    Vertex::set(newVertex, pts[1].x(), pts[1].y());
+                    pushToVector(outputVertices, pts[1].x(), pts[1].y());
                     break;
                 case SkPath::kQuad_Verb:
                     ALOGV("kQuad_Verb");
@@ -403,6 +634,14 @@
                     break;
             }
     }
+
+    int size = outputVertices.size();
+    if (size >= 2 && outputVertices[0].position[0] == outputVertices[size - 1].position[0] &&
+            outputVertices[0].position[1] == outputVertices[size - 1].position[1]) {
+        outputVertices.pop();
+        return true;
+    }
+    return false;
 }
 
 void PathRenderer::recursiveCubicBezierVertices(
@@ -419,10 +658,7 @@
 
     if (d * d < THRESHOLD * THRESHOLD * (dx * dx * sqrInvScaleY + dy * dy * sqrInvScaleX)) {
         // below thresh, draw line by adding endpoint
-        // TODO: make this not yuck
-        outputVertices.push();
-        Vertex* newVertex = &(outputVertices.editArray()[outputVertices.size() - 1]);
-        Vertex::set(newVertex, p2x, p2y);
+        pushToVector(outputVertices, p2x, p2y);
     } else {
         float p1c1x = (p1x + c1x) * 0.5f;
         float p1c1y = (p1y + c1y) * 0.5f;
@@ -463,10 +699,7 @@
 
     if (d * d < THRESHOLD * THRESHOLD * (dx * dx * sqrInvScaleY + dy * dy * sqrInvScaleX)) {
         // below thresh, draw line by adding endpoint
-        // TODO: make this not yuck
-        outputVertices.push();
-        Vertex* newVertex = &(outputVertices.editArray()[outputVertices.size() - 1]);
-        Vertex::set(newVertex, bx, by);
+        pushToVector(outputVertices, bx, by);
     } else {
         float acx = (ax + cx) * 0.5f;
         float bcx = (bx + cx) * 0.5f;
diff --git a/libs/hwui/PathRenderer.h b/libs/hwui/PathRenderer.h
index 28a5b90..e9f347b 100644
--- a/libs/hwui/PathRenderer.h
+++ b/libs/hwui/PathRenderer.h
@@ -71,10 +71,8 @@
             const mat4 *transform, VertexBuffer& vertexBuffer);
 
 private:
-    static void convexPathPerimeterVertices(
-        const SkPath &path,
-        float sqrInvScaleX, float sqrInvScaleY,
-        Vector<Vertex> &outputVertices);
+    static bool convexPathPerimeterVertices(const SkPath &path, bool forceClose,
+        float sqrInvScaleX, float sqrInvScaleY, Vector<Vertex> &outputVertices);
 
 /*
   endpoints a & b,
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index f26d322..f77cbfb 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -153,11 +153,10 @@
     private static final int MSG_SET_A2DP_CONNECTION_STATE = 22;
     // end of messages handled under wakelock
     private static final int MSG_SET_RSX_CONNECTION_STATE = 23; // change remote submix connection
-    private static final int MSG_SET_FORCE_RSX_USE = 24;        // force remote submix audio routing
-    private static final int MSG_CHECK_MUSIC_ACTIVE = 25;
-    private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 26;
-    private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME = 27;
-    private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED = 28;
+    private static final int MSG_CHECK_MUSIC_ACTIVE = 24;
+    private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 25;
+    private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME = 26;
+    private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED = 27;
 
     // flags for MSG_PERSIST_VOLUME indicating if current and/or last audible volume should be
     // persisted
@@ -2221,13 +2220,6 @@
                 on ? 1 : 0 /*arg1*/,
                 address /*arg2*/,
                 null/*obj*/, 0/*delay*/);
-
-        // Note that we are  currently forcing use of remote submix as soon as corresponding device
-        //   is made available
-        sendMsg(mAudioHandler, MSG_SET_FORCE_RSX_USE, SENDMSG_REPLACE,
-                AudioSystem.FOR_MEDIA,
-                on ? AudioSystem.FORCE_REMOTE_SUBMIX : AudioSystem.FORCE_NONE,
-                null/*obj*/, 0/*delay*/);
     }
 
     private void onSetRsxConnectionState(int available, int address) {
@@ -3320,7 +3312,6 @@
 
                 case MSG_SET_FORCE_USE:
                 case MSG_SET_FORCE_BT_A2DP_USE:
-                case MSG_SET_FORCE_RSX_USE:
                     setForceUse(msg.arg1, msg.arg2);
                     break;
 
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 260ddc7..dde2979 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -360,9 +360,8 @@
     public static final int FORCE_ANALOG_DOCK = 8;
     public static final int FORCE_DIGITAL_DOCK = 9;
     public static final int FORCE_NO_BT_A2DP = 10;
-    public static final int FORCE_REMOTE_SUBMIX = 11;
-    public static final int FORCE_SYSTEM_ENFORCED = 12;
-    private static final int NUM_FORCE_CONFIG = 13;
+    public static final int FORCE_SYSTEM_ENFORCED = 11;
+    private static final int NUM_FORCE_CONFIG = 12;
     public static final int FORCE_DEFAULT = FORCE_NONE;
 
     // usage for setForceUse, must match AudioSystem::force_use
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPasswordView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPasswordView.java
index 3b37d56..1868507 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPasswordView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPasswordView.java
@@ -86,6 +86,13 @@
         mLockPatternUtils = utils;
     }
 
+    @Override
+    public void onWindowFocusChanged(boolean hasWindowFocus) {
+        if (hasWindowFocus) {
+            reset();
+        }
+    }
+
     public void reset() {
         // start fresh
         mPasswordEntry.setText("");
@@ -191,7 +198,9 @@
             }
 
             public void afterTextChanged(Editable s) {
-                mCallback.userActivity(0);
+                if (mCallback != null) {
+                    mCallback.userActivity(0);
+                }
             }
         });
 
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusViewManager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusViewManager.java
index 9615e71..5b85064 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusViewManager.java
@@ -221,6 +221,7 @@
             mHandler.removeCallbacks(mClearSecurityMessageRunnable);
             mHandler.postDelayed(mClearSecurityMessageRunnable, SECURITY_MESSAGE_DURATION);
         }
+        mSecurityMessage.announceForAccessibility(mSecurityMessage.getText());
     }
 
     /**
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
index c18fe0e..e7e4f87 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -304,6 +304,8 @@
 
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+
         // Dump the state of all the app widget providers
         synchronized (mAppWidgetServices) {
             IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index c5016e6..6948927 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -609,10 +609,9 @@
     }
 
     /**
-     * Throw SecurityException if caller has neither COARSE or FINE.
-     * Otherwise, return the best permission.
+     * Returns the best permission available to the caller.
      */
-    private String checkPermission() {
+    private String getBestCallingPermission() {
         if (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION) ==
                 PackageManager.PERMISSION_GRANTED) {
             return ACCESS_FINE_LOCATION;
@@ -620,9 +619,20 @@
                 PackageManager.PERMISSION_GRANTED) {
             return ACCESS_COARSE_LOCATION;
         }
+        return null;
+    }
 
-        throw new SecurityException("Location requires either ACCESS_COARSE_LOCATION or" +
-                " ACCESS_FINE_LOCATION permission");
+    /**
+     * Throw SecurityException if caller has neither COARSE or FINE.
+     * Otherwise, return the best permission.
+     */
+    private String checkPermission() {
+        String perm = getBestCallingPermission();
+        if (perm == null) {
+            throw new SecurityException("Location requires either ACCESS_COARSE_LOCATION or" +
+                    " ACCESS_FINE_LOCATION permission");
+        }
+        return perm;
     }
 
     /**
@@ -635,19 +645,15 @@
         }
     }
 
-    private boolean isAllowedProviderSafe(String provider) {
+    private String getMinimumPermissionForProvider(String provider) {
         if (LocationManager.GPS_PROVIDER.equals(provider) ||
                 LocationManager.PASSIVE_PROVIDER.equals(provider)) {
             // gps and passive providers require FINE permission
-            return mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
-                    == PackageManager.PERMISSION_GRANTED;
+            return ACCESS_FINE_LOCATION;
         } else if (LocationManager.NETWORK_PROVIDER.equals(provider) ||
                 LocationManager.FUSED_PROVIDER.equals(provider)) {
             // network and fused providers are ok with COARSE or FINE
-            return (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
-                    == PackageManager.PERMISSION_GRANTED) ||
-                    (mContext.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION)
-                    == PackageManager.PERMISSION_GRANTED);
+            return ACCESS_COARSE_LOCATION;
         } else {
             // mock providers
             LocationProviderInterface lp = mMockProviders.get(provider);
@@ -656,20 +662,43 @@
                 if (properties != null) {
                     if (properties.mRequiresSatellite) {
                         // provider requiring satellites require FINE permission
-                        return mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
-                                == PackageManager.PERMISSION_GRANTED;
+                        return ACCESS_FINE_LOCATION;
                     } else if (properties.mRequiresNetwork || properties.mRequiresCell) {
                         // provider requiring network and or cell require COARSE or FINE
-                        return (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
-                                == PackageManager.PERMISSION_GRANTED) ||
-                                (mContext.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION)
-                                 == PackageManager.PERMISSION_GRANTED);
+                        return ACCESS_COARSE_LOCATION;
                     }
                 }
             }
         }
 
-        return false;
+        return null;
+    }
+
+    private boolean isPermissionSufficient(String perm, String minPerm) {
+        if (ACCESS_FINE_LOCATION.equals(minPerm)) {
+            return ACCESS_FINE_LOCATION.equals(perm);
+        } else if (ACCESS_COARSE_LOCATION.equals(minPerm)) {
+            return ACCESS_FINE_LOCATION.equals(perm) ||
+                    ACCESS_COARSE_LOCATION.equals(perm);
+        } else {
+            return false;
+        }
+    }
+
+    private void checkPermissionForProvider(String perm, String provider) {
+        String minPerm = getMinimumPermissionForProvider(provider);
+        if (!isPermissionSufficient(perm, minPerm)) {
+            if (ACCESS_FINE_LOCATION.equals(minPerm)) {
+                throw new SecurityException("Location provider \"" + provider +
+                        "\" requires ACCESS_FINE_LOCATION permission.");
+            } else if (ACCESS_COARSE_LOCATION.equals(minPerm)) {
+                throw new SecurityException("Location provider \"" + provider +
+                        "\" requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission.");                
+            } else {
+                throw new SecurityException("Insufficient permission for location provider \"" +
+                        provider + "\".");
+            }
+        }
     }
 
     /**
@@ -703,6 +732,7 @@
     @Override
     public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
         ArrayList<String> out;
+        String perm = getBestCallingPermission();
         int callingUserId = UserHandle.getCallingUserId();
         long identity = Binder.clearCallingIdentity();
         try {
@@ -713,7 +743,7 @@
                     if (LocationManager.FUSED_PROVIDER.equals(name)) {
                         continue;
                     }
-                    if (isAllowedProviderSafe(name)) {
+                    if (isPermissionSufficient(perm, getMinimumPermissionForProvider(name))) {
                         if (enabledOnly && !isAllowedBySettingsLocked(name, callingUserId)) {
                             continue;
                         }
@@ -980,26 +1010,12 @@
         return receiver;
     }
 
-    private boolean isProviderAllowedByCoarsePermission(String provider) {
-        if (LocationManager.FUSED_PROVIDER.equals(provider)) {
-            return true;
-        }
-        if (LocationManager.PASSIVE_PROVIDER.equals(provider)) {
-            return true;
-        }
-        if (LocationManager.NETWORK_PROVIDER.equals(provider)) {
-            return true;
-        }
-        return false;
-    }
-
     private String checkPermissionAndRequest(LocationRequest request) {
-        String perm = checkPermission();
+        String perm = getBestCallingPermission();
+        String provider = request.getProvider();
+        checkPermissionForProvider(perm, provider);
 
         if (ACCESS_COARSE_LOCATION.equals(perm)) {
-            if (!isProviderAllowedByCoarsePermission(request.getProvider())) {
-                throw new SecurityException("Requires ACCESS_FINE_LOCATION permission");
-            }
             switch (request.getQuality()) {
                 case LocationRequest.ACCURACY_FINE:
                     request.setQuality(LocationRequest.ACCURACY_BLOCK);
@@ -1324,7 +1340,7 @@
      */
     @Override
     public ProviderProperties getProviderProperties(String provider) {
-        checkPermission();
+        checkPermissionForProvider(getBestCallingPermission(), provider);
 
         LocationProviderInterface p;
         synchronized (mLock) {
@@ -1337,13 +1353,8 @@
 
     @Override
     public boolean isProviderEnabled(String provider) {
-        String perms = checkPermission();
+        checkPermissionForProvider(getBestCallingPermission(), provider);
         if (LocationManager.FUSED_PROVIDER.equals(provider)) return false;
-        if (ACCESS_COARSE_LOCATION.equals(perms) &&
-                !isProviderAllowedByCoarsePermission(provider)) {
-            throw new SecurityException("The \"" + provider +
-                    "\" provider requires ACCESS_FINE_LOCATION permission");
-        }
 
         long identity = Binder.clearCallingIdentity();
         try {
diff --git a/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java b/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java
index 26cb97b..fd594f7 100644
--- a/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java
@@ -66,7 +66,7 @@
      * @return elapsed nanoseconds since boot.
      */
     @LayoutlibDelegate
-    /*package*/ static long elapsedRealtimeNano() {
+    /*package*/ static long elapsedRealtimeNanos() {
         return System.nanoTime() - sBootTimeNano;
     }
 
diff --git a/tools/layoutlib/bridge/src/android/view/Choreographer_Delegate.java b/tools/layoutlib/bridge/src/android/view/Choreographer_Delegate.java
new file mode 100644
index 0000000..f75ee50
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/view/Choreographer_Delegate.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2012 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.view;
+
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+/**
+ * Delegate used to provide new implementation of a select few methods of {@link Choreographer}
+ *
+ * Through the layoutlib_create tool, the original  methods of Choreographer have been
+ * replaced by calls to methods of the same name in this delegate class.
+ *
+ */
+public class Choreographer_Delegate {
+
+    @LayoutlibDelegate
+    public static float getRefreshRate() {
+        return 60.f;
+    }
+}
diff --git a/tools/layoutlib/bridge/src/android/view/Display_Delegate.java b/tools/layoutlib/bridge/src/android/view/Display_Delegate.java
index 6ccdcb6..53dc821 100644
--- a/tools/layoutlib/bridge/src/android/view/Display_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/view/Display_Delegate.java
@@ -16,11 +16,8 @@
 
 package android.view;
 
-import com.android.layoutlib.bridge.android.BridgeWindowManager;
-import com.android.layoutlib.bridge.impl.RenderAction;
 import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
 
-import android.os.RemoteException;
 
 /**
  * Delegate used to provide new implementation of a select few methods of {@link Display}
@@ -31,4 +28,9 @@
  */
 public class Display_Delegate {
 
+    @LayoutlibDelegate
+    static void updateDisplayInfoLocked(Display theDisplay) {
+        // do nothing
+    }
+
 }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
similarity index 95%
rename from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
rename to tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 3fcc8ef..da736b7 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.layoutlib.bridge.android;
+package android.view;
 
 import com.android.internal.view.IInputContext;
 import com.android.internal.view.IInputMethodClient;
@@ -28,7 +28,6 @@
 import android.os.RemoteException;
 import android.util.DisplayMetrics;
 import android.view.Display;
-import android.view.Display_Delegate;
 import android.view.Gravity;
 import android.view.IApplicationToken;
 import android.view.IDisplayContentChangeListener;
@@ -45,16 +44,21 @@
  * Basic implementation of {@link IWindowManager} so that {@link Display} (and
  * {@link Display_Delegate}) can return a valid instance.
  */
-public class BridgeWindowManager implements IWindowManager {
+public class IWindowManagerImpl implements IWindowManager {
 
     private final Configuration mConfig;
     private final DisplayMetrics mMetrics;
     private final int mRotation;
+    private final boolean mHasSystemNavBar;
+    private final boolean mHasNavigationBar;
 
-    public BridgeWindowManager(Configuration config, DisplayMetrics metrics, int rotation) {
+    public IWindowManagerImpl(Configuration config, DisplayMetrics metrics, int rotation,
+            boolean hasSystemNavBar, boolean hasNavigationBar) {
         mConfig = config;
         mMetrics = metrics;
         mRotation = rotation;
+        mHasSystemNavBar = hasSystemNavBar;
+        mHasNavigationBar = hasNavigationBar;
     }
 
     // custom API.
@@ -70,14 +74,18 @@
         return mRotation;
     }
 
-    // ---- unused implementation of IWindowManager ----
+    @Override
+    public boolean hasNavigationBar() {
+        return mHasNavigationBar;
+    }
 
     @Override
     public boolean hasSystemNavBar() throws RemoteException {
-        // TODO Auto-generated method stub
-        return false;
+        return mHasSystemNavBar;
     }
 
+    // ---- unused implementation of IWindowManager ----
+
     @Override
     public void addAppToken(int arg0, IApplicationToken arg1, int arg2, int arg3, boolean arg4,
                             boolean arg5)
@@ -435,11 +443,6 @@
     }
 
     @Override
-    public boolean hasNavigationBar() {
-        return false; // should this return something else?
-    }
-
-    @Override
     public void lockNow(Bundle options) {
         // TODO Auto-generated method stub
     }
diff --git a/tools/layoutlib/bridge/src/android/view/WindowManagerGlobal_Delegate.java b/tools/layoutlib/bridge/src/android/view/WindowManagerGlobal_Delegate.java
new file mode 100644
index 0000000..2606e55
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/view/WindowManagerGlobal_Delegate.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2012 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.view;
+
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+/**
+ * Delegate used to provide new implementation of a select few methods of
+ * {@link WindowManagerGlobal}
+ *
+ * Through the layoutlib_create tool, the original  methods of WindowManagerGlobal have been
+ * replaced by calls to methods of the same name in this delegate class.
+ *
+ */
+public class WindowManagerGlobal_Delegate {
+
+    private static IWindowManager sService;
+
+    @LayoutlibDelegate
+    public static IWindowManager getWindowManagerService() {
+        return sService;
+    }
+
+    // ---- internal implementation stuff ----
+
+    public static void setWindowManagerService(IWindowManager service) {
+        sService = service;
+    }
+}
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 80478ba..e2fced6 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
@@ -25,6 +25,7 @@
 import com.android.ide.common.rendering.api.StyleResourceValue;
 import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.BridgeConstants;
+import com.android.layoutlib.bridge.android.view.WindowManagerImpl;
 import com.android.layoutlib.bridge.impl.ParserFactory;
 import com.android.layoutlib.bridge.impl.Stack;
 import com.android.resources.ResourceType;
@@ -68,9 +69,9 @@
 import android.view.BridgeInflater;
 import android.view.CompatibilityInfoHolder;
 import android.view.Display;
-import android.view.Surface;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.WindowManager;
 import android.view.textservice.TextServicesManager;
 
 import java.io.File;
@@ -98,7 +99,7 @@
     private final Configuration mConfig;
     private final ApplicationInfo mApplicationInfo;
     private final IProjectCallback mProjectCallback;
-    private final BridgeWindowManager mIWindowManager;
+    private final WindowManager mWindowManager;
 
     private Resources.Theme mTheme;
 
@@ -139,10 +140,10 @@
         mRenderResources = renderResources;
         mConfig = config;
 
-        mIWindowManager = new BridgeWindowManager(mConfig, metrics, Surface.ROTATION_0);
-
         mApplicationInfo = new ApplicationInfo();
         mApplicationInfo.targetSdkVersion = targetSdkVersion;
+
+        mWindowManager = new WindowManagerImpl(mMetrics);
     }
 
     /**
@@ -198,14 +199,14 @@
         return mRenderResources;
     }
 
-    public BridgeWindowManager getIWindowManager() {
-        return mIWindowManager;
-    }
-
     public Map<String, String> getDefaultPropMap(Object key) {
         return mDefaultPropMaps.get(key);
     }
 
+    public Configuration getConfiguration() {
+        return mConfig;
+    }
+
     /**
      * Adds a parser to the stack.
      * @param parser the parser to add.
@@ -431,10 +432,8 @@
             return TextServicesManager.getInstance();
         }
 
-        // AutoCompleteTextView and MultiAutoCompleteTextView want a window
-        // service. We don't have any but it's not worth an exception.
         if (WINDOW_SERVICE.equals(service)) {
-            return null;
+            return mWindowManager;
         }
 
         // needed by SearchView
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java
new file mode 100644
index 0000000..9a633bf
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2012 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 com.android.layoutlib.bridge.android.view;
+
+import android.util.DisplayMetrics;
+import android.view.Display;
+import android.view.DisplayInfo;
+import android.view.View;
+import android.view.WindowManager;
+
+public class WindowManagerImpl implements WindowManager {
+
+    private final DisplayMetrics mMetrics;
+    private final Display mDisplay;
+
+    public WindowManagerImpl(DisplayMetrics metrics) {
+        mMetrics = metrics;
+
+        DisplayInfo info = new DisplayInfo();
+        info.logicalHeight = mMetrics.heightPixels;
+        info.logicalWidth = mMetrics.widthPixels;
+        mDisplay = new Display(null, Display.DEFAULT_DISPLAY, info, null);
+    }
+
+    @Override
+    public Display getDefaultDisplay() {
+        return mDisplay;
+    }
+
+
+    @Override
+    public void addView(View arg0, android.view.ViewGroup.LayoutParams arg1) {
+        // pass
+    }
+
+    @Override
+    public void removeView(View arg0) {
+        // pass
+    }
+
+    @Override
+    public void updateViewLayout(View arg0, android.view.ViewGroup.LayoutParams arg1) {
+        // pass
+    }
+
+
+    @Override
+    public void removeViewImmediate(View arg0) {
+        // pass
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index e93b41d..cc0f077 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -68,11 +68,15 @@
 import android.util.TypedValue;
 import android.view.AttachInfo_Accessor;
 import android.view.BridgeInflater;
+import android.view.IWindowManagerImpl;
+import android.view.IWindowManager;
+import android.view.Surface;
 import android.view.View;
 import android.view.View.MeasureSpec;
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
 import android.view.ViewGroup.MarginLayoutParams;
+import android.view.WindowManagerGlobal_Delegate;
 import android.widget.AbsListView;
 import android.widget.AbsSpinner;
 import android.widget.AdapterView;
@@ -185,6 +189,14 @@
         findActionBar(resources, metrics);
         findSystemBar(resources, metrics);
 
+        // FIXME: find those out, and possibly add them to the render params
+        boolean hasSystemNavBar = true;
+        boolean hasNavigationBar = true;
+        IWindowManager iwm = new IWindowManagerImpl(getContext().getConfiguration(),
+                metrics, Surface.ROTATION_0,
+                hasSystemNavBar, hasNavigationBar);
+        WindowManagerGlobal_Delegate.setWindowManagerService(iwm);
+
         // build the inflater and parser.
         mInflater = new BridgeInflater(context, params.getProjectCallback());
         context.setBridgeInflater(mInflater);
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 5109810..80a1a60 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
@@ -110,11 +110,13 @@
         "android.os.Handler#sendMessageAtTime",
         "android.os.HandlerThread#run",
         "android.os.Build#getString",
-        "android.view.Display#getWindowManager",
+        "android.view.Choreographer#getRefreshRate",
+        "android.view.Display#updateDisplayInfoLocked",
         "android.view.LayoutInflater#rInflate",
         "android.view.LayoutInflater#parseInclude",
         "android.view.View#isInEditMode",
         "android.view.ViewRootImpl#isInTouchMode",
+        "android.view.WindowManagerGlobal#getWindowManagerService",
         "android.view.inputmethod.InputMethodManager#getInstance",
         "com.android.internal.util.XmlUtils#convertValueToInt",
         "com.android.internal.textservice.ITextServicesManager$Stub#asInterface",