Merge "Add test to ensure themes get copied from separate resource tables" into lmp-dev
diff --git a/libs/hwui/AmbientShadow.cpp b/libs/hwui/AmbientShadow.cpp
index 9cc83ed..7834ef8 100644
--- a/libs/hwui/AmbientShadow.cpp
+++ b/libs/hwui/AmbientShadow.cpp
@@ -16,6 +16,43 @@
 
 #define LOG_TAG "OpenGLRenderer"
 
+/**
+ * Extra vertices for the corner for smoother corner.
+ * Only for outer vertices.
+ * Note that we use such extra memory to avoid an extra loop.
+ */
+// For half circle, we could add EXTRA_VERTEX_PER_PI vertices.
+// Set to 1 if we don't want to have any.
+#define EXTRA_CORNER_VERTEX_PER_PI 12
+
+// For the whole polygon, the sum of all the deltas b/t normals is 2 * M_PI,
+// therefore, the maximum number of extra vertices will be twice bigger.
+#define MAX_EXTRA_CORNER_VERTEX_NUMBER  (2 * EXTRA_CORNER_VERTEX_PER_PI)
+
+// For each RADIANS_DIVISOR, we would allocate one more vertex b/t the normals.
+#define CORNER_RADIANS_DIVISOR (M_PI / EXTRA_CORNER_VERTEX_PER_PI)
+
+/**
+ * Extra vertices for the Edge for interpolation artifacts.
+ * Same value for both inner and outer vertices.
+ */
+#define EXTRA_EDGE_VERTEX_PER_PI 50
+
+#define MAX_EXTRA_EDGE_VERTEX_NUMBER  (2 * EXTRA_EDGE_VERTEX_PER_PI)
+
+#define EDGE_RADIANS_DIVISOR  (M_PI / EXTRA_EDGE_VERTEX_PER_PI)
+
+/**
+ * Other constants:
+ */
+// For the edge of the penumbra, the opacity is 0.
+#define OUTER_OPACITY (0.0f)
+
+// Once the alpha difference is greater than this threshold, we will allocate extra
+// edge vertices.
+// If this is set to negative value, then all the edge will be tessellated.
+#define ALPHA_THRESHOLD (0.1f / 255.0f)
+
 #include <math.h>
 #include <utils/Log.h>
 #include <utils/Vector.h>
@@ -23,11 +60,97 @@
 #include "AmbientShadow.h"
 #include "ShadowTessellator.h"
 #include "Vertex.h"
+#include "utils/MathUtils.h"
 
 namespace android {
 namespace uirenderer {
 
 /**
+ *  Local utility functions.
+ */
+inline Vector2 getNormalFromVertices(const Vector3* vertices, int current, int next) {
+    // Convert from Vector3 to Vector2 first.
+    Vector2 currentVertex = { vertices[current].x, vertices[current].y };
+    Vector2 nextVertex = { vertices[next].x, vertices[next].y };
+
+    return ShadowTessellator::calculateNormal(currentVertex, nextVertex);
+}
+
+// The input z value will be converted to be non-negative inside.
+// The output must be ranged from 0 to 1.
+inline float getAlphaFromFactoredZ(float factoredZ) {
+    return 1.0 / (1 + MathUtils::max(factoredZ, 0.0f));
+}
+
+inline float getTransformedAlphaFromAlpha(float alpha) {
+    return acosf(1.0f - 2.0f * alpha);
+}
+
+// The output is ranged from 0 to M_PI.
+inline float getTransformedAlphaFromFactoredZ(float factoredZ) {
+    return getTransformedAlphaFromAlpha(getAlphaFromFactoredZ(factoredZ));
+}
+
+inline int getExtraVertexNumber(const Vector2& vector1, const Vector2& vector2,
+        float divisor) {
+    // The formula is :
+    // extraNumber = floor(acos(dot(n1, n2)) / (M_PI / EXTRA_VERTEX_PER_PI))
+    // The value ranges for each step are:
+    // dot( ) --- [-1, 1]
+    // acos( )     --- [0, M_PI]
+    // floor(...)  --- [0, EXTRA_VERTEX_PER_PI]
+    float dotProduct = vector1.dot(vector2);
+    // TODO: Use look up table for the dotProduct to extraVerticesNumber
+    // computation, if needed.
+    float angle = acosf(dotProduct);
+    return (int) floor(angle / divisor);
+}
+
+inline void checkOverflow(int used, int total, const char* bufferName) {
+    LOG_ALWAYS_FATAL_IF(used > total, "Error: %s overflow!!! used %d, total %d",
+            bufferName, used, total);
+}
+
+inline int getEdgeExtraAndUpdateSpike(Vector2* currentSpike,
+        const Vector3& secondVertex, const Vector3& centroid) {
+    Vector2 secondSpike  = {secondVertex.x - centroid.x, secondVertex.y - centroid.y};
+    secondSpike.normalize();
+
+    int result = getExtraVertexNumber(secondSpike, *currentSpike, EDGE_RADIANS_DIVISOR);
+    *currentSpike = secondSpike;
+    return result;
+}
+
+// Given the caster's vertex count, compute all the buffers size depending on
+// whether or not the caster is opaque.
+inline void computeBufferSize(int* totalVertexCount, int* totalIndexCount,
+        int* totalUmbraCount, int casterVertexCount, bool isCasterOpaque) {
+    // Compute the size of the vertex buffer.
+    int outerVertexCount = casterVertexCount * 2 + MAX_EXTRA_CORNER_VERTEX_NUMBER +
+        MAX_EXTRA_EDGE_VERTEX_NUMBER;
+    int innerVertexCount = casterVertexCount + MAX_EXTRA_EDGE_VERTEX_NUMBER;
+    *totalVertexCount = outerVertexCount + innerVertexCount;
+
+    // Compute the size of the index buffer.
+    *totalIndexCount = 2 * outerVertexCount + 2;
+
+    // Compute the size of the umber buffer.
+    // For translucent object, keep track of the umbra(inner) vertex in order to draw
+    // inside. We only need to store the index information.
+    *totalUmbraCount = 0;
+    if (!isCasterOpaque) {
+        // Add the centroid if occluder is translucent.
+        *totalVertexCount++;
+        *totalIndexCount += 2 * innerVertexCount + 1;
+        *totalUmbraCount = innerVertexCount;
+    }
+}
+
+inline bool needsExtraForEdge(float firstAlpha, float secondAlpha) {
+    return abs(firstAlpha - secondAlpha) > ALPHA_THRESHOLD;
+}
+
+/**
  * Calculate the shadows as a triangle strips while alpha value as the
  * shadow values.
  *
@@ -43,290 +166,198 @@
  *
  * @param shadowVertexBuffer Return an floating point array of (x, y, a)
  *               triangle strips mode.
+ *
+ * An simple illustration:
+ * For now let's mark the outer vertex as Pi, the inner as Vi, the centroid as C.
+ *
+ * First project the occluder to the Z=0 surface.
+ * Then we got all the inner vertices. And we compute the normal for each edge.
+ * According to the normal, we generate outer vertices. E.g: We generate P1 / P4
+ * as extra corner vertices to make the corner looks round and smoother.
+ *
+ * Due to the fact that the alpha is not linear interpolated along the inner
+ * edge, when the alpha is different, we may add extra vertices such as P2.1, P2.2,
+ * V0.1, V0.2 to avoid the visual artifacts.
+ *
+ *                                            (P3)
+ *          (P2)     (P2.1)     (P2.2)         |     ' (P4)
+ *   (P1)'   |        |           |            |   '
+ *         ' |        |           |            | '
+ * (P0)  ------------------------------------------------(P5)
+ *           | (V0)   (V0.1)    (V0.2)         |(V1)
+ *           |                                 |
+ *           |                                 |
+ *           |               (C)               |
+ *           |                                 |
+ *           |                                 |
+ *           |                                 |
+ *           |                                 |
+ *        (V3)-----------------------------------(V2)
  */
 void AmbientShadow::createAmbientShadow(bool isCasterOpaque,
-        const Vector3* vertices, int vertexCount, const Vector3& centroid3d,
+        const Vector3* casterVertices, int casterVertexCount, const Vector3& centroid3d,
         float heightFactor, float geomFactor, VertexBuffer& shadowVertexBuffer) {
-    const int rays = SHADOW_RAY_COUNT;
-    // Validate the inputs.
-    if (vertexCount < 3 || heightFactor <= 0 || rays <= 0
-        || geomFactor <= 0) {
-#if DEBUG_SHADOW
-        ALOGW("Invalid input for createAmbientShadow(), early return!");
-#endif
-        return;
-    }
+    shadowVertexBuffer.setMode(VertexBuffer::kIndices);
 
-    Vector<Vector2> dir; // TODO: use C++11 unique_ptr
-    dir.setCapacity(rays);
-    float rayDist[rays];
-    float rayHeight[rays];
-    calculateRayDirections(rays, vertices, vertexCount, centroid3d, dir.editArray());
+    // In order to computer the outer vertices in one loop, we need pre-compute
+    // the normal by the vertex (n - 1) to vertex 0, and the spike and alpha value
+    // for vertex 0.
+    Vector2 previousNormal = getNormalFromVertices(casterVertices,
+            casterVertexCount - 1 , 0);
+    Vector2 currentSpike = {casterVertices[0].x - centroid3d.x,
+        casterVertices[0].y - centroid3d.y};
+    currentSpike.normalize();
+    float currentAlpha = getAlphaFromFactoredZ(casterVertices[0].z * heightFactor);
 
-    // Calculate the length and height of the points along the edge.
-    //
-    // The math here is:
-    // Intersect each ray (starting from the centroid) with the polygon.
-    for (int i = 0; i < rays; i++) {
-        int edgeIndex;
-        float edgeFraction;
-        float rayDistance;
-        calculateIntersection(vertices, vertexCount, centroid3d, dir[i], edgeIndex,
-                edgeFraction, rayDistance);
-        rayDist[i] = rayDistance;
-        if (edgeIndex < 0 || edgeIndex >= vertexCount) {
-#if DEBUG_SHADOW
-            ALOGW("Invalid edgeIndex!");
-#endif
-            edgeIndex = 0;
-        }
-        float h1 = vertices[edgeIndex].z;
-        float h2 = vertices[((edgeIndex + 1) % vertexCount)].z;
-        rayHeight[i] = h1 + edgeFraction * (h2 - h1);
-    }
-
-    // The output buffer length basically is roughly rays * layers, but since we
-    // need triangle strips, so we need to duplicate vertices to accomplish that.
+    // Preparing all the output data.
+    int totalVertexCount, totalIndexCount, totalUmbraCount;
+    computeBufferSize(&totalVertexCount, &totalIndexCount, &totalUmbraCount,
+            casterVertexCount, isCasterOpaque);
     AlphaVertex* shadowVertices =
-            shadowVertexBuffer.alloc<AlphaVertex>(SHADOW_VERTEX_COUNT);
+            shadowVertexBuffer.alloc<AlphaVertex>(totalVertexCount);
+    int vertexBufferIndex = 0;
+    uint16_t* indexBuffer = shadowVertexBuffer.allocIndices<uint16_t>(totalIndexCount);
+    int indexBufferIndex = 0;
+    uint16_t umbraVertices[totalUmbraCount];
+    int umbraIndex = 0;
 
-    // Calculate the vertex of the shadows.
-    //
-    // The math here is:
-    // Along the edges of the polygon, for each intersection point P (generated above),
-    // calculate the normal N, which should be perpendicular to the edge of the
-    // polygon (represented by the neighbor intersection points) .
-    // Shadow's vertices will be generated as : P + N * scale.
-    const Vector2 centroid2d = {centroid3d.x, centroid3d.y};
-    for (int rayIndex = 0; rayIndex < rays; rayIndex++) {
-        Vector2 normal = {1.0f, 0.0f};
-        calculateNormal(rays, rayIndex, dir.array(), rayDist, normal);
+    for (int i = 0; i < casterVertexCount; i++)  {
+        // Corner: first figure out the extra vertices we need for the corner.
+        const Vector3& innerVertex = casterVertices[i];
+        Vector2 currentNormal = getNormalFromVertices(casterVertices, i,
+                (i + 1) % casterVertexCount);
 
-        // The vertex should be start from rayDist[i] then scale the
-        // normalizeNormal!
-        Vector2 intersection = dir[rayIndex] * rayDist[rayIndex] +
-                centroid2d;
+        int extraVerticesNumber = getExtraVertexNumber(currentNormal, previousNormal,
+                CORNER_RADIANS_DIVISOR);
 
-        // outer ring of points, expanded based upon height of each ray intersection
-        float expansionDist = rayHeight[rayIndex] * heightFactor *
-                geomFactor;
-        AlphaVertex::set(&shadowVertices[rayIndex],
-                intersection.x + normal.x * expansionDist,
-                intersection.y + normal.y * expansionDist,
-                0.0f);
-
-        // inner ring of points
-        float opacity = 1.0 / (1 + rayHeight[rayIndex] * heightFactor);
-        // NOTE: Shadow alpha values are transformed when stored in alphavertices,
-        // so that they can be consumed directly by gFS_Main_ApplyVertexAlphaShadowInterp
-        float transformedOpacity = acos(1.0f - 2.0f * opacity);
-        AlphaVertex::set(&shadowVertices[rays + rayIndex],
-                intersection.x,
-                intersection.y,
-                transformedOpacity);
-    }
-
-    if (isCasterOpaque) {
-        // skip inner ring, calc bounds over filled portion of buffer
-        shadowVertexBuffer.computeBounds<AlphaVertex>(2 * rays);
-        shadowVertexBuffer.setMode(VertexBuffer::kOnePolyRingShadow);
-    } else {
-        // If caster isn't opaque, we need to to fill the umbra by storing the umbra's
-        // centroid in the innermost ring of vertices.
-        float centroidAlpha = 1.0 / (1 + centroid3d.z * heightFactor);
-        AlphaVertex centroidXYA;
-        AlphaVertex::set(&centroidXYA, centroid2d.x, centroid2d.y, centroidAlpha);
-        for (int rayIndex = 0; rayIndex < rays; rayIndex++) {
-            shadowVertices[2 * rays + rayIndex] = centroidXYA;
-        }
-        // calc bounds over entire buffer
-        shadowVertexBuffer.computeBounds<AlphaVertex>();
-        shadowVertexBuffer.setMode(VertexBuffer::kTwoPolyRingShadow);
-    }
-
+        float expansionDist = innerVertex.z * heightFactor * geomFactor;
+        const int cornerSlicesNumber = extraVerticesNumber + 1; // Minimal as 1.
 #if DEBUG_SHADOW
-    for (int i = 0; i < SHADOW_VERTEX_COUNT; i++) {
-        ALOGD("ambient shadow value: i %d, (x:%f, y:%f, a:%f)", i, shadowVertices[i].x,
-                shadowVertices[i].y, shadowVertices[i].alpha);
-    }
+        ALOGD("cornerSlicesNumber is %d", cornerSlicesNumber);
 #endif
-}
 
-/**
- * Generate an array of rays' direction vectors.
- * To make sure the vertices generated are clockwise, the directions are from PI
- * to -PI.
- *
- * @param rays The number of rays shooting out from the centroid.
- * @param vertices Vertices of the polygon.
- * @param vertexCount The number of vertices.
- * @param centroid3d The centroid of the polygon.
- * @param dir Return the array of ray vectors.
- */
-void AmbientShadow::calculateRayDirections(const int rays, const Vector3* vertices,
-        const int vertexCount, const Vector3& centroid3d, Vector2* dir) {
-    // If we don't have enough rays, then fall back to the uniform distribution.
-    if (vertexCount * 2 > rays) {
-        float deltaAngle = 2 * M_PI / rays;
-        for (int i = 0; i < rays; i++) {
-            dir[i].x = cosf(M_PI - deltaAngle * i);
-            dir[i].y = sinf(M_PI - deltaAngle * i);
+        // Corner: fill the corner Vertex Buffer(VB) and Index Buffer(IB).
+        // We fill the inner vertex first, such that we can fill the index buffer
+        // inside the loop.
+        int currentInnerVertexIndex = vertexBufferIndex;
+        if (!isCasterOpaque) {
+            umbraVertices[umbraIndex++] = vertexBufferIndex;
         }
-        return;
-    }
+        AlphaVertex::set(&shadowVertices[vertexBufferIndex++], casterVertices[i].x,
+                casterVertices[i].y,
+                getTransformedAlphaFromAlpha(currentAlpha));
 
-    // If we have enough rays, then we assign each vertices a ray, and distribute
-    // the rest uniformly.
-    float rayThetas[rays];
+        const Vector3& innerStart = casterVertices[i];
 
-    const int uniformRayCount = rays - vertexCount;
-    const float deltaAngle = 2 * M_PI / uniformRayCount;
+        // outerStart is the first outer vertex for this inner vertex.
+        // outerLast is the last outer vertex for this inner vertex.
+        Vector2 outerStart = {0, 0};
+        Vector2 outerLast = {0, 0};
+        // This will create vertices from [0, cornerSlicesNumber] inclusively,
+        // which means minimally 2 vertices even without the extra ones.
+        for (int j = 0; j <= cornerSlicesNumber; j++) {
+            Vector2 averageNormal =
+                previousNormal * (cornerSlicesNumber - j) + currentNormal * j;
+            averageNormal /= cornerSlicesNumber;
+            averageNormal.normalize();
+            Vector2 outerVertex;
+            outerVertex.x = innerVertex.x + averageNormal.x * expansionDist;
+            outerVertex.y = innerVertex.y + averageNormal.y * expansionDist;
 
-    // We have to generate all the vertices' theta anyway and we also need to
-    // find the minimal, so let's precompute it first.
-    // Since the incoming polygon is clockwise, we can find the dip to identify
-    // the minimal theta.
-    float polyThetas[vertexCount];
-    int maxPolyThetaIndex = 0;
-    for (int i = 0; i < vertexCount; i++) {
-        polyThetas[i] = atan2(vertices[i].y - centroid3d.y,
-                vertices[i].x - centroid3d.x);
-        if (i > 0 && polyThetas[i] > polyThetas[i - 1]) {
-            maxPolyThetaIndex = i;
-        }
-    }
+            indexBuffer[indexBufferIndex++] = vertexBufferIndex;
+            indexBuffer[indexBufferIndex++] = currentInnerVertexIndex;
+            AlphaVertex::set(&shadowVertices[vertexBufferIndex++], outerVertex.x,
+                    outerVertex.y, OUTER_OPACITY);
 
-    // Both poly's thetas and uniform thetas are in decrease order(clockwise)
-    // from PI to -PI.
-    int polyThetaIndex = maxPolyThetaIndex;
-    float polyTheta = polyThetas[maxPolyThetaIndex];
-    int uniformThetaIndex = 0;
-    float uniformTheta = M_PI;
-    for (int i = 0; i < rays; i++) {
-        // Compare both thetas and pick the smaller one and move on.
-        bool hasThetaCollision = abs(polyTheta - uniformTheta) < MINIMAL_DELTA_THETA;
-        if (polyTheta > uniformTheta || hasThetaCollision) {
-            if (hasThetaCollision) {
-                // Shift the uniformTheta to middle way between current polyTheta
-                // and next uniform theta. The next uniform theta can wrap around
-                // to exactly PI safely here.
-                // Note that neither polyTheta nor uniformTheta can be FLT_MAX
-                // due to the hasThetaCollision is true.
-                uniformTheta = (polyTheta +  M_PI - deltaAngle * (uniformThetaIndex + 1)) / 2;
-#if DEBUG_SHADOW
-                ALOGD("Shifted uniformTheta to %f", uniformTheta);
-#endif
-            }
-            rayThetas[i] = polyTheta;
-            polyThetaIndex = (polyThetaIndex + 1) % vertexCount;
-            if (polyThetaIndex != maxPolyThetaIndex) {
-                polyTheta = polyThetas[polyThetaIndex];
-            } else {
-                // out of poly points.
-                polyTheta = - FLT_MAX;
-            }
-        } else {
-            rayThetas[i] = uniformTheta;
-            uniformThetaIndex++;
-            if (uniformThetaIndex < uniformRayCount) {
-                uniformTheta = M_PI - deltaAngle * uniformThetaIndex;
-            } else {
-                // out of uniform points.
-                uniformTheta = - FLT_MAX;
+            if (j == 0) {
+                outerStart = outerVertex;
+            } else if (j == cornerSlicesNumber) {
+                outerLast = outerVertex;
             }
         }
-    }
+        previousNormal = currentNormal;
 
-    for (int i = 0; i < rays; i++) {
+        // Edge: first figure out the extra vertices needed for the edge.
+        const Vector3& innerNext = casterVertices[(i + 1) % casterVertexCount];
+        float nextAlpha = getAlphaFromFactoredZ(innerNext.z * heightFactor);
+        if (needsExtraForEdge(currentAlpha, nextAlpha)) {
+            // TODO: See if we can / should cache this outer vertex across the loop.
+            Vector2 outerNext;
+            float expansionDist = innerNext.z * heightFactor * geomFactor;
+            outerNext.x = innerNext.x + currentNormal.x * expansionDist;
+            outerNext.y = innerNext.y + currentNormal.y * expansionDist;
+
+            // Compute the angle and see how many extra points we need.
+            int extraVerticesNumber = getEdgeExtraAndUpdateSpike(&currentSpike,
+                    innerNext, centroid3d);
 #if DEBUG_SHADOW
-        ALOGD("No. %d : %f", i, rayThetas[i] * 180 / M_PI);
+            ALOGD("extraVerticesNumber %d for edge %d", extraVerticesNumber, i);
 #endif
-        // TODO: Fix the intersection precision problem and remvoe the delta added
-        // here.
-        dir[i].x = cosf(rayThetas[i] + MINIMAL_DELTA_THETA);
-        dir[i].y = sinf(rayThetas[i] + MINIMAL_DELTA_THETA);
-    }
-}
+            // Edge: fill the edge's VB and IB.
+            // This will create vertices pair from [1, extraVerticesNumber - 1].
+            // If there is no extra vertices created here, the edge will be drawn
+            // as just 2 triangles.
+            for (int k = 1; k < extraVerticesNumber; k++) {
+                int startWeight = extraVerticesNumber - k;
+                Vector2 currentOuter =
+                    (outerLast * startWeight + outerNext * k) / extraVerticesNumber;
+                indexBuffer[indexBufferIndex++] = vertexBufferIndex;
+                AlphaVertex::set(&shadowVertices[vertexBufferIndex++], currentOuter.x,
+                        currentOuter.y, OUTER_OPACITY);
 
-/**
- * Calculate the intersection of a ray hitting the polygon.
- *
- * @param vertices The shadow caster's polygon, which is represented in a
- *                 Vector3 array.
- * @param vertexCount The length of caster's polygon in terms of number of vertices.
- * @param start The starting point of the ray.
- * @param dir The direction vector of the ray.
- *
- * @param outEdgeIndex Return the index of the segment (or index of the starting
- *                     vertex) that ray intersect with.
- * @param outEdgeFraction Return the fraction offset from the segment starting
- *                        index.
- * @param outRayDist Return the ray distance from centroid to the intersection.
- */
-void AmbientShadow::calculateIntersection(const Vector3* vertices, int vertexCount,
-        const Vector3& start, const Vector2& dir, int& outEdgeIndex,
-        float& outEdgeFraction, float& outRayDist) {
-    float startX = start.x;
-    float startY = start.y;
-    float dirX = dir.x;
-    float dirY = dir.y;
-    // Start the search from the last edge from poly[len-1] to poly[0].
-    int p1 = vertexCount - 1;
-
-    for (int p2 = 0; p2 < vertexCount; p2++) {
-        float p1x = vertices[p1].x;
-        float p1y = vertices[p1].y;
-        float p2x = vertices[p2].x;
-        float p2y = vertices[p2].y;
-
-        // The math here is derived from:
-        // f(t, v) = p1x * (1 - t) + p2x * t - (startX + dirX * v) = 0;
-        // g(t, v) = p1y * (1 - t) + p2y * t - (startY + dirY * v) = 0;
-        float div = (dirX * (p1y - p2y) + dirY * p2x - dirY * p1x);
-        if (div != 0) {
-            float t = (dirX * (p1y - startY) + dirY * startX - dirY * p1x) / (div);
-            if (t > 0 && t <= 1) {
-                float t2 = (p1x * (startY - p2y)
-                            + p2x * (p1y - startY)
-                            + startX * (p2y - p1y)) / div;
-                if (t2 > 0) {
-                    outEdgeIndex = p1;
-                    outRayDist = t2;
-                    outEdgeFraction = t;
-                    return;
+                if (!isCasterOpaque) {
+                    umbraVertices[umbraIndex++] = vertexBufferIndex;
                 }
+                Vector3 currentInner =
+                    (innerStart * startWeight + innerNext * k) / extraVerticesNumber;
+                indexBuffer[indexBufferIndex++] = vertexBufferIndex;
+                AlphaVertex::set(&shadowVertices[vertexBufferIndex++], currentInner.x,
+                        currentInner.y,
+                        getTransformedAlphaFromFactoredZ(currentInner.z * heightFactor));
             }
         }
-        p1 = p2;
+        currentAlpha = nextAlpha;
     }
-    return;
-};
 
-/**
- * Calculate the normal at the intersection point between a ray and the polygon.
- *
- * @param rays The total number of rays.
- * @param currentRayIndex The index of the ray which the normal is based on.
- * @param dir The array of the all the rays directions.
- * @param rayDist The pre-computed ray distances array.
- *
- * @param normal Return the normal.
- */
-void AmbientShadow::calculateNormal(int rays, int currentRayIndex,
-        const Vector2* dir, const float* rayDist, Vector2& normal) {
-    int preIndex = (currentRayIndex - 1 + rays) % rays;
-    int postIndex = (currentRayIndex + 1) % rays;
-    Vector2 p1 = dir[preIndex] * rayDist[preIndex];
-    Vector2 p2 = dir[postIndex] * rayDist[postIndex];
+    indexBuffer[indexBufferIndex++] = 1;
+    indexBuffer[indexBufferIndex++] = 0;
 
-    // Now the rays are going CW around the poly.
-    Vector2 delta = p2 - p1;
-    if (delta.length() != 0) {
-        delta.normalize();
-        // Calculate the normal , which is CCW 90 rotate to the delta.
-        normal.x = - delta.y;
-        normal.y = delta.x;
+    if (!isCasterOpaque) {
+        // Add the centroid as the last one in the vertex buffer.
+        float centroidOpacity =
+            getTransformedAlphaFromFactoredZ(centroid3d.z * heightFactor);
+        int centroidIndex = vertexBufferIndex;
+        AlphaVertex::set(&shadowVertices[vertexBufferIndex++], centroid3d.x,
+                centroid3d.y, centroidOpacity);
+
+        for (int i = 0; i < umbraIndex; i++) {
+            // Note that umbraVertices[0] is always 0.
+            // So the start and the end of the umbra are using the "0".
+            // And penumbra ended with 0, so a degenerated triangle is formed b/t
+            // the umbra and penumbra.
+            indexBuffer[indexBufferIndex++] = umbraVertices[i];
+            indexBuffer[indexBufferIndex++] = centroidIndex;
+        }
+        indexBuffer[indexBufferIndex++] = 0;
     }
+
+    // At the end, update the real index and vertex buffer size.
+    shadowVertexBuffer.updateVertexCount(vertexBufferIndex);
+    shadowVertexBuffer.updateIndexCount(indexBufferIndex);
+
+    checkOverflow(vertexBufferIndex, totalVertexCount, "Vertex Buffer");
+    checkOverflow(indexBufferIndex, totalIndexCount, "Index Buffer");
+    checkOverflow(umbraIndex, totalUmbraCount, "Umbra Buffer");
+
+#if DEBUG_SHADOW
+    for (int i = 0; i < vertexBufferIndex; i++) {
+        ALOGD("vertexBuffer i %d, (%f, %f %f)", i, shadowVertices[i].x, shadowVertices[i].y,
+                shadowVertices[i].alpha);
+    }
+    for (int i = 0; i < indexBufferIndex; i++) {
+        ALOGD("indexBuffer i %d, indexBuffer[i] %d", i, indexBuffer[i]);
+    }
+#endif
 }
 
 }; // namespace uirenderer
diff --git a/libs/hwui/AmbientShadow.h b/libs/hwui/AmbientShadow.h
index 68df246..9660dc0 100644
--- a/libs/hwui/AmbientShadow.h
+++ b/libs/hwui/AmbientShadow.h
@@ -28,27 +28,12 @@
 
 /**
  * AmbientShadow is used to calculate the ambient shadow value around a polygon.
- *
- * TODO: calculateIntersection() now is O(N*M), where N is the number of
- * polygon's vertics and M is the number of rays. In fact, by staring tracing
- * the vertex from the previous intersection, the algorithm can be O(N + M);
  */
 class AmbientShadow {
 public:
     static void createAmbientShadow(bool isCasterOpaque, const Vector3* poly,
             int polyLength, const Vector3& centroid3d, float heightFactor,
             float geomFactor, VertexBuffer& shadowVertexBuffer);
-
-private:
-    static void calculateRayDirections(const int rays, const Vector3* vertices,
-            const int vertexCount, const Vector3& centroid3d, Vector2* dir);
-
-    static void calculateIntersection(const Vector3* poly, int nbVertices,
-            const Vector3& start, const Vector2& dir, int& outEdgeIndex,
-            float& outEdgeFraction, float& outRayDist);
-
-    static void calculateNormal(int rays, int currentRayIndex, const Vector2* dir,
-            const float* rayDist, Vector2& normal);
 }; // AmbientShadow
 
 }; // namespace uirenderer
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index bbf0551..0f36c06 100755
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -2417,6 +2417,10 @@
     } else if (mode == VertexBuffer::kTwoPolyRingShadow) {
         mCaches.bindShadowIndicesBuffer();
         glDrawElements(GL_TRIANGLE_STRIP, TWO_POLY_RING_SHADOW_INDEX_COUNT, GL_UNSIGNED_SHORT, 0);
+    } else if (mode == VertexBuffer::kIndices) {
+        mCaches.unbindIndicesBuffer();
+        glDrawElements(GL_TRIANGLE_STRIP, vertexBuffer.getIndexCount(), GL_UNSIGNED_SHORT,
+                vertexBuffer.getIndices());
     }
 
     if (isAA) {
diff --git a/libs/hwui/Vector.h b/libs/hwui/Vector.h
index 2a9f01c..d033ed9 100644
--- a/libs/hwui/Vector.h
+++ b/libs/hwui/Vector.h
@@ -111,6 +111,23 @@
     float y;
     float z;
 
+    Vector3 operator+(const Vector3& v) const {
+        return (Vector3){x + v.x, y + v.y, z + v.z};
+    }
+
+    Vector3 operator-(const Vector3& v) const {
+        return (Vector3){x - v.x, y - v.y, z - v.z};
+    }
+
+    Vector3 operator/(float s) const {
+        return (Vector3){x / s, y / s, z / s};
+    }
+
+    Vector3 operator*(float s) const {
+        return (Vector3){x * s, y * s, z * s};
+    }
+
+
     void dump() {
         ALOGD("Vector3[%.2f, %.2f, %.2f]", x, y, z);
     }
diff --git a/libs/hwui/VertexBuffer.h b/libs/hwui/VertexBuffer.h
index 3837f88..966fa4e 100644
--- a/libs/hwui/VertexBuffer.h
+++ b/libs/hwui/VertexBuffer.h
@@ -17,6 +17,7 @@
 #ifndef ANDROID_HWUI_VERTEX_BUFFER_H
 #define ANDROID_HWUI_VERTEX_BUFFER_H
 
+#include "utils/MathUtils.h"
 
 namespace android {
 namespace uirenderer {
@@ -26,19 +27,27 @@
     enum Mode {
         kStandard = 0,
         kOnePolyRingShadow = 1,
-        kTwoPolyRingShadow = 2
+        kTwoPolyRingShadow = 2,
+        kIndices = 3
     };
 
     VertexBuffer()
             : mBuffer(0)
+            , mIndices(0)
             , mVertexCount(0)
+            , mIndexCount(0)
+            , mAllocatedVertexCount(0)
+            , mAllocatedIndexCount(0)
             , mByteCount(0)
             , mMode(kStandard)
+            , mReallocBuffer(0)
             , mCleanupMethod(NULL)
+            , mCleanupIndexMethod(NULL)
     {}
 
     ~VertexBuffer() {
         if (mCleanupMethod) mCleanupMethod(mBuffer);
+        if (mCleanupIndexMethod) mCleanupIndexMethod(mIndices);
     }
 
     /**
@@ -59,6 +68,7 @@
             mReallocBuffer = reallocBuffer + vertexCount;
             return reallocBuffer;
         }
+        mAllocatedVertexCount = vertexCount;
         mVertexCount = vertexCount;
         mByteCount = mVertexCount * sizeof(TYPE);
         mReallocBuffer = mBuffer = (void*)new TYPE[vertexCount];
@@ -69,6 +79,17 @@
     }
 
     template <class TYPE>
+    TYPE* allocIndices(int indexCount) {
+        mAllocatedIndexCount = indexCount;
+        mIndexCount = indexCount;
+        mIndices = (void*)new TYPE[indexCount];
+
+        mCleanupIndexMethod = &(cleanup<TYPE>);
+
+        return (TYPE*)mIndices;
+    }
+
+    template <class TYPE>
     void copyInto(const VertexBuffer& srcBuffer, float xOffset, float yOffset) {
         int verticesToCopy = srcBuffer.getVertexCount();
 
@@ -103,9 +124,17 @@
     }
 
     const void* getBuffer() const { return mBuffer; }
+    const void* getIndices() const { return mIndices; }
     const Rect& getBounds() const { return mBounds; }
     unsigned int getVertexCount() const { return mVertexCount; }
     unsigned int getSize() const { return mByteCount; }
+    unsigned int getIndexCount() const { return mIndexCount; }
+    void updateIndexCount(unsigned int newCount)  {
+        mIndexCount = MathUtils::min(newCount, mAllocatedIndexCount);
+    }
+    void updateVertexCount(unsigned int newCount)  {
+        newCount = MathUtils::min(newCount, mAllocatedVertexCount);
+    }
     Mode getMode() const { return mMode; }
 
     void setBounds(Rect bounds) { mBounds = bounds; }
@@ -127,14 +156,22 @@
     }
 
     Rect mBounds;
+
     void* mBuffer;
+    void* mIndices;
+
     unsigned int mVertexCount;
+    unsigned int mIndexCount;
+    unsigned int mAllocatedVertexCount;
+    unsigned int mAllocatedIndexCount;
     unsigned int mByteCount;
+
     Mode mMode;
 
     void* mReallocBuffer; // used for multi-allocation
 
     void (*mCleanupMethod)(void*);
+    void (*mCleanupIndexMethod)(void*);
 };
 
 }; // namespace uirenderer
diff --git a/services/core/java/com/android/server/am/ContentProviderRecord.java b/services/core/java/com/android/server/am/ContentProviderRecord.java
index ff22764..a37249d 100644
--- a/services/core/java/com/android/server/am/ContentProviderRecord.java
+++ b/services/core/java/com/android/server/am/ContentProviderRecord.java
@@ -166,8 +166,16 @@
         }
         if (full) {
             if (hasExternalProcessHandles()) {
-                pw.print(prefix); pw.print("externals=");
-                        pw.println(externalProcessTokenToHandle.size());
+                pw.print(prefix); pw.print("externals:");
+                if (externalProcessTokenToHandle != null) {
+                    pw.print(" w/token=");
+                    pw.print(externalProcessTokenToHandle.size());
+                }
+                if (externalProcessNoHandleCount > 0) {
+                    pw.print(" notoken=");
+                    pw.print(externalProcessNoHandleCount);
+                }
+                pw.println();
             }
         } else {
             if (connections.size() > 0 || externalProcessNoHandleCount > 0) {