Merge "Hide GeocoderParams class from public API."
diff --git a/core/java/android/net/http/SslCertificate.java b/core/java/android/net/http/SslCertificate.java
index e2d687d..c29926c 100644
--- a/core/java/android/net/http/SslCertificate.java
+++ b/core/java/android/net/http/SslCertificate.java
@@ -128,8 +128,8 @@
             String issuedTo, String issuedBy, Date validNotBefore, Date validNotAfter) {
         mIssuedTo = new DName(issuedTo);
         mIssuedBy = new DName(issuedBy);
-        mValidNotBefore = validNotBefore;
-        mValidNotAfter = validNotAfter;
+        mValidNotBefore = cloneDate(validNotBefore);
+        mValidNotAfter  = cloneDate(validNotAfter);
     }
 
     /**
@@ -148,7 +148,7 @@
      * "" if none has been set
      */
     public Date getValidNotBeforeDate() {
-        return mValidNotBefore;
+        return cloneDate(mValidNotBefore);
     }
 
     /**
@@ -166,7 +166,7 @@
      * "" if none has been set
      */
     public Date getValidNotAfterDate() {
-        return mValidNotAfter;
+        return cloneDate(mValidNotAfter);
     }
 
     /**
@@ -224,6 +224,16 @@
     }
 
     /**
+     * Clone a possibly null Date
+     */
+    private static Date cloneDate(Date date) {
+        if (date == null) {
+            return null;
+        }
+        return (Date) date.clone();
+    }
+
+    /**
      * A distinguished name helper class: a 3-tuple of:
      * - common name (CN),
      * - organization (O),
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 639441b..abbab0e 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6493,7 +6493,7 @@
      * Create a snapshot of the view into a bitmap.  We should probably make
      * some form of this public, but should think about the API.
      */
-    Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor) {
+    Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
         int width = mRight - mLeft;
         int height = mBottom - mTop;
 
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index 616485e..8311bdc 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -23,9 +23,12 @@
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.Rect;
 import android.os.Environment;
 import android.os.Debug;
+import android.os.RemoteException;
 
+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.BufferedWriter;
 import java.io.FileWriter;
@@ -345,6 +348,7 @@
     private static final String REMOTE_COMMAND_INVALIDATE = "INVALIDATE";
     private static final String REMOTE_COMMAND_REQUEST_LAYOUT = "REQUEST_LAYOUT";
     private static final String REMOTE_PROFILE = "PROFILE";
+    private static final String REMOTE_COMMAND_CAPTURE_LAYERS = "CAPTURE_LAYERS";
 
     private static HashMap<Class<?>, Field[]> sFieldsForClasses;
     private static HashMap<Class<?>, Method[]> sMethodsForClasses;
@@ -846,6 +850,8 @@
 
         if (REMOTE_COMMAND_DUMP.equalsIgnoreCase(command)) {
             dump(view, clientStream);
+        } else if (REMOTE_COMMAND_CAPTURE_LAYERS.equalsIgnoreCase(command)) {
+            captureLayers(view, new DataOutputStream(clientStream));
         } else {
             final String[] params = parameters.split(" ");
             if (REMOTE_COMMAND_CAPTURE.equalsIgnoreCase(command)) {
@@ -1017,24 +1023,109 @@
         return duration[0];
     }
 
+    private static void captureLayers(View root, final DataOutputStream clientStream)
+            throws IOException {
+
+        try {
+            Rect outRect = new Rect();
+            try {
+                root.mAttachInfo.mSession.getDisplayFrame(root.mAttachInfo.mWindow, outRect);
+            } catch (RemoteException e) {
+                // Ignore
+            }
+    
+            clientStream.writeInt(outRect.width());
+            clientStream.writeInt(outRect.height());
+    
+            captureViewLayer(root, clientStream);
+            
+            clientStream.write(2);
+        } finally {
+            clientStream.close();
+        }
+    }
+
+    private static void captureViewLayer(View view, DataOutputStream clientStream)
+            throws IOException {
+
+        if ((view.mPrivateFlags & View.SKIP_DRAW) != View.SKIP_DRAW) {
+            final int id = view.getId();
+            String name = view.getClass().getSimpleName();
+            if (id != View.NO_ID) {
+                name = resolveId(view.getContext(), id).toString();
+            }
+    
+            clientStream.write(1);
+            clientStream.writeUTF(name);
+            clientStream.writeByte(view.getVisibility() == View.VISIBLE ? 1 : 0);
+    
+            int[] position = new int[2];
+            // XXX: Should happen on the UI thread
+            view.getLocationInWindow(position);
+    
+            clientStream.writeInt(position[0]);
+            clientStream.writeInt(position[1]);
+            clientStream.flush();
+    
+            Bitmap b = performViewCapture(view, true);
+            if (b != null) {
+                ByteArrayOutputStream arrayOut = new ByteArrayOutputStream(b.getWidth() *
+                        b.getHeight() * 2);
+                b.compress(Bitmap.CompressFormat.PNG, 100, arrayOut);
+                clientStream.writeInt(arrayOut.size());
+                arrayOut.writeTo(clientStream);
+            }
+            clientStream.flush();
+        }
+
+        if (view instanceof ViewGroup) {
+            ViewGroup group = (ViewGroup) view;
+            int count = group.getChildCount();
+
+            for (int i = 0; i < count; i++) {
+                captureViewLayer(group.getChildAt(i), clientStream);
+            }
+        }
+    }
+
     private static void capture(View root, final OutputStream clientStream, String parameter)
             throws IOException {
 
         final View captureView = findView(root, parameter);
+        Bitmap b = performViewCapture(captureView, false);
+       
+        if (b != null) {
+            BufferedOutputStream out = null;
+            try {
+                out = new BufferedOutputStream(clientStream, 32 * 1024);
+                b.compress(Bitmap.CompressFormat.PNG, 100, out);
+                out.flush();
+            } finally {
+                if (out != null) {
+                    out.close();
+                }
+                b.recycle();
+            }
+        } else {
+            Log.w("View", "Failed to create capture bitmap!");
+            clientStream.close();
+        }
+    }
 
+    private static Bitmap performViewCapture(final View captureView, final boolean skpiChildren) {
         if (captureView != null) {
             final CountDownLatch latch = new CountDownLatch(1);
             final Bitmap[] cache = new Bitmap[1];
 
-            root.post(new Runnable() {
+            captureView.post(new Runnable() {
                 public void run() {
                     try {
                         cache[0] = captureView.createSnapshot(
-                                Bitmap.Config.ARGB_8888, 0);
+                                Bitmap.Config.ARGB_8888, 0, skpiChildren);
                     } catch (OutOfMemoryError e) {
                         try {
                             cache[0] = captureView.createSnapshot(
-                                    Bitmap.Config.ARGB_4444, 0);
+                                    Bitmap.Config.ARGB_4444, 0, skpiChildren);
                         } catch (OutOfMemoryError e2) {
                             Log.w("View", "Out of memory for bitmap");
                         }
@@ -1046,28 +1137,14 @@
 
             try {
                 latch.await(CAPTURE_TIMEOUT, TimeUnit.MILLISECONDS);
-
-                if (cache[0] != null) {
-                    BufferedOutputStream out = null;
-                    try {
-                        out = new BufferedOutputStream(clientStream, 32 * 1024);
-                        cache[0].compress(Bitmap.CompressFormat.PNG, 100, out);
-                        out.flush();
-                    } finally {
-                        if (out != null) {
-                            out.close();
-                        }
-                        cache[0].recycle();
-                    }
-                } else {
-                    Log.w("View", "Failed to create capture bitmap!");
-                    clientStream.close();
-                }
+                return cache[0];
             } catch (InterruptedException e) {
                 Log.w("View", "Could not complete the capture of the view " + captureView);
                 Thread.currentThread().interrupt();
             }
         }
+        
+        return null;
     }
 
     private static void dump(View root, OutputStream clientStream) throws IOException {
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 9bf36bb..597d583 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -1272,6 +1272,19 @@
         }
     }
 
+    @Override
+    Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
+        int oldCount = mChildrenCount;
+        if (skipChildren) {
+            mChildrenCount = 0;
+        }
+
+        Bitmap b = super.createSnapshot(quality, backgroundColor, skipChildren);
+        mChildrenCount = oldCount;
+
+        return b;
+    }
+
     /**
      * {@inheritDoc}
      */
diff --git a/core/java/android/widget/OverScroller.java b/core/java/android/widget/OverScroller.java
index b11caa1..1730a68 100644
--- a/core/java/android/widget/OverScroller.java
+++ b/core/java/android/widget/OverScroller.java
@@ -394,4 +394,44 @@
     public float getCurrVelocity() {
         return mCurrScroller.getCurrVelocity();
     }
+    
+    /**
+     * Extend the scroll animation. This allows a running animation to scroll
+     * further and longer, when used with {@link #setFinalX(int)} or {@link #setFinalY(int)}.
+     *
+     * @param extend Additional time to scroll in milliseconds.
+     * @see #setFinalX(int)
+     * @see #setFinalY(int)
+     */
+    public void extendDuration(int extend) {
+        if (mScrollMode == MODE_DEFAULT) {
+            mDefaultScroller.extendDuration(extend);
+        }
+    }
+    
+    /**
+     * Sets the final position (X) for this scroller.
+     *
+     * @param newX The new X offset as an absolute distance from the origin.
+     * @see #extendDuration(int)
+     * @see #setFinalY(int)
+     */
+    public void setFinalX(int newX) {
+        if (mScrollMode == MODE_DEFAULT) {
+            mDefaultScroller.setFinalX(newX);
+        }
+    }
+    
+    /**
+     * Sets the final position (Y) for this scroller.
+     *
+     * @param newY The new Y offset as an absolute distance from the origin.
+     * @see #extendDuration(int)
+     * @see #setFinalX(int)
+     */
+    public void setFinalY(int newY) {
+        if (mScrollMode == MODE_DEFAULT) {
+            mDefaultScroller.setFinalY(newY);
+        }
+    }
 }
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index d9d9bfe..5969617 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -246,10 +246,15 @@
     LOGI("version   : %s", glGetString(GL_VERSION));
     LOGI("extensions: %s", gl_extensions);
 
-    if (strstr(gl_renderer, "Adreno")) {
+#if 0
+    // for drivers that don't have proper support for flushing cached buffers
+    // on gralloc unlock, uncomment this block and test for the specific
+    // renderer substring
+    if (strstr(gl_renderer, "<some vendor string>")) {
         LOGD("Assuming uncached graphics buffers.");
         mFlags &= ~CACHED_BUFFERS;
     }
+#endif
 
     if (strstr(gl_extensions, "GL_ARB_texture_non_power_of_two")) {
         mFlags |= NPOT_EXTENSION;