am aa642c0c: Merge changes 1591,1596 into donut

Merge commit 'aa642c0cc20293137376d44f8221876c121e5be9'

* commit 'aa642c0cc20293137376d44f8221876c121e5be9':
  Get the backup calling through to the file backup helper.
  Fix typos.
  Add a new feature to android.os.Debug to add the ability to inject only specific fields when calling setFieldsOn().
  Fixes #1836075. Adds consistency checks for the View hierarchy. To enable them, you need a debug build and ViewDebug.sConsistencyCheckEnabled set to true in debug.prop. This change also lets you easily enable drawing and layout profiling in ViewRoot by setting ViewRoot.sProfileDrawing, ViewRoot.sProfileLayout and ViewRoot.sShowFps in debug.prop with a debug build.
  Add Intent.ACTION_APP_ERROR
diff --git a/api/current.xml b/api/current.xml
index 95fbea9..b8330b2 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -23859,219 +23859,6 @@
 </field>
 </class>
 </package>
-<package name="android.backup"
->
-<class name="BackupDataOutput"
- extends="java.lang.Object"
- abstract="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<constructor name="BackupDataOutput"
- type="android.backup.BackupDataOutput"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="context" type="android.content.Context">
-</parameter>
-<parameter name="fd" type="java.io.FileDescriptor">
-</parameter>
-</constructor>
-<method name="close"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="flush"
- return="void"
- abstract="false"
- native="true"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="write"
- return="void"
- abstract="false"
- native="true"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="buffer" type="byte[]">
-</parameter>
-</method>
-<method name="write"
- return="void"
- abstract="false"
- native="true"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="oneByte" type="int">
-</parameter>
-</method>
-<method name="write"
- return="void"
- abstract="false"
- native="true"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="buffer" type="byte[]">
-</parameter>
-<parameter name="offset" type="int">
-</parameter>
-<parameter name="count" type="int">
-</parameter>
-</method>
-<method name="writeKey"
- return="void"
- abstract="false"
- native="true"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="key" type="java.lang.String">
-</parameter>
-</method>
-<method name="writeOperation"
- return="void"
- abstract="false"
- native="true"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="op" type="int">
-</parameter>
-</method>
-<field name="OP_DELETE"
- type="int"
- transient="false"
- volatile="false"
- value="2"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="OP_UPDATE"
- type="int"
- transient="false"
- volatile="false"
- value="1"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-</class>
-<class name="FileBackupHelper"
- extends="java.lang.Object"
- abstract="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<constructor name="FileBackupHelper"
- type="android.backup.FileBackupHelper"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</constructor>
-<method name="performBackup"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="context" type="android.content.Context">
-</parameter>
-<parameter name="oldSnapshot" type="android.os.ParcelFileDescriptor">
-</parameter>
-<parameter name="newSnapshot" type="android.os.ParcelFileDescriptor">
-</parameter>
-<parameter name="data" type="android.backup.BackupDataOutput">
-</parameter>
-<parameter name="files" type="java.lang.String[]">
-</parameter>
-</method>
-</class>
-<class name="SharedPreferencesBackupHelper"
- extends="java.lang.Object"
- abstract="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<constructor name="SharedPreferencesBackupHelper"
- type="android.backup.SharedPreferencesBackupHelper"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</constructor>
-<method name="performBackup"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="context" type="android.content.Context">
-</parameter>
-<parameter name="oldSnapshot" type="android.os.ParcelFileDescriptor">
-</parameter>
-<parameter name="newSnapshot" type="android.os.ParcelFileDescriptor">
-</parameter>
-<parameter name="data" type="android.backup.BackupDataOutput">
-</parameter>
-<parameter name="prefGroups" type="java.lang.String[]">
-</parameter>
-</method>
-</class>
-</package>
 <package name="android.content"
 >
 <class name="AbstractCursorEntityIterator"
diff --git a/core/java/android/appwidget/AppWidgetProvider.java b/core/java/android/appwidget/AppWidgetProvider.java
index 7871fb6..26712a1 100755
--- a/core/java/android/appwidget/AppWidgetProvider.java
+++ b/core/java/android/appwidget/AppWidgetProvider.java
@@ -22,7 +22,7 @@
 import android.os.Bundle;
 
 /**
- * A conveience class to aid in implementing an AppWidget provider.
+ * A convenience class to aid in implementing an AppWidget provider.
  * Everything you can do with AppWidgetProvider, you can do with a regular {@link BroadcastReceiver}.
  * AppWidgetProvider merely parses the relevant fields out of the Intent that is received in
  * {@link #onReceive(Context,Intent) onReceive(Context,Intent)}, and calls hook methods
diff --git a/core/java/android/backup/BackupDataOutput.java b/core/java/android/backup/BackupDataOutput.java
index 6c47f7e..555494e 100644
--- a/core/java/android/backup/BackupDataOutput.java
+++ b/core/java/android/backup/BackupDataOutput.java
@@ -20,6 +20,7 @@
 
 import java.io.FileDescriptor;
 
+/** @hide */
 public class BackupDataOutput {
     /* package */ FileDescriptor fd;
 
diff --git a/core/java/android/backup/BackupService.java b/core/java/android/backup/BackupService.java
index 6ac703a..50a5921 100644
--- a/core/java/android/backup/BackupService.java
+++ b/core/java/android/backup/BackupService.java
@@ -75,9 +75,8 @@
      *                 file.  The application should record the final backup state
      *                 here after writing the requested data to dataFd.
      */
-    public abstract void onBackup(ParcelFileDescriptor oldState,
-            ParcelFileDescriptor data,
-            ParcelFileDescriptor newState);
+    public abstract void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
+             ParcelFileDescriptor newState);
     
     /**
      * The application is being restored from backup, and should replace any
@@ -92,7 +91,7 @@
      *                 file.  The application should record the final backup state
      *                 here after restoring its data from dataFd.
      */
-    public abstract void onRestore(ParcelFileDescriptor data, ParcelFileDescriptor newState);
+    public abstract void onRestore(ParcelFileDescriptor /* TODO: BackupDataInput */ data, ParcelFileDescriptor newState);
 
 
     // ----- Core implementation -----
@@ -117,7 +116,15 @@
                 ParcelFileDescriptor newState) throws RemoteException {
             // !!! TODO - real implementation; for now just invoke the callbacks directly
             Log.v("BackupServiceBinder", "doBackup() invoked");
-            BackupService.this.onBackup(oldState, data, newState);
+            BackupDataOutput output = new BackupDataOutput(BackupService.this,
+                    data.getFileDescriptor());
+            try {
+                BackupService.this.onBackup(oldState, output, newState);
+            } catch (RuntimeException ex) {
+                Log.d("BackupService", "onBackup ("
+                        + BackupService.this.getClass().getName() + ") threw", ex);
+                throw ex;
+            }
         }
 
         public void doRestore(ParcelFileDescriptor data,
diff --git a/core/java/android/backup/FileBackupHelper.java b/core/java/android/backup/FileBackupHelper.java
index 3b2122c..2762f22 100644
--- a/core/java/android/backup/FileBackupHelper.java
+++ b/core/java/android/backup/FileBackupHelper.java
@@ -18,20 +18,24 @@
 
 import android.content.Context;
 import android.os.ParcelFileDescriptor;
+import android.util.Log;
 
 import java.io.FileDescriptor;
 
+/** @hide */
 public class FileBackupHelper {
+    private static final String TAG = "FileBackupHelper";
+
     /**
-     * Based on oldSnapshot, determine which of the files from the application's data directory
-     * need to be backed up, write them to the data stream, and fill in newSnapshot with the
+     * Based on oldState, determine which of the files from the application's data directory
+     * need to be backed up, write them to the data stream, and fill in newState with the
      * state as it exists now.
      */
     public static void performBackup(Context context,
-            ParcelFileDescriptor oldSnapshot, ParcelFileDescriptor newSnapshot,
-            BackupDataOutput data, String[] files) {
+            ParcelFileDescriptor oldState, BackupDataOutput data,
+            ParcelFileDescriptor newState, String[] files) {
         String basePath = context.getFilesDir().getAbsolutePath();
-        performBackup_checked(basePath, oldSnapshot, newSnapshot, data, files);
+        performBackup_checked(basePath, oldState, data, newState, files);
     }
 
     /**
@@ -39,30 +43,34 @@
      * since it's easier to do that from java.
      */
     static void performBackup_checked(String basePath,
-            ParcelFileDescriptor oldSnapshot, ParcelFileDescriptor newSnapshot,
-            BackupDataOutput data, String[] files) {
-        if (newSnapshot == null) {
-            throw new NullPointerException("newSnapshot==null");
+            ParcelFileDescriptor oldState, BackupDataOutput data,
+            ParcelFileDescriptor newState, String[] files) {
+        if (files.length == 0) {
+            return;
         }
-        if (data == null) {
-            throw new NullPointerException("data==null");
+        if (basePath == null) {
+            throw new NullPointerException();
         }
+        // oldStateFd can be null
+        FileDescriptor oldStateFd = oldState != null ? oldState.getFileDescriptor() : null;
         if (data.fd == null) {
-            throw new NullPointerException("data.fd==null");
+            throw new NullPointerException();
+        }
+        FileDescriptor newStateFd = newState.getFileDescriptor();
+        if (newStateFd == null) {
+            throw new NullPointerException();
         }
         if (files == null) {
-            throw new NullPointerException("files==null");
+            throw new NullPointerException();
         }
 
-        int err = performBackup_native(basePath, oldSnapshot.getFileDescriptor(),
-                newSnapshot.getFileDescriptor(), data.fd, files);
+        int err = performBackup_native(basePath, oldStateFd, data.fd, newStateFd, files);
 
         if (err != 0) {
             throw new RuntimeException("Backup failed"); // TODO: more here
         }
     }
 
-    native private static int performBackup_native(String basePath,
-            FileDescriptor oldSnapshot, FileDescriptor newSnapshot,
-            FileDescriptor data, String[] files);
+    native private static int performBackup_native(String basePath, FileDescriptor oldState,
+            FileDescriptor data, FileDescriptor newState, String[] files);
 }
diff --git a/core/java/android/backup/SharedPreferencesBackupHelper.java b/core/java/android/backup/SharedPreferencesBackupHelper.java
index e839bb4..8627f08 100644
--- a/core/java/android/backup/SharedPreferencesBackupHelper.java
+++ b/core/java/android/backup/SharedPreferencesBackupHelper.java
@@ -21,6 +21,7 @@
 
 import java.io.FileDescriptor;
 
+/** @hide */
 public class SharedPreferencesBackupHelper {
     public static void performBackup(Context context,
             ParcelFileDescriptor oldSnapshot, ParcelFileDescriptor newSnapshot,
@@ -34,7 +35,7 @@
             files[i] = prefGroups[i] + ".xml";
         }
 
-        FileBackupHelper.performBackup_checked(basePath, oldSnapshot, newSnapshot, data, files);
+        FileBackupHelper.performBackup_checked(basePath, oldSnapshot, data, newSnapshot, files);
     }
 }
 
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index bb8de29..0e6be0a 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1048,6 +1048,17 @@
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_SEARCH_LONG_PRESS = "android.intent.action.SEARCH_LONG_PRESS";
 
+    /**
+     * Activity Action: The user pressed the "Report" button in the crash/ANR dialog.
+     * This intent is delivered to the package which installed the application, usually
+     * the Market.
+     * <p>Input: No data is specified. The bug report is passed in using
+     * an {@link #EXTRA_BUG_REPORT} field.
+     * <p>Output: Nothing.
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_APP_ERROR = "android.intent.action.APP_ERROR";
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     // Standard intent broadcast actions (see action variable).
@@ -1796,6 +1807,24 @@
      * delivered.
      */
     public static final String EXTRA_ALARM_COUNT = "android.intent.extra.ALARM_COUNT";
+    
+    /**
+     * Used as a parcelable extra field in {@link #ACTION_APP_ERROR}, containing
+     * the bug report.
+     * 
+     * @hide
+     */
+    public static final String EXTRA_BUG_REPORT = "android.intent.extra.BUG_REPORT";
+
+    /**
+     * Used as a string extra field when sending an intent to PackageInstaller to install a 
+     * package. Specifies the installer package name; this package will receive the
+     * {@link #ACTION_APP_ERROR} intent.
+     * 
+     * @hide
+     */
+    public static final String EXTRA_INSTALLER_PACKAGE_NAME 
+            = "android.intent.extra.INSTALLER_PACKAGE_NAME";
 
     /**
      * Used in the extra field in the remote intent. It's astring token passed with the
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index a7de895..ab4ce11 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -30,6 +30,10 @@
 import java.io.Reader;
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 
 import org.apache.harmony.dalvik.ddmc.Chunk;
 import org.apache.harmony.dalvik.ddmc.ChunkHandler;
@@ -876,6 +880,15 @@
 
 
     /**
+     * Equivalent to <code>setFieldsOn(cl, false)</code>.
+     *
+     * @see #setFieldsOn(Class, boolean)
+     */
+    public static void setFieldsOn(Class<?> cl) {
+        setFieldsOn(cl, false);
+    }
+
+    /**
      * Reflectively sets static fields of a class based on internal debugging
      * properties.  This method is a no-op if android.util.Config.DEBUG is
      * false.
@@ -887,7 +900,7 @@
      * Class setup: define a class whose only fields are non-final, static
      * primitive types (except for "char") or Strings.  In a static block
      * after the field definitions/initializations, pass the class to
-     * this method, Debug.setFieldsOn().  Example:
+     * this method, Debug.setFieldsOn(). Example:
      * <pre>
      * package com.example;
      *
@@ -899,12 +912,18 @@
      *    public static String ns = null;
      *    public static boolean b = false;
      *    public static int i = 5;
+     *    @Debug.DebugProperty
      *    public static float f = 0.1f;
+     *    @@Debug.DebugProperty
      *    public static double d = 0.5d;
      *
      *    // This MUST appear AFTER all fields are defined and initialized!
      *    static {
+     *        // Sets all the fields
      *        Debug.setFieldsOn(MyDebugVars.class);
+     * 
+     *        // Sets only the fields annotated with @Debug.DebugProperty
+     *        // Debug.setFieldsOn(MyDebugVars.class, true);
      *    }
      * }
      * </pre>
@@ -917,25 +936,31 @@
      * {@hide}
      *
      * @param cl The class to (possibly) modify
+     * @param partial If false, sets all static fields, otherwise, only set
+     *        fields with the {@link android.os.Debug.DebugProperty}
+     *        annotation
      * @throws IllegalArgumentException if any fields are final or non-static,
      *         or if the type of the field does not match the type of
      *         the internal debugging property value.
      */
-    public static void setFieldsOn(Class<?> cl) {
+    public static void setFieldsOn(Class<?> cl, boolean partial) {
         if (Config.DEBUG) {
             if (debugProperties != null) {
                 /* Only look for fields declared directly by the class,
                  * so we don't mysteriously change static fields in superclasses.
                  */
                 for (Field field : cl.getDeclaredFields()) {
-                    final String propertyName = cl.getName() + "." + field.getName();
-                    boolean isStatic = Modifier.isStatic(field.getModifiers());
-                    boolean isFinal = Modifier.isFinal(field.getModifiers());
-                    if (!isStatic || isFinal) {
-                        throw new IllegalArgumentException(propertyName +
-                            " must be static and non-final");
+                    if (!partial || field.getAnnotation(DebugProperty.class) != null) {
+                        final String propertyName = cl.getName() + "." + field.getName();
+                        boolean isStatic = Modifier.isStatic(field.getModifiers());
+                        boolean isFinal = Modifier.isFinal(field.getModifiers());
+
+                        if (!isStatic || isFinal) {
+                            throw new IllegalArgumentException(propertyName +
+                                " must be static and non-final");
+                        }
+                        modifyFieldIfSet(field, debugProperties, propertyName);
                     }
-                    modifyFieldIfSet(field, debugProperties, propertyName);
                 }
             }
         } else {
@@ -944,4 +969,15 @@
                   ") called in non-DEBUG build");
         }
     }
+
+    /**
+     * Annotation to put on fields you want to set with
+     * {@link Debug#setFieldsOn(Class, boolean)}.
+     *
+     * @hide
+     */
+    @Target({ ElementType.FIELD })
+    @Retention(RetentionPolicy.RUNTIME)
+    public @interface DebugProperty {
+    }
 }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 335b43c..af5dca6 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -49,6 +49,7 @@
 import android.util.Pool;
 import android.util.Pools;
 import android.util.PoolableManager;
+import android.util.Config;
 import android.view.ContextMenu.ContextMenuInfo;
 import android.view.animation.Animation;
 import android.view.inputmethod.InputConnection;
@@ -5641,7 +5642,7 @@
             if (ViewDebug.TRACE_HIERARCHY) {
                 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.BUILD_CACHE);
             }
-            if (ViewRoot.PROFILE_DRAWING) {
+            if (Config.DEBUG && ViewDebug.profileDrawing) {
                 EventLog.writeEvent(60002, hashCode());
             }
 
@@ -7166,6 +7167,60 @@
     }
 
     /**
+     * @param consistency The type of consistency. See ViewDebug for more information.
+     *
+     * @hide
+     */
+    protected boolean dispatchConsistencyCheck(int consistency) {
+        return onConsistencyCheck(consistency);
+    }
+
+    /**
+     * Method that subclasses should implement to check their consistency. The type of
+     * consistency check is indicated by the bit field passed as a parameter.
+     * 
+     * @param consistency The type of consistency. See ViewDebug for more information.
+     *
+     * @throws IllegalStateException if the view is in an inconsistent state.
+     *
+     * @hide
+     */
+    protected boolean onConsistencyCheck(int consistency) {
+        boolean result = true;
+
+        final boolean checkLayout = (consistency & ViewDebug.CONSISTENCY_LAYOUT) != 0;
+        final boolean checkDrawing = (consistency & ViewDebug.CONSISTENCY_DRAWING) != 0;
+
+        if (checkLayout) {
+            if (getParent() == null) {
+                result = false;
+                android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
+                        "View " + this + " does not have a parent.");
+            }
+
+            if (mAttachInfo == null) {
+                result = false;
+                android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
+                        "View " + this + " is not attached to a window.");
+            }
+        }
+
+        if (checkDrawing) {
+            // Do not check the DIRTY/DRAWN flags because views can call invalidate()
+            // from their draw() method
+
+            if ((mPrivateFlags & DRAWN) != DRAWN &&
+                    (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) {
+                result = false;
+                android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
+                        "View " + this + " was invalidated but its drawing cache is valid.");
+            }
+        }
+
+        return result;
+    }
+
+    /**
      * Prints information about this view in the log output, with the tag
      * {@link #VIEW_LOG_TAG}.
      *
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index 367c9a2..4436f4b 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -54,6 +54,27 @@
  */
 public class ViewDebug {
     /**
+     * Log tag used to log errors related to the consistency of the view hierarchy.
+     *
+     * @hide
+     */
+    public static final String CONSISTENCY_LOG_TAG = "ViewConsistency";
+
+    /**
+     * Flag indicating the consistency check should check layout-related properties.
+     *
+     * @hide
+     */
+    public static final int CONSISTENCY_LAYOUT = 0x1;
+
+    /**
+     * Flag indicating the consistency check should check drawing-related properties.
+     *
+     * @hide
+     */
+    public static final int CONSISTENCY_DRAWING = 0x2;
+
+    /**
      * Enables or disables view hierarchy tracing. Any invoker of
      * {@link #trace(View, android.view.ViewDebug.HierarchyTraceType)} should first
      * check that this value is set to true as not to affect performance.
@@ -80,6 +101,49 @@
     static final String SYSTEM_PROPERTY_CAPTURE_EVENT = "debug.captureevent";
 
     /**
+     * Profiles drawing times in the events log.
+     *
+     * @hide
+     */
+    @Debug.DebugProperty
+    public static boolean profileDrawing = false;
+
+    /**
+     * Profiles layout times in the events log.
+     *
+     * @hide
+     */
+    @Debug.DebugProperty
+    public static boolean profileLayout = false;
+
+    /**
+     * Profiles real fps (times between draws) and displays the result.
+     *
+     * @hide
+     */
+    @Debug.DebugProperty
+    public static boolean showFps = false;
+
+    /**
+     * <p>Enables or disables views consistency check. Even when this property is enabled,
+     * view consistency checks happen only if {@link android.util.Config#DEBUG} is set
+     * to true. The value of this property can be configured externally in one of the
+     * following files:</p>
+     * <ul>
+     *  <li>/system/debug.prop</li>
+     *  <li>/debug.prop</li>
+     *  <li>/data/debug.prop</li>
+     * </ul>
+     * @hide
+     */
+    @Debug.DebugProperty
+    public static boolean consistencyCheckEnabled = false;
+
+    static {
+        Debug.setFieldsOn(ViewDebug.class, true);
+    }
+
+    /**
      * This annotation can be used to mark fields and methods to be dumped by
      * the view server. Only non-void methods with no arguments can be annotated
      * by this annotation.
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 31159d7..26fe776 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -32,6 +32,7 @@
 import android.util.EventLog;
 import android.util.Log;
 import android.util.SparseArray;
+import android.util.Config;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
 import android.view.animation.LayoutAnimationController;
@@ -1404,7 +1405,7 @@
 
         // Clear the flag as early as possible to allow draw() implementations
         // to call invalidate() successfully when doing animations
-        child.mPrivateFlags |= DRAWN;
+        child.mPrivateFlags = (child.mPrivateFlags & ~DIRTY_MASK) | DRAWN;
 
         if (!concatMatrix && canvas.quickReject(cl, ct, cr, cb, Canvas.EdgeType.BW) &&
                 (child.mPrivateFlags & DRAW_ANIMATION) == 0) {
@@ -1494,7 +1495,7 @@
                 cachePaint.setAlpha(255);
                 mGroupFlags &= ~FLAG_ALPHA_LOWER_THAN_ONE;
             }
-            if (ViewRoot.PROFILE_DRAWING) {
+            if (Config.DEBUG && ViewDebug.profileDrawing) {
                 EventLog.writeEvent(60003, hashCode());
             }
             canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
@@ -2750,6 +2751,61 @@
     }
 
     /**
+     * @hide
+     */
+    @Override
+    protected boolean dispatchConsistencyCheck(int consistency) {
+        boolean result = super.dispatchConsistencyCheck(consistency);
+
+        final int count = mChildrenCount;
+        final View[] children = mChildren;
+        for (int i = 0; i < count; i++) {
+            if (!children[i].dispatchConsistencyCheck(consistency)) result = false;
+        }
+
+        return result;
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    protected boolean onConsistencyCheck(int consistency) {
+        boolean result = super.onConsistencyCheck(consistency);
+
+        final boolean checkLayout = (consistency & ViewDebug.CONSISTENCY_LAYOUT) != 0;
+        final boolean checkDrawing = (consistency & ViewDebug.CONSISTENCY_DRAWING) != 0;
+
+        if (checkLayout) {
+            final int count = mChildrenCount;
+            final View[] children = mChildren;
+            for (int i = 0; i < count; i++) {
+                if (children[i].getParent() != this) {
+                    result = false;
+                    android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
+                            "View " + children[i] + " has no parent/a parent that is not " + this);
+                }
+            }
+        }
+
+        if (checkDrawing) {
+            // If this group is dirty, check that the parent is dirty as well
+            if ((mPrivateFlags & DIRTY_MASK) != 0) {
+                final ViewParent parent = getParent();
+                if (parent != null && !(parent instanceof ViewRoot)) {
+                    if ((((View) parent).mPrivateFlags & DIRTY_MASK) == 0) {
+                        result = false;
+                        android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
+                                "ViewGroup " + this + " is dirty but its parent is not: " + this);
+                    }
+                }
+            }
+        }
+
+        return result;
+    }
+
+    /**
      * {@inheritDoc}
      */
     @Override
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 8494d5e..90453ba 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -75,13 +75,6 @@
     private static final boolean DEBUG_IMF = false || LOCAL_LOGV;
     private static final boolean WATCH_POINTER = false;
 
-    static final boolean PROFILE_DRAWING = false;
-    private static final boolean PROFILE_LAYOUT = false;
-    // profiles real fps (times between draws) and displays the result
-    private static final boolean SHOW_FPS = false;
-    // used by SHOW_FPS
-    private static int sDrawTime;
-
     /**
      * Maximum time we allow the user to roll the trackball enough to generate
      * a key event, before resetting the counters.
@@ -97,6 +90,8 @@
 
     static final ThreadLocal<RunQueue> sRunQueues = new ThreadLocal<RunQueue>();
 
+    private static int sDrawTime;    
+
     long mLastTrackballTime = 0;
     final TrackballAxis mTrackballAxisX = new TrackballAxis();
     final TrackballAxis mTrackballAxisY = new TrackballAxis();
@@ -796,7 +791,7 @@
             final Rect frame = mWinFrame;
             boolean initialized = false;
             boolean contentInsetsChanged = false;
-            boolean visibleInsetsChanged = false;
+            boolean visibleInsetsChanged;
             try {
                 boolean hadSurface = mSurface.isValid();
                 int fl = 0;
@@ -937,14 +932,22 @@
             if (DEBUG_ORIENTATION || DEBUG_LAYOUT) Log.v(
                 "ViewRoot", "Laying out " + host + " to (" +
                 host.mMeasuredWidth + ", " + host.mMeasuredHeight + ")");
-            long startTime;
-            if (PROFILE_LAYOUT) {
+            long startTime = 0L;
+            if (Config.DEBUG && ViewDebug.profileLayout) {
                 startTime = SystemClock.elapsedRealtime();
             }
 
             host.layout(0, 0, host.mMeasuredWidth, host.mMeasuredHeight);
 
-            if (PROFILE_LAYOUT) {
+            if (Config.DEBUG && ViewDebug.consistencyCheckEnabled) {
+                if (!host.dispatchConsistencyCheck(ViewDebug.CONSISTENCY_LAYOUT)) {
+                    throw new IllegalStateException("The view hierarchy is an inconsistent state,"
+                            + "please refer to the logs with the tag "
+                            + ViewDebug.CONSISTENCY_LOG_TAG + " for more infomation.");
+                }
+            }
+
+            if (Config.DEBUG && ViewDebug.profileLayout) {
                 EventLog.writeEvent(60001, SystemClock.elapsedRealtime() - startTime);
             }
 
@@ -960,10 +963,11 @@
                         mTmpLocation[1] + host.mBottom - host.mTop);
 
                 host.gatherTransparentRegion(mTransparentRegion);
-                if (mAppScale != 1.0f) {
-                    mTransparentRegion.scale(mAppScale);
-                }
 
+                // TODO: scale the region, like:
+                // Region uses native methods. We probabl should have ScalableRegion class.
+
+                // Region does not have equals method ?
                 if (!mTransparentRegion.equals(mPreviousTransparentRegion)) {
                     mPreviousTransparentRegion.set(mTransparentRegion);
                     // reconfigure window manager
@@ -1168,6 +1172,9 @@
                             canvas.scale(scale, scale);
                         }
                         mView.draw(canvas);
+                        if (Config.DEBUG && ViewDebug.consistencyCheckEnabled) {
+                            mView.dispatchConsistencyCheck(ViewDebug.CONSISTENCY_DRAWING);
+                        }
                     } finally {
                         canvas.restoreToCount(saveCount);
                     }
@@ -1175,7 +1182,7 @@
                     mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);
                     checkEglErrors();
 
-                    if (SHOW_FPS) {
+                    if (Config.DEBUG && ViewDebug.showFps) {
                         int now = (int)SystemClock.elapsedRealtime();
                         if (sDrawTime != 0) {
                             nativeShowFPS(canvas, now - sDrawTime);
@@ -1216,7 +1223,7 @@
 
         try {
             if (!dirty.isEmpty() || mIsAnimating) {
-                long startTime;
+                long startTime = 0L;
 
                 if (DEBUG_ORIENTATION || DEBUG_DRAW) {
                     Log.v("ViewRoot", "Surface " + surface + " drawing to bitmap w="
@@ -1224,7 +1231,7 @@
                     //canvas.drawARGB(255, 255, 0, 0);
                 }
 
-                if (PROFILE_DRAWING) {
+                if (Config.DEBUG && ViewDebug.profileDrawing) {
                     startTime = SystemClock.elapsedRealtime();
                 }
 
@@ -1259,11 +1266,15 @@
                         canvas.scale(scale, scale);
                     }
                     mView.draw(canvas);
+
+                    if (Config.DEBUG && ViewDebug.consistencyCheckEnabled) {
+                        mView.dispatchConsistencyCheck(ViewDebug.CONSISTENCY_DRAWING);
+                    }
                 } finally {
                     canvas.restoreToCount(saveCount);
                 }
 
-                if (SHOW_FPS) {
+                if (Config.DEBUG && ViewDebug.showFps) {
                     int now = (int)SystemClock.elapsedRealtime();
                     if (sDrawTime != 0) {
                         nativeShowFPS(canvas, now - sDrawTime);
@@ -1271,7 +1282,7 @@
                     sDrawTime = now;
                 }
 
-                if (PROFILE_DRAWING) {
+                if (Config.DEBUG && ViewDebug.profileDrawing) {
                     EventLog.writeEvent(60000, SystemClock.elapsedRealtime() - startTime);
                 }
             }
@@ -1878,6 +1889,9 @@
         } else {
             didFinish = false;
         }
+        if (event != null) {
+            event.scale(mAppScaleInverted);
+        }
 
         if (DEBUG_TRACKBALL) Log.v(TAG, "Motion event:" + event);
 
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 4f503b4..1ca59b2 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -3190,7 +3190,7 @@
         // Reclaim views on screen
         for (int i = 0; i < childCount; i++) {
             View child = getChildAt(i);
-            AbsListView.LayoutParams lp = (AbsListView.LayoutParams)child.getLayoutParams();
+            AbsListView.LayoutParams lp = (AbsListView.LayoutParams) child.getLayoutParams();
             // Don't reclaim header or footer views, or views that should be ignored
             if (lp != null && mRecycler.shouldRecycleViewType(lp.viewType)) {
                 views.add(child);
@@ -3205,6 +3205,63 @@
     }
 
     /**
+     * @hide
+     */
+    @Override
+    protected boolean onConsistencyCheck(int consistency) {
+        boolean result = super.onConsistencyCheck(consistency);
+
+        final boolean checkLayout = (consistency & ViewDebug.CONSISTENCY_LAYOUT) != 0;
+
+        if (checkLayout) {
+            // The active recycler must be empty
+            final View[] activeViews = mRecycler.mActiveViews;
+            int count = activeViews.length;
+            for (int i = 0; i < count; i++) {
+                if (activeViews[i] != null) {
+                    result = false;
+                    android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
+                            "AbsListView " + this + " has a view in its active recycler: " +
+                                    activeViews[i]);
+                }
+            }
+
+            // All views in the recycler must NOT be on screen and must NOT have a parent
+            final ArrayList<View> scrap = mRecycler.mCurrentScrap;
+            if (!checkScrap(scrap)) result = false;
+            final ArrayList<View>[] scraps = mRecycler.mScrapViews;
+            count = scraps.length;
+            for (int i = 0; i < count; i++) {
+                if (!checkScrap(scraps[i])) result = false;
+            }
+        }
+
+        return result;
+    }
+
+    private boolean checkScrap(ArrayList<View> scrap) {
+        if (scrap == null) return true;
+        boolean result = true;
+
+        final int count = scrap.size();
+        for (int i = 0; i < count; i++) {
+            final View view = scrap.get(i);
+            if (view.getParent() != null) {
+                result = false;
+                android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG, "AbsListView " + this +
+                        " has a view in its scrap heap still attached to a parent: " + view);
+            }
+            if (indexOfChild(view) >= 0) {
+                result = false;
+                android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG, "AbsListView " + this +
+                        " has a view in its scrap heap that is also a direct child: " + view);
+            }
+        }
+
+        return result;
+    }
+
+    /**
      * Sets the recycler listener to be notified whenever a View is set aside in
      * the recycler for later reuse. This listener can be used to free resources
      * associated to the View.
diff --git a/core/jni/android_backup_FileBackupHelper.cpp b/core/jni/android_backup_FileBackupHelper.cpp
index e8d60a0..c6de3a5 100644
--- a/core/jni/android_backup_FileBackupHelper.cpp
+++ b/core/jni/android_backup_FileBackupHelper.cpp
@@ -14,6 +14,9 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "FileBackupHelper_native"
+#include <utils/Log.h>
+
 #include "JNIHelp.h"
 #include <android_runtime/AndroidRuntime.h>
 
@@ -22,29 +25,29 @@
 namespace android
 {
 
-static jfieldID s_descriptorField;
+static jfieldID s_descriptorField = 0;
 
 static int
-performBackup_native(JNIEnv* env, jstring basePath,
-            jobject oldSnapshot, jobject newSnapshot,
-            jobject data, jobjectArray files)
+performBackup_native(JNIEnv* env, jobject clazz, jstring basePath, jobject oldState, jobject data,
+        jobject newState, jobjectArray files)
 {
     int err;
 
     // all parameters have already been checked against null
-
-    int oldSnapshotFD = env->GetIntField(oldSnapshot, s_descriptorField);
-    int newSnapshotFD = env->GetIntField(newSnapshot, s_descriptorField);
+    LOGD("oldState=%p newState=%p data=%p\n", oldState, newState, data);
+    int oldStateFD = oldState != NULL ? env->GetIntField(oldState, s_descriptorField) : -1;
+    int newStateFD = env->GetIntField(newState, s_descriptorField);
     int dataFD = env->GetIntField(data, s_descriptorField);
 
     char const* basePathUTF = env->GetStringUTFChars(basePath, NULL);
+    LOGD("basePathUTF=\"%s\"\n", basePathUTF);
     const int fileCount = env->GetArrayLength(files);
     char const** filesUTF = (char const**)malloc(sizeof(char*)*fileCount);
     for (int i=0; i<fileCount; i++) {
         filesUTF[i] = env->GetStringUTFChars((jstring)env->GetObjectArrayElement(files, i), NULL);
     }
 
-    err = back_up_files(oldSnapshotFD, newSnapshotFD, dataFD, basePathUTF, filesUTF, fileCount);
+    err = back_up_files(oldStateFD, dataFD, newStateFD, basePathUTF, filesUTF, fileCount);
 
     for (int i=0; i<fileCount; i++) {
         env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(files, i), filesUTF[i]);
@@ -64,6 +67,8 @@
 
 int register_android_backup_FileBackupHelper(JNIEnv* env)
 {
+    LOGD("register_android_backup_FileBackupHelper");
+
     jclass clazz;
 
     clazz = env->FindClass("java/io/FileDescriptor");
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 0b398bc..fda584d 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -400,7 +400,7 @@
      * @param y        The y coordinate of the first pixel in source
      * @param width    The number of pixels in each row
      * @param height   The number of rows
-     * @param m        Option matrix to be applied to the pixels
+     * @param m        Optional matrix to be applied to the pixels
      * @param filter   true if the source should be filtered.
      *                   Only applies if the matrix contains more than just
      *                   translation.
diff --git a/include/utils/backup_helpers.h b/include/utils/backup_helpers.h
index 61bee340..137c5f1 100644
--- a/include/utils/backup_helpers.h
+++ b/include/utils/backup_helpers.h
@@ -1,7 +1,7 @@
 #ifndef _UTILS_BACKUP_HELPERS_H
 #define _UTILS_BACKUP_HELPERS_H
 
-int back_up_files(int oldSnapshotFD, int newSnapshotFD, int oldDataStream,
+int back_up_files(int oldSnapshotFD, int oldDataStream, int newSnapshotFD,
         char const* fileBase, char const* const* files, int fileCount);
 
 #define TEST_BACKUP_HELPERS 0
diff --git a/libs/utils/file_backup_helper.cpp b/libs/utils/file_backup_helper.cpp
index 111f88d..453084a 100644
--- a/libs/utils/file_backup_helper.cpp
+++ b/libs/utils/file_backup_helper.cpp
@@ -24,6 +24,9 @@
 #define MAGIC0 0x70616e53 // Snap
 #define MAGIC1 0x656c6946 // File
 
+#define LOGP(x...) LOGD(x)
+//#define LOGP(x...) printf(x)
+
 struct SnapshotHeader {
     int magic0;
     int fileCount;
@@ -159,14 +162,14 @@
 static int
 write_delete_file(const String8& key)
 {
-    printf("write_delete_file %s\n", key.string());
+    LOGP("write_delete_file %s\n", key.string());
     return 0;
 }
 
 static int
 write_update_file(const String8& realFilename, const String8& key)
 {
-    printf("write_update_file %s (%s)\n", realFilename.string(), key.string());
+    LOGP("write_update_file %s (%s)\n", realFilename.string(), key.string());
     return 0;
 }
 
@@ -195,7 +198,7 @@
 }
 
 int
-back_up_files(int oldSnapshotFD, int newSnapshotFD, int oldDataStream,
+back_up_files(int oldSnapshotFD, int oldDataStream, int newSnapshotFD,
         char const* fileBase, char const* const* files, int fileCount)
 {
     int err;
@@ -260,10 +263,10 @@
             const FileState& f = oldSnapshot.valueAt(n);
             const FileState& g = newSnapshot.valueAt(m);
 
-            printf("%s\n", q.string());
-            printf("  new: modTime=%d,%d size=%-3d crc32=0x%08x\n",
+            LOGP("%s\n", q.string());
+            LOGP("  new: modTime=%d,%d size=%-3d crc32=0x%08x\n",
                     f.modTime_sec, f.modTime_nsec, f.size, f.crc32);
-            printf("  old: modTime=%d,%d size=%-3d crc32=0x%08x\n",
+            LOGP("  old: modTime=%d,%d size=%-3d crc32=0x%08x\n",
                     g.modTime_sec, g.modTime_nsec, g.size, g.crc32);
             if (f.modTime_sec != g.modTime_sec || f.modTime_nsec != g.modTime_nsec
                     || f.size != g.size || f.crc32 != g.crc32) {
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index db1deae..983329b 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -220,6 +220,9 @@
 
             BackupRequest request;
             synchronized (mQueueLock) {
+                if (mBackupQueue == null) {
+                    Log.d(TAG, "mBackupQueue is null.  WHY?");
+                }
                 request = mBackupQueue.get(0);
             }
 
diff --git a/services/java/com/android/server/status/IconMerger.java b/services/java/com/android/server/status/IconMerger.java
index 37fdbfb..5b80638 100644
--- a/services/java/com/android/server/status/IconMerger.java
+++ b/services/java/com/android/server/status/IconMerger.java
@@ -8,8 +8,6 @@
 
 
 public class IconMerger extends LinearLayout {
-    private static final boolean SPEW = false;
-
     StatusBarService service;
     StatusBarIcon moreIcon;
 
@@ -29,7 +27,7 @@
         int fitRight = -1;
         for (i=N-1; i>=0; i--) {
             final View child = getChildAt(i);
-            if (child != null && child.getVisibility() != GONE) {
+            if (child.getVisibility() != GONE) {
                 fitRight = child.getRight();
                 break;
             }
@@ -45,7 +43,7 @@
                 moreView = child;
                 startIndex = i+1;
             }
-            else if (child != null && child.getVisibility() != GONE) {
+            else if (child.getVisibility() != GONE) {
                 fitLeft = child.getLeft();
                 break;
             }
@@ -71,7 +69,7 @@
         int number = 0;
         for (i=startIndex; i<N; i++) {
             final View child = getChildAt(i);
-            if (child != null && child.getVisibility() != GONE) {
+            if (child.getVisibility() != GONE) {
                 int childLeft = child.getLeft();
                 int childRight = child.getRight();
                 if (childLeft < breakingPoint) {
diff --git a/tests/backup/src/com/android/backuptest/BackupTestActivity.java b/tests/backup/src/com/android/backuptest/BackupTestActivity.java
index de68cb7..af7dfd4 100644
--- a/tests/backup/src/com/android/backuptest/BackupTestActivity.java
+++ b/tests/backup/src/com/android/backuptest/BackupTestActivity.java
@@ -83,6 +83,27 @@
                 bm.dataChanged();
             }
         },
+        new Test("Clear File") {
+            void run() {
+                PrintStream output = null;
+                try {
+                    output = new PrintStream(openFileOutput(FILE_NAME, MODE_PRIVATE));
+                    output.close();
+                } catch (IOException ex) {
+                    if (output != null) {
+                        output.close();
+                    }
+                }
+                BackupManager bm = new BackupManager(BackupTestActivity.this);
+                bm.dataChanged();
+            }
+        },
+        new Test("Poke") {
+            void run() {
+                BackupManager bm = new BackupManager(BackupTestActivity.this);
+                bm.dataChanged();
+            }
+        },
         new Test("Show Shared Pref") {
             void run() {
                 SharedPreferences prefs = getSharedPreferences(PREF_GROUP_SETTINGS, MODE_PRIVATE);
diff --git a/tests/backup/src/com/android/backuptest/BackupTestService.java b/tests/backup/src/com/android/backuptest/BackupTestService.java
index c58c98b..00eb86e 100644
--- a/tests/backup/src/com/android/backuptest/BackupTestService.java
+++ b/tests/backup/src/com/android/backuptest/BackupTestService.java
@@ -17,6 +17,8 @@
 package com.android.backuptest;
 
 import android.backup.BackupService;
+import android.backup.BackupDataOutput;
+import android.backup.FileBackupHelper;
 import android.os.ParcelFileDescriptor;
 import android.util.Log;
 
@@ -25,10 +27,12 @@
     static final String TAG = "BackupTestService";
 
     @Override
-    public void onBackup(ParcelFileDescriptor oldState,
-            ParcelFileDescriptor data,
-            ParcelFileDescriptor newState) {
+    public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
+             ParcelFileDescriptor newState) {
         Log.d(TAG, "onBackup");
+        FileBackupHelper.performBackup(this, oldState, data, newState, new String[] {
+                    BackupTestActivity.FILE_NAME
+                });
     }
 
     @Override