Merge change 20787

* changes:
  Removing primary/default phone number and email on contact from the API.
diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
index 6b6d3c9..8c15d0b 100644
--- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
+++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
@@ -315,8 +315,7 @@
                 for (RestoreSet s : sets) {
                     if (s.token == token) {
                         System.out.println("Scheduling restore: " + s.name);
-                        mRestore.performRestore(token, observer);
-                        didRestore = true;
+                        didRestore = (mRestore.performRestore(token, observer) == 0);
                         break;
                     }
                 }
@@ -330,12 +329,15 @@
                 }
             }
 
-            // now wait for it to be done
-            synchronized (observer) {
-                while (!observer.done) {
-                    try {
-                        observer.wait();
-                    } catch (InterruptedException ex) {
+            // if we kicked off a restore successfully, we have to wait for it
+            // to complete before we can shut down the restore session safely
+            if (didRestore) {
+                synchronized (observer) {
+                    while (!observer.done) {
+                        try {
+                            observer.wait();
+                        } catch (InterruptedException ex) {
+                        }
                     }
                 }
             }
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 9c20a4b..b75bec2 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -67,6 +67,7 @@
 import android.widget.ImageView;
 import android.widget.ListView;
 import android.widget.TextView;
+import android.widget.ListAdapter;
 import android.widget.AdapterView.OnItemClickListener;
 import android.widget.AdapterView.OnItemSelectedListener;
 
@@ -1750,7 +1751,7 @@
                 // case we want to dismiss the soft keyboard so the user can see the rest of the
                 // shortcuts.
                 if (isInputMethodNotNeeded() ||
-                        (isEmpty() && getDropDownChildCount() >= getAdapter().getCount())) {
+                        (isEmpty() && getDropDownChildCount() >= getAdapterCount())) {
                     mSearchDialog.cancel();
                     return true;
                 }
@@ -1758,6 +1759,11 @@
             }
             return false;
         }
+
+        private int getAdapterCount() {
+            final ListAdapter adapter = getAdapter();
+            return adapter == null ? 0 : adapter.getCount();
+        }
     }
     
     protected boolean handleBackKey(int keyCode, KeyEvent event) {
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index fd559d6..7ad6423 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -40,7 +40,7 @@
  * methods and the the {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH}
  * {@link android.content.Intent Intent}.  This class does provide a basic
  * overview of search services and how to integrate them with your activities.
- * If you do require direct access to the Search Manager, do not instantiate 
+ * If you do require direct access to the SearchManager, do not instantiate 
  * this class directly; instead, retrieve it through
  * {@link android.content.Context#getSystemService
  * context.getSystemService(Context.SEARCH_SERVICE)}.
@@ -49,9 +49,10 @@
  * <ol>
  * <li><a href="#DeveloperGuide">Developer Guide</a>
  * <li><a href="#HowSearchIsInvoked">How Search Is Invoked</a>
- * <li><a href="#QuerySearchApplications">Query-Search Applications</a>
- * <li><a href="#FilterSearchApplications">Filter-Search Applications</a>
+ * <li><a href="#ImplementingSearchForYourApp">Implementing Search for Your App</a>
  * <li><a href="#Suggestions">Search Suggestions</a>
+ * <li><a href="#ExposingSearchSuggestionsToQuickSearchBox">Exposing Search Suggestions to
+ * Quick Search Box</a></li>
  * <li><a href="#ActionKeys">Action Keys</a>
  * <li><a href="#SearchabilityMetadata">Searchability Metadata</a>
  * <li><a href="#PassingSearchContext">Passing Search Context</a>
@@ -62,37 +63,18 @@
  * <h3>Developer Guide</h3>
  * 
  * <p>The ability to search for user, system, or network based data is considered to be
- * a core user-level feature of the android platform.  At any time, the user should be
+ * a core user-level feature of the Android platform.  At any time, the user should be
  * able to use a familiar command, button, or keystroke to invoke search, and the user
- * should be able to search any data which is available to them.  The goal is to make search 
- * appear to the user as a seamless, system-wide feature.
+ * should be able to search any data which is available to them.
  * 
- * <p>In terms of implementation, there are three broad classes of Applications:
- * <ol>
- * <li>Applications that are not inherently searchable</li>
- * <li>Query-Search Applications</li>
- * <li>Filter-Search Applications</li>
- * </ol>
- * <p>These categories, as well as related topics, are discussed in
- * the sections below.
+ * <p>To make search appear to the user as a seamless system-wide feature, the application
+ * framework centrally controls it, offering APIs to individual applications to control how they
+ * are searched. Applications can customize how search is invoked, how the search dialog looks,
+ * and what type of search results are available, including suggestions that are available as the
+ * user types.
  *
- * <p>Even if your application is not <i>searchable</i>, it can still support the invocation of
- * search.  Please review the section <a href="#HowSearchIsInvoked">How Search Is Invoked</a>
- * for more information on how to support this.
- * 
- * <p>Many applications are <i>searchable</i>.  These are 
- * the applications which can convert a query string into a list of results.  
- * Within this subset, applications can be grouped loosely into two families:  
- * <ul><li><i>Query Search</i> applications perform batch-mode searches - each query string is 
- * converted to a list of results.</li>
- * <li><i>Filter Search</i> applications provide live filter-as-you-type searches.</li></ul>
- * <p>Generally speaking, you would use query search for network-based data, and filter 
- * search for local data, but this is not a hard requirement and applications 
- * are free to use the model that fits them best (or invent a new model).
- * <p>It should be clear that the search implementation decouples "search 
- * invocation" from "searchable".  This satisfies the goal of making search appear
- * to be "universal".  The user should be able to launch any search from 
- * almost any context.
+ * <p>Even applications which are not searchable will by default support the invocation of
+ * search to trigger Quick Search Box, the system's 'global search'.
  * 
  * <a name="HowSearchIsInvoked"></a>
  * <h3>How Search Is Invoked</h3>
@@ -100,14 +82,15 @@
  * <p>Unless impossible or inapplicable, all applications should support
  * invoking the search UI.  This means that when the user invokes the search command, 
  * a search UI will be presented to them.  The search command is currently defined as a menu
- * item called "Search" (with an alphabetic shortcut key of "S"), or on some devices, a dedicated
+ * item called "Search" (with an alphabetic shortcut key of "S"), or on many devices, a dedicated
  * search button key.
- * <p>If your application is not inherently searchable, you can also allow the search UI
- * to be invoked in a "web search" mode.  If the user enters a search term and clicks the 
- * "Search" button, this will bring the browser to the front and will launch a web-based
+ * <p>If your application is not inherently searchable, the default implementation will cause
+ * the search UI to be invoked in a "global search" mode known as Quick Search Box.  As the user
+ * types, search suggestions from across the device and the web will be surfaced, and if they
+ * click the "Search" button, this will bring the browser to the front and will launch a web-based
  * search.  The user will be able to click the "Back" button and return to your application.
  * <p>In general this is implemented by your activity, or the {@link android.app.Activity Activity}
- * base class, which captures the search command and invokes the Search Manager to 
+ * base class, which captures the search command and invokes the SearchManager to 
  * display and operate the search UI.  You can also cause the search UI to be presented in response
  * to user keystrokes in your activity (for example, to instantly start filter searching while
  * viewing a list and typing any key).
@@ -124,7 +107,7 @@
  * button or menu item - and invoking the search UI directly.</li>
  * <li>You can provide a <i>type-to-search</i> feature, in which search is invoked automatically
  * when the user enters any characters.</li>
- * <li>Even if your application is not inherently searchable, you can allow web search, 
+ * <li>Even if your application is not inherently searchable, you can allow global search, 
  * via the search key (or even via a search menu item).
  * <li>You can disable search entirely.  This should only be used in very rare circumstances,
  * as search is a system-wide feature and users will expect it to be available in all contexts.</li>
@@ -148,21 +131,23 @@
  * setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);   // search within your activity
  * setDefaultKeyMode(DEFAULT_KEYS_SEARCH_GLOBAL);  // search using platform global search</pre>
  * 
- * <p><b>How to enable web-based search.</b>  In addition to searching within your activity or
- * application, you can also use the Search Manager to invoke a platform-global search, typically
- * a web search.  There are two ways to do this:
+ * <p><b>How to enable global search with Quick Search Box.</b>  In addition to searching within
+ * your activity or application, you can also use the Search Manager to invoke a platform-global
+ * search, which uses Quick Search Box to search across the device and the web. There are two ways
+ * to do this:
  * <ul><li>You can simply define "search" within your application or activity to mean global search.
  * This is described in more detail in the 
  * <a href="#SearchabilityMetadata">Searchability Metadata</a> section.  Briefly, you will
  * add a single meta-data entry to your manifest, declaring that the default search
  * for your application is "*".  This indicates to the system that no application-specific
  * search activity is provided, and that it should launch web-based search instead.</li>
- * <li>You can specify this at invocation time via default keys (see above), overriding
- * {@link android.app.Activity#onSearchRequested}, or via a direct call to 
- * {@link android.app.Activity#startSearch}.  This is most useful if you wish to provide local
- * searchability <i>and</i> access to global search.</li></ul> 
+ * <li>Simply do nothing and the default implementation of
+ * {@link android.app.Activity#onSearchRequested} will cause global search to be triggered.
+ * (You can also always trigger search via a direct call to {@link android.app.Activity#startSearch}.
+ * This is most useful if you wish to provide local searchability <i>and</i> access to global
+ * search.)</li></ul> 
  * 
- * <p><b>How to disable search from your activity.</b>  search is a system-wide feature and users
+ * <p><b>How to disable search from your activity.</b> Search is a system-wide feature and users
  * will expect it to be available in all contexts.  If your UI design absolutely precludes
  * launching search, override {@link android.app.Activity#onSearchRequested onSearchRequested}
  * as shown:
@@ -172,7 +157,7 @@
  *    return false;
  * }</pre> 
  * 
- * <p><b>Managing focus and knowing if Search is active.</b>  The search UI is not a separate
+ * <p><b>Managing focus and knowing if search is active.</b>  The search UI is not a separate
  * activity, and when the UI is invoked or dismissed, your activity will not typically be paused,
  * resumed, or otherwise notified by the methods defined in 
  * <a href="{@docRoot}guide/topics/fundamentals.html#actlife">Application Fundamentals: 
@@ -194,17 +179,10 @@
  * the search UI.  More details on searchable activities and search intents are provided in the
  * sections below.
  *
- * <a name="QuerySearchApplications"></a>
- * <h3>Query-Search Applications</h3>
- * 
- * <p>Query-search applications are those that take a single query (e.g. a search
- * string) and present a set of results that may fit.  Primary examples include
- * web queries, map lookups, or email searches (with the common thread being
- * network query dispatch).  It may also be the case that certain local searches
- * are treated this way.  It's up to the application to decide.
+ * <a name="ImplementingSearchForYourApp"></a>
+ * <h3>Implementing Search for Your App</h3>
  *
- * <p><b>What you need to do:</b>  The following steps are necessary in order to
- * implement query search.
+ * <p>The following steps are necessary in order to implement search.
  * <ul>
  * <li>Implement search invocation as described above.  (Strictly speaking, 
  * these are decoupled, but it would make little sense to be "searchable" but not 
@@ -220,16 +198,16 @@
  * {@link #QUERY getStringExtra(SearchManager.QUERY)}.</li>
  * <li>To identify and support your searchable activity, you'll need to 
  * provide an XML file providing searchability configuration parameters, a reference to that 
- * in your searchable activity's <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest</a>
- * entry, and an intent-filter declaring that you can 
- * receive ACTION_SEARCH intents.  This is described in more detail in the 
- * <a href="#SearchabilityMetadata">Searchability Metadata</a> section.</li>
- * <li>Your <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest</a> also needs a metadata entry
- * providing a global reference to the searchable activity.  This is the "glue" directing the search
- * UI, when invoked from any of your <i>other</i> activities, to use your application as the
- * default search context.  This is also described in more detail in the 
+ * in your searchable activity's
+ * <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest</a> entry, and an
+ * intent-filter declaring that you can receive ACTION_SEARCH intents. This is described in more
+ * detail in the <a href="#SearchabilityMetadata">Searchability Metadata</a> section.</li>
+ * <li>Your <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest</a> also needs a
+ * metadata entry providing a global reference to the searchable activity. This is the "glue"
+ * directing the search UI, when invoked from any of your <i>other</i> activities, to use your
+ * application as the default search context.  This is also described in more detail in the 
  * <a href="#SearchabilityMetadata">Searchability Metadata</a> section.</li> 
- * <li>Finally, you may want to define your search results activity as with the 
+ * <li>Finally, you may want to define your search results activity as single-top with the 
  * {@link android.R.attr#launchMode singleTop} launchMode flag.  This allows the system 
  * to launch searches from/to the same activity without creating a pile of them on the 
  * activity stack.  If you do this, be sure to also override 
@@ -255,25 +233,10 @@
  *     doSearchWithQuery(queryString);
  * }</pre>
  * 
- * <a name="FilterSearchApplications"></a>
- * <h3>Filter-Search Applications</h3>
- * 
- * <p>Filter-search applications are those that use live text entry (e.g. keystrokes)) to
- * display and continuously update a list of results.  Primary examples include applications
- * that use locally-stored data.
- * 
- * <p>Filter search is not directly supported by the Search Manager.  Most filter search
- * implementations will use variants of {@link android.widget.Filterable}, such as a 
- * {@link android.widget.ListView} bound to a {@link android.widget.SimpleCursorAdapter}.  However,
- * you may find it useful to mix them together, by declaring your filtered view searchable.  With
- * this configuration, you can still present the standard search dialog in all activities
- * within your application, but transition to a filtered search when you enter the activity
- * and display the results.
- * 
  * <a name="Suggestions"></a>
  * <h3>Search Suggestions</h3>
  * 
- * <p>A powerful feature of the Search Manager is the ability of any application to easily provide
+ * <p>A powerful feature of the search system is the ability of any application to easily provide
  * live "suggestions" in order to prompt the user.  Each application implements suggestions in a 
  * different, unique, and appropriate way.  Suggestions be drawn from many sources, including but 
  * not limited to:
@@ -285,11 +248,11 @@
  * <li>Summaries of possible results</li>
  * </ul>
  * 
- * <p>Another feature of suggestions is that they can expose queries or results before the user
- * ever visits the application.  This reduces the amount of context switching required, and helps
- * the user access their data quickly and with less context shifting.  In order to provide this
- * capability, suggestions are accessed via a 
- * {@link android.content.ContentProvider Content Provider}.  
+ * <p>Once an application is configured to provide search suggestions, those same suggestions can
+ * easily be made available to the system-wide Quick Search Box, providing faster access to its
+ * content from on central prominent place. See
+ * <a href="#ExposingSearchSuggestionsToQuickSearchBox">Exposing Search Suggestions to Quick Search
+ * Box</a> for more details.
  * 
  * <p>The primary form of suggestions is known as <i>queried suggestions</i> and is based on query
  * text that the user has already typed.  This would generally be based on partial matches in
@@ -299,7 +262,8 @@
  * available, they should be weighted based on other factors - for example, most recent queries 
  * or most recent results.
  * 
- * <p><b>Overview of how suggestions are provided.</b>  When the search manager identifies a 
+ * <p><b>Overview of how suggestions are provided.</b>  Suggestions are accessed via a
+ * {@link android.content.ContentProvider Content Provider}. When the search manager identifies a 
  * particular activity as searchable, it will check for certain metadata which indicates that
  * there is also a source of suggestions.  If suggestions are provided, the following steps are
  * taken.
@@ -569,6 +533,11 @@
  * query text is provided and the SUGGEST_COLUMN_INTENT_DATA values are not suitable for user 
  * inspection and editing.</li></ul>
  *
+ * <a name="ExposingSearchSuggestionsToQuickSearchBox"></a>
+ * <h3>Exposing Search Suggestions to Quick Search Box</h3>
+ * 
+ * <p>
+ * 
  * <a name="ActionKeys"></a>
  * <h3>Action Keys</h3>
  * 
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index 9799ac4..cced338 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -24,16 +24,17 @@
 import android.graphics.Color;
 import android.graphics.Paint;
 import android.os.SystemClock;
+import android.os.Parcelable;
+import android.os.Parcel;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.util.SparseArray;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
-import android.view.ViewGroup;
 import android.widget.FrameLayout;
 import android.widget.RemoteViews;
 import android.widget.TextView;
-import android.widget.FrameLayout.LayoutParams;
 
 /**
  * Provides the glue to show AppWidget views. This class offers automatic animation
@@ -108,6 +109,24 @@
         return mInfo;
     }
 
+    @Override
+    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
+        final ParcelableSparseArray jail = new ParcelableSparseArray();
+        super.dispatchSaveInstanceState(jail);
+        container.put(generateId(), jail);
+    }
+
+    private int generateId() {
+        final int id = getId();
+        return id == View.NO_ID ? mAppWidgetId : id;
+    }
+
+    @Override
+    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
+        final ParcelableSparseArray jail = (ParcelableSparseArray) container.get(generateId());
+        super.dispatchRestoreInstanceState(jail);
+    }
+
     /** {@inheritDoc} */
     @Override
     public LayoutParams generateLayoutParams(AttributeSet attrs) {
@@ -339,4 +358,36 @@
         tv.setBackgroundColor(Color.argb(127, 0, 0, 0));
         return tv;
     }
+
+    private static class ParcelableSparseArray extends SparseArray<Parcelable> implements Parcelable {
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel dest, int flags) {
+            final int count = size();
+            dest.writeInt(count);
+            for (int i = 0; i < count; i++) {
+                dest.writeInt(keyAt(i));
+                dest.writeParcelable(valueAt(i), 0);
+            }
+        }
+
+        public static final Parcelable.Creator<ParcelableSparseArray> CREATOR =
+                new Parcelable.Creator<ParcelableSparseArray>() {
+                    public ParcelableSparseArray createFromParcel(Parcel source) {
+                        final ParcelableSparseArray array = new ParcelableSparseArray();
+                        final ClassLoader loader = array.getClass().getClassLoader();
+                        final int count = source.readInt();
+                        for (int i = 0; i < count; i++) {
+                            array.put(source.readInt(), source.readParcelable(loader));
+                        }
+                        return array;
+                    }
+
+                    public ParcelableSparseArray[] newArray(int size) {
+                        return new ParcelableSparseArray[size];
+                    }
+                };
+    }
 }
diff --git a/core/java/android/backup/IRestoreSession.aidl b/core/java/android/backup/IRestoreSession.aidl
index 2a1fbc1..fd40d98 100644
--- a/core/java/android/backup/IRestoreSession.aidl
+++ b/core/java/android/backup/IRestoreSession.aidl
@@ -40,6 +40,8 @@
      * Restore the given set onto the device, replacing the current data of any app
      * contained in the restore set with the data previously backed up.
      *
+     * @return Zero on success; nonzero on error.  The observer will only receive
+     *   progress callbacks if this method returned zero.
      * @param token The token from {@link getAvailableRestoreSets()} corresponding to
      *   the restore set that should be used.
      * @param observer If non-null, this binder points to an object that will receive
@@ -50,6 +52,9 @@
     /**
      * End this restore session.  After this method is called, the IRestoreSession binder
      * is no longer valid.
+     *
+     * <p><b>Note:</b> The caller <i>must</i> invoke this method to end the restore session,
+     *   even if {@link getAvailableRestoreSets} or {@link performRestore} failed.
      */
     void endRestoreSession();
 }
diff --git a/core/java/android/inputmethodservice/KeyboardView.java b/core/java/android/inputmethodservice/KeyboardView.java
index dff7cae..9e966cd 100755
--- a/core/java/android/inputmethodservice/KeyboardView.java
+++ b/core/java/android/inputmethodservice/KeyboardView.java
@@ -163,8 +163,8 @@
     private static final int MSG_REPEAT = 3;
     private static final int MSG_LONGPRESS = 4;
 
-    private static final int DELAY_BEFORE_PREVIEW = 40;
-    private static final int DELAY_AFTER_PREVIEW = 60;
+    private static final int DELAY_BEFORE_PREVIEW = 0;
+    private static final int DELAY_AFTER_PREVIEW = 70;
     
     private int mVerticalCorrection;
     private int mProximityThreshold;
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index cf26b1b..e1b8e99 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2947,6 +2947,11 @@
         public static final String DATA_MESSAGE_GET_APP_TOKEN_URL =
                 "data_messaging_get_app_token_url";
 
+	/**
+	 * Use android://&lt;it&gt; routing infos for Google Sync Server subcriptions.
+	 */
+	public static final String GSYNC_USE_RMQ2_ROUTING_INFO = "gsync_use_rmq2_routing_info";
+
         /**
          * Enable use of ssl session caching.
          * 'db' - save each session in a (per process) database
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index b033c6a..04a0ec8 100755
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -189,6 +189,12 @@
                 "android.speech.tts.engine.INSTALL_TTS_DATA";
 
         /**
+         * {@hide}
+         */
+        @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+        public static final String ACTION_TTS_DATA_INSTALLED =
+                "android.speech.tts.engine.TTS_DATA_INSTALLED";
+        /**
          * Broadcast Action: Starts the activity from the platform Text-To-Speech
          * engine to verify the proper installation and availability of the
          * resource files on the system. Upon completion, the activity will
@@ -233,6 +239,16 @@
          */
         public static final String EXTRA_VOICE_DATA_FILES_INFO = "dataFilesInfo";
 
+        // extras for a TTS engine's data installation
+        /**
+         * Extra information received with the {@link #ACTION_TTS_DATA_INSTALLED} intent
+         * which indicates whether the TTS data installation requested with
+         * {@link #ACTION_INSTALL_TTS_DATA} completed successfully or not. The value is
+         * {@link TextToSpeech#SUCCESS} or {@link TextToSpeech#ERROR}.
+         * {@hide}
+         */
+        public static final String EXTRA_TTS_DATA_INSTALLED = "dataInstalled";
+
         // keys for the parameters passed with speak commands. Hidden keys are used internally
         // to maintain engine state for each TextToSpeech instance.
         /**
diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java
index b2277cb..96bf46e 100644
--- a/core/java/android/webkit/CallbackProxy.java
+++ b/core/java/android/webkit/CallbackProxy.java
@@ -111,7 +111,7 @@
 
     // Result transportation object for returning results across thread
     // boundaries.
-    private class ResultTransport<E> {
+    private static class ResultTransport<E> {
         // Private result object
         private E mResult;
 
diff --git a/core/java/android/webkit/GeolocationService.java b/core/java/android/webkit/GeolocationService.java
new file mode 100755
index 0000000..78b25ba
--- /dev/null
+++ b/core/java/android/webkit/GeolocationService.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit;
+
+import android.app.ActivityThread;
+import android.content.Context;
+import android.location.Location;
+import android.location.LocationListener;
+import android.location.LocationManager;
+import android.location.LocationProvider;
+import android.os.Bundle;
+import android.util.Log;
+import android.webkit.WebView;
+import android.webkit.WebViewCore;
+
+
+/**
+ * Implements the Java side of GeolocationServiceAndroid.
+ * @hide Pending API council review.
+ */
+public final class GeolocationService implements LocationListener {
+
+    // Log tag
+    private static final String TAG = "geolocationService";
+
+    private long mNativeObject;
+    private LocationManager mLocationManager;
+    private boolean mIsGpsEnabled;
+    private boolean mIsRunning;
+    private boolean mIsNetworkProviderAvailable;
+    private boolean mIsGpsProviderAvailable;
+
+    /**
+     * Constructor
+     * @param nativeObject The native object to which this object will report position updates and
+     *     errors.
+     */
+    public GeolocationService(long nativeObject) {
+        mNativeObject = nativeObject;
+        // Register newLocationAvailable with platform service.
+        ActivityThread thread = ActivityThread.systemMain();
+        Context context = thread.getApplication();
+        mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
+        if (mLocationManager == null) {
+            Log.e(TAG, "Could not get location manager.");
+        }
+     }
+
+    /**
+     * Start listening for location updates.
+     */
+    public void start() {
+        registerForLocationUpdates();
+        mIsRunning = true;
+    }
+
+    /**
+     * Stop listening for location updates.
+     */
+    public void stop() {
+        unregisterFromLocationUpdates();
+        mIsRunning = false;
+    }
+
+    /**
+     * Sets whether to use the GPS.
+     * @param enable Whether to use the GPS.
+     */
+    public void setEnableGps(boolean enable) {
+        if (mIsGpsEnabled != enable) {
+            mIsGpsEnabled = enable;
+            if (mIsRunning) {
+                // There's no way to unregister from a single provider, so we can
+                // only unregister from all, then reregister with all but the GPS.
+                unregisterFromLocationUpdates();
+                registerForLocationUpdates();
+            }
+        }
+    }
+
+    /**
+     * LocationListener implementation.
+     * Called when the location has changed.
+     * @param location The new location, as a Location object.
+     */
+    public void onLocationChanged(Location location) {
+        // Callbacks from the system location sevice are queued to this thread, so it's possible
+        // that we receive callbacks after unregistering. At this point, the native object will no
+        // longer exist.
+        if (mIsRunning) {
+            nativeNewLocationAvailable(mNativeObject, location);
+        }
+    }
+
+    /**
+     * LocationListener implementation.
+     * Called when the provider status changes.
+     * @param provider The name of the provider.
+     * @param status The new status of the provider.
+     * @param extras an optional Bundle with provider specific data.
+     */
+    public void onStatusChanged(String providerName, int status, Bundle extras) {
+        boolean isAvailable = (status == LocationProvider.AVAILABLE);
+        if (LocationManager.NETWORK_PROVIDER.equals(providerName)) {
+            mIsNetworkProviderAvailable = isAvailable;
+        } else if (LocationManager.GPS_PROVIDER.equals(providerName)) {
+            mIsGpsProviderAvailable = isAvailable;
+        }
+        maybeReportError("The last location provider is no longer available");
+    }
+
+    /**
+     * LocationListener implementation.
+     * Called when the provider is enabled.
+     * @param provider The name of the location provider that is now enabled.
+     */
+    public void onProviderEnabled(String providerName) {
+        // No need to notify the native side. It's enough to start sending
+        // valid position fixes again.
+        if (LocationManager.NETWORK_PROVIDER.equals(providerName)) {
+            mIsNetworkProviderAvailable = true;
+        } else if (LocationManager.GPS_PROVIDER.equals(providerName)) {
+            mIsGpsProviderAvailable = true;
+        }
+    }
+
+    /**
+     * LocationListener implementation.
+     * Called when the provider is disabled.
+     * @param provider The name of the location provider that is now disabled.
+     */
+    public void onProviderDisabled(String providerName) {
+        if (LocationManager.NETWORK_PROVIDER.equals(providerName)) {
+            mIsNetworkProviderAvailable = false;
+        } else if (LocationManager.GPS_PROVIDER.equals(providerName)) {
+            mIsGpsProviderAvailable = false;
+        }
+        maybeReportError("The last location provider was disabled");
+    }
+
+    /**
+     * Registers this object with the location service.
+     */
+    private void registerForLocationUpdates() {
+        mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
+        mIsNetworkProviderAvailable = true;
+        if (mIsGpsEnabled) {
+            mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
+            mIsGpsProviderAvailable = true;
+        }
+    }
+
+    /**
+     * Unregisters this object from the location service.
+     */
+    private void unregisterFromLocationUpdates() {
+        mLocationManager.removeUpdates(this);
+    }
+
+    /**
+     * Reports an error if neither the network nor the GPS provider is available.
+     */
+    private void maybeReportError(String message) {
+        // Callbacks from the system location sevice are queued to this thread, so it's possible
+        // that we receive callbacks after unregistering. At this point, the native object will no
+        // longer exist.
+        if (mIsRunning && !mIsNetworkProviderAvailable && !mIsGpsProviderAvailable) {
+            nativeNewErrorAvailable(mNativeObject, message);
+        }
+    }
+
+    // Native functions
+    private static native void nativeNewLocationAvailable(long nativeObject, Location location);
+    private static native void nativeNewErrorAvailable(long nativeObject, String message);
+}
diff --git a/core/java/android/webkit/WebIconDatabase.java b/core/java/android/webkit/WebIconDatabase.java
index d284f5e..6cc6bb4 100644
--- a/core/java/android/webkit/WebIconDatabase.java
+++ b/core/java/android/webkit/WebIconDatabase.java
@@ -37,7 +37,7 @@
     private final EventHandler mEventHandler = new EventHandler();
 
     // Class to handle messages before WebCore is ready
-    private class EventHandler extends Handler {
+    private static class EventHandler extends Handler {
         // Message ids
         static final int OPEN         = 0;
         static final int CLOSE        = 1;
diff --git a/core/java/android/webkit/WebStorage.java b/core/java/android/webkit/WebStorage.java
index c3b359e..ae560fb 100644
--- a/core/java/android/webkit/WebStorage.java
+++ b/core/java/android/webkit/WebStorage.java
@@ -70,7 +70,7 @@
 
     private Handler mHandler = null;
 
-    private class Origin {
+    private static class Origin {
         String mOrigin = null;
         long mQuota = 0;
 
diff --git a/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java b/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java
index 7aa4f47..6d50840 100644
--- a/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java
+++ b/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java
@@ -18,73 +18,68 @@
 
 import android.app.WallpaperManager;
 import android.graphics.Canvas;
-import android.graphics.Paint;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
-import android.os.Handler;
-import android.os.Message;
-import android.os.SystemClock;
 import android.service.wallpaper.WallpaperService;
 import android.view.SurfaceHolder;
+import android.content.Context;
+import android.content.IntentFilter;
+import android.content.Intent;
+import android.content.BroadcastReceiver;
 
 /**
  * Default built-in wallpaper that simply shows a static image.
  */
 public class ImageWallpaper extends WallpaperService {
-    public WallpaperManager mWallpaperManager;
-    
-    static final int MSG_DRAW = 1;
-    
-    class MyEngine extends Engine {
-        final Paint mTextPaint = new Paint();
-        float mDensity;
-        Drawable mBackground;
-        long mAnimStartTime;
-        boolean mAnimLarger;
-        
-        final Handler mHandler = new Handler() {
+    WallpaperManager mWallpaperManager;
+    ImageWallpaper.DrawableEngine mEngine;
+    private WallpaperObserver mReceiver;
 
-            @Override
-            public void handleMessage(Message msg) {
-                switch (msg.what) {
-                    case MSG_DRAW:
-                        drawFrame(true);
-                        mHandler.sendEmptyMessage(MSG_DRAW);
-                        break;
-                    default:
-                        super.handleMessage(msg);
-                }
-            }
-        };
-        
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        mWallpaperManager = (WallpaperManager) getSystemService(WALLPAPER_SERVICE);
+        IntentFilter filter = new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED);
+        mReceiver = new WallpaperObserver();
+        registerReceiver(mReceiver, filter);
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        unregisterReceiver(mReceiver);
+    }
+
+    public Engine onCreateEngine() {
+        mEngine = new DrawableEngine();
+        return mEngine;
+    }
+
+    class WallpaperObserver extends BroadcastReceiver {
+        public void onReceive(Context context, Intent intent) {
+            mEngine.updateWallpaper();
+        }
+    }
+
+    class DrawableEngine extends Engine {
+        private final Object mLock = new Object();
+        Drawable mBackground;
+
         @Override
         public void onCreate(SurfaceHolder surfaceHolder) {
             super.onCreate(surfaceHolder);
             mBackground = mWallpaperManager.getDrawable();
-            mTextPaint.setAntiAlias(true);
-            mDensity = getResources().getDisplayMetrics().density;
-            mTextPaint.setTextSize(30 * mDensity);
-            mTextPaint.setShadowLayer(5*mDensity, 3*mDensity, 3*mDensity, 0xff000000);
-            mTextPaint.setARGB(255, 255, 255, 255);
-            mTextPaint.setTextAlign(Paint.Align.CENTER);
         }
 
         @Override
         public void onVisibilityChanged(boolean visible) {
-            mHandler.removeMessages(MSG_DRAW);
-            if (visible) {
-                mHandler.sendEmptyMessage(MSG_DRAW);
-                mAnimStartTime = SystemClock.uptimeMillis();
-                mAnimLarger = true;
-            } else {
-                drawFrame(false);
-            }
+            drawFrame();
         }
         
         @Override
         public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
             super.onSurfaceChanged(holder, format, width, height);
-            drawFrame(false);
+            drawFrame();
         }
 
         @Override
@@ -97,44 +92,28 @@
             super.onSurfaceDestroyed(holder);
         }
         
-        void drawFrame(boolean drawText) {
+        void drawFrame() {
             SurfaceHolder sh = getSurfaceHolder();
-            Canvas c = sh.lockCanvas();
-            if (c != null) {
-                final Rect frame = sh.getSurfaceFrame();
-                mBackground.setBounds(frame);
-                mBackground.draw(c);
-                
-                if (drawText) {
-                    // Figure out animation.
-                    long now = SystemClock.uptimeMillis();
-                    while (mAnimStartTime < (now-1000)) {
-                        mAnimStartTime += 1000;
-                        mAnimLarger = !mAnimLarger;
+            Canvas c = null;
+            try {
+                c = sh.lockCanvas();
+                if (c != null) {
+                    final Rect frame = sh.getSurfaceFrame();
+                    synchronized (mLock) {
+                        final Drawable background = mBackground;
+                        background.setBounds(frame);
+                        background.draw(c);
                     }
-                    float size = (now-mAnimStartTime) / (float)1000;
-                    if (!mAnimLarger) size = 1-size;
-                    int alpha = (int)(255*(size*size));
-                    mTextPaint.setARGB(alpha, 255, 255, 255);
-                    mTextPaint.setShadowLayer(5*mDensity, 3*mDensity, 3*mDensity,
-                            alpha<<24);
-                    mTextPaint.setTextSize(100 * mDensity * size);
-                    c.drawText("Am I live?",
-                            frame.left + (frame.right-frame.left)/2,
-                            frame.top + (frame.bottom-frame.top)/2, mTextPaint);
                 }
+            } finally {
+                if (c != null) sh.unlockCanvasAndPost(c);
             }
-            sh.unlockCanvasAndPost(c);
         }
-    }
-    
-    @Override
-    public void onCreate() {
-        super.onCreate();
-        mWallpaperManager = (WallpaperManager)getSystemService(WALLPAPER_SERVICE);
-    }
-    
-    public Engine onCreateEngine() {
-        return new MyEngine();
+
+        void updateWallpaper() {
+            synchronized (mLock) {
+                mBackground = mWallpaperManager.getDrawable();
+            }
+        }
     }
 }
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 0035142..77486b1 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -203,7 +203,7 @@
     ///////////////////////////////////////////////////////////////////////////////////
     //
 
-    RenderScript(Surface sur) {
+    public RenderScript(Surface sur) {
         mSurface = sur;
         mDev = nDeviceCreate();
         mContext = nContextCreate(mDev, mSurface, 0);
diff --git a/include/ui/FramebufferNativeWindow.h b/include/ui/FramebufferNativeWindow.h
index cb9bf94..68144b5 100644
--- a/include/ui/FramebufferNativeWindow.h
+++ b/include/ui/FramebufferNativeWindow.h
@@ -63,6 +63,7 @@
     static int lockBuffer(android_native_window_t* window, android_native_buffer_t* buffer);
     static int queueBuffer(android_native_window_t* window, android_native_buffer_t* buffer);
     static int query(android_native_window_t* window, int what, int* value);
+    static int perform(android_native_window_t* window, int operation, ...);
     
     framebuffer_device_t* fbDev;
     alloc_device_t* grDev;
diff --git a/include/ui/ISurface.h b/include/ui/ISurface.h
index adba45a..7909c2f 100644
--- a/include/ui/ISurface.h
+++ b/include/ui/ISurface.h
@@ -50,7 +50,7 @@
 public: 
     DECLARE_META_INTERFACE(Surface);
 
-    virtual sp<SurfaceBuffer> getBuffer() = 0; 
+    virtual sp<SurfaceBuffer> getBuffer(int usage) = 0; 
     
     class BufferHeap {
     public:
diff --git a/include/ui/Surface.h b/include/ui/Surface.h
index d5dad31..4ff0e4a 100644
--- a/include/ui/Surface.h
+++ b/include/ui/Surface.h
@@ -184,7 +184,7 @@
     friend class IOMX;
     const sp<ISurface>& getISurface() const { return mSurface; }
 
-    status_t getBufferLocked(int index);
+    status_t getBufferLocked(int index, int usage);
    
            status_t validate(per_client_cblk_t const* cblk) const;
     static void _send_dirty_region(layer_cblk_t* lcblk, const Region& dirty);
@@ -197,11 +197,13 @@
     static int lockBuffer(android_native_window_t* window, android_native_buffer_t* buffer);
     static int queueBuffer(android_native_window_t* window, android_native_buffer_t* buffer);
     static int query(android_native_window_t* window, int what, int* value);
+    static int perform(android_native_window_t* window, int operation, ...);
 
     int dequeueBuffer(android_native_buffer_t** buffer);
     int lockBuffer(android_native_buffer_t* buffer);
     int queueBuffer(android_native_buffer_t* buffer);
     int query(int what, int* value);
+    int perform(int operation, va_list args);
 
     status_t dequeueBuffer(sp<SurfaceBuffer>* buffer);
     status_t lockBuffer(const sp<SurfaceBuffer>& buffer);
@@ -217,6 +219,7 @@
     uint32_t                    mIdentity;
     uint32_t                    mWidth;
     uint32_t                    mHeight;
+    uint32_t                    mUsage;
     PixelFormat                 mFormat;
     uint32_t                    mFlags;
     mutable Region              mDirtyRegion;
diff --git a/include/ui/egl/android_natives.h b/include/ui/egl/android_natives.h
index 7da69b1..4c58e47 100644
--- a/include/ui/egl/android_natives.h
+++ b/include/ui/egl/android_natives.h
@@ -67,6 +67,11 @@
     NATIVE_WINDOW_FORMAT    = 2,
 };
 
+/* valid operations for the (*perform)() hook */
+enum {
+    NATIVE_WINDOW_SET_USAGE = 0
+};
+
 struct android_native_window_t 
 {
 #ifdef __cplusplus
@@ -142,11 +147,45 @@
      * Returns 0 on success or -errno on error.
      */
     int     (*query)(struct android_native_window_t* window,
-            int what, int* value);
+                int what, int* value);
     
-    void* reserved_proc[4];
+    /*
+     * hook used to perform various operations on the surface.
+     * (*perform)() is a generic mechanism to add functionality to
+     * android_native_window_t while keeping backward binary compatibility.
+     * 
+     * This hook should not be called directly, instead use the helper functions
+     * defined below.
+     * 
+     * The valid operations are:
+     *     NATIVE_WINDOW_SET_USAGE
+     *  
+     */
+    
+    int     (*perform)(struct android_native_window_t* window,
+                int operation, ... );
+    
+    void* reserved_proc[3];
 };
 
+
+/*
+ *  native_window_set_usage() sets the intended usage flags for the next
+ *  buffers acquired with (*lockBuffer)() and on.
+ *  By default (if this function is never called), a usage of
+ *      GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE
+ *  is assumed.
+ *  Calling this function will usually cause following buffers to be
+ *  reallocated.
+ */
+
+inline int native_window_set_usage(
+        struct android_native_window_t* window, int usage)
+{
+    return window->perform(window, NATIVE_WINDOW_SET_USAGE, usage);
+}
+
+
 // ---------------------------------------------------------------------------
 
 /* FIXME: this is legacy for pixmaps */
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index d1142cc..8c0b40d 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -217,7 +217,7 @@
     drawWithOpenGL(clip, mTextures[index]);
 }
 
-sp<SurfaceBuffer> Layer::peekBuffer()
+sp<SurfaceBuffer> Layer::peekBuffer(int usage)
 {
     /*
      * This is called from the client's Surface::lock(), after it locked
@@ -250,7 +250,7 @@
     }
     
     LayerBitmap& layerBitmap(mBuffers[backBufferIndex]);
-    sp<SurfaceBuffer> buffer = layerBitmap.allocate();
+    sp<SurfaceBuffer> buffer = layerBitmap.allocate(usage);
     
     LOGD_IF(DEBUG_RESIZE,
             "Layer::getBuffer(this=%p), index=%d, (%d,%d), (%d,%d)",
@@ -649,12 +649,12 @@
 {
 }
 
-sp<SurfaceBuffer> Layer::SurfaceLayer::getBuffer()
+sp<SurfaceBuffer> Layer::SurfaceLayer::getBuffer(int usage)
 {
     sp<SurfaceBuffer> buffer = 0;
     sp<Layer> owner(getOwner());
     if (owner != 0) {
-        buffer = owner->peekBuffer();
+        buffer = owner->peekBuffer(usage);
     }
     return buffer;
 }
diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h
index 4c13d6e..add5d50 100644
--- a/libs/surfaceflinger/Layer.h
+++ b/libs/surfaceflinger/Layer.h
@@ -101,7 +101,7 @@
 
     status_t resize(int32_t index, uint32_t w, uint32_t h, const char* what);
     Region post(uint32_t* oldState, bool& recomputeVisibleRegions);
-    sp<SurfaceBuffer> peekBuffer();
+    sp<SurfaceBuffer> peekBuffer(int usage);
     void destroy();
     void scheduleBroadcast();
 
@@ -114,7 +114,7 @@
                 ~SurfaceLayer();
 
     private:
-        virtual sp<SurfaceBuffer> getBuffer();
+        virtual sp<SurfaceBuffer> getBuffer(int usage);
 
         sp<Layer> getOwner() const {
             return static_cast<Layer*>(Surface::getOwner().get());
diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp
index fbce73d..419574c 100644
--- a/libs/surfaceflinger/LayerBase.cpp
+++ b/libs/surfaceflinger/LayerBase.cpp
@@ -759,7 +759,7 @@
     return BnSurface::onTransact(code, data, reply, flags);
 }
 
-sp<SurfaceBuffer> LayerBaseClient::Surface::getBuffer() 
+sp<SurfaceBuffer> LayerBaseClient::Surface::getBuffer(int) 
 {
     return NULL; 
 }
diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h
index 6fb1d1c..65bf55b 100644
--- a/libs/surfaceflinger/LayerBase.h
+++ b/libs/surfaceflinger/LayerBase.h
@@ -335,7 +335,7 @@
         sp<LayerBaseClient> getOwner() const;
 
     private:
-        virtual sp<SurfaceBuffer> getBuffer();
+        virtual sp<SurfaceBuffer> getBuffer(int usage);
         virtual status_t registerBuffers(const ISurface::BufferHeap& buffers); 
         virtual void postBuffer(ssize_t offset);
         virtual void unregisterBuffers();
diff --git a/libs/surfaceflinger/LayerBitmap.cpp b/libs/surfaceflinger/LayerBitmap.cpp
index 5221fed..5e74451 100644
--- a/libs/surfaceflinger/LayerBitmap.cpp
+++ b/libs/surfaceflinger/LayerBitmap.cpp
@@ -38,13 +38,14 @@
 // Buffer and implementation of android_native_buffer_t
 // ===========================================================================
 
-Buffer::Buffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
+Buffer::Buffer(uint32_t w, uint32_t h, PixelFormat format,
+        uint32_t reqUsage, uint32_t flags)
     : SurfaceBuffer(), mInitCheck(NO_INIT), mFlags(flags), 
     mVStride(0)
 {
     this->format = format;
     if (w>0 && h>0) {
-        mInitCheck = initSize(w, h);
+        mInitCheck = initSize(w, h, reqUsage);
     }
 }
 
@@ -65,7 +66,7 @@
     return static_cast<android_native_buffer_t*>(const_cast<Buffer*>(this));
 }
 
-status_t Buffer::initSize(uint32_t w, uint32_t h)
+status_t Buffer::initSize(uint32_t w, uint32_t h, uint32_t reqUsage)
 {
     status_t err = NO_ERROR;
 
@@ -88,16 +89,9 @@
         usage = BufferAllocator::USAGE_SW_READ_OFTEN | 
                 BufferAllocator::USAGE_SW_WRITE_OFTEN;
     } else {
-        if (mFlags & Buffer::GPU) {
-            // the client wants to do GL rendering
-            usage = BufferAllocator::USAGE_HW_RENDER |
-                    BufferAllocator::USAGE_HW_TEXTURE;
-        } else {
-            // software rendering-client, h/w composition
-            usage = BufferAllocator::USAGE_SW_READ_OFTEN | 
-                    BufferAllocator::USAGE_SW_WRITE_OFTEN |
-                    BufferAllocator::USAGE_HW_TEXTURE;
-        }
+        // it's allowed to modify the usage flags here, but generally
+        // the requested flags should be honored.
+        usage = reqUsage | BufferAllocator::USAGE_HW_TEXTURE;
     }
 
     err = allocator.alloc(w, h, format, usage, &handle, &stride);
@@ -174,12 +168,12 @@
     return NO_ERROR;
 }
 
-sp<Buffer> LayerBitmap::allocate()
+sp<Buffer> LayerBitmap::allocate(uint32_t reqUsage)
 {
     Mutex::Autolock _l(mLock);
     surface_info_t* info = mInfo;
     mBuffer.clear(); // free buffer before allocating a new one
-    sp<Buffer> buffer = new Buffer(mWidth, mHeight, mFormat, mFlags);
+    sp<Buffer> buffer = new Buffer(mWidth, mHeight, mFormat, reqUsage, mFlags);
     status_t err = buffer->initCheck();
     if (LIKELY(err == NO_ERROR)) {
         info->flags  = surface_info_t::eBufferDirty;
diff --git a/libs/surfaceflinger/LayerBitmap.h b/libs/surfaceflinger/LayerBitmap.h
index 22525ce..48ee553 100644
--- a/libs/surfaceflinger/LayerBitmap.h
+++ b/libs/surfaceflinger/LayerBitmap.h
@@ -58,7 +58,8 @@
     };
 
     // creates w * h buffer
-    Buffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags = 0);
+    Buffer(uint32_t w, uint32_t h, PixelFormat format,
+            uint32_t reqUsage, uint32_t flags = 0);
 
     // return status
     status_t initCheck() const;
@@ -81,7 +82,7 @@
     Buffer& operator = (const Buffer& rhs);
     const Buffer& operator = (const Buffer& rhs) const;
 
-    status_t initSize(uint32_t w, uint32_t h);
+    status_t initSize(uint32_t w, uint32_t h, uint32_t reqUsage);
 
     ssize_t                 mInitCheck;
     uint32_t                mFlags;
@@ -108,7 +109,7 @@
 
     status_t setSize(uint32_t w, uint32_t h);
 
-    sp<Buffer> allocate();
+    sp<Buffer> allocate(uint32_t reqUsage);
     status_t free();
     
     sp<const Buffer>  getBuffer() const { return mBuffer; }
diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp
index 90e7f50..bd6d472f 100644
--- a/libs/surfaceflinger/LayerBuffer.cpp
+++ b/libs/surfaceflinger/LayerBuffer.cpp
@@ -28,6 +28,7 @@
 
 #include <hardware/copybit.h>
 
+#include "BufferAllocator.h"
 #include "LayerBuffer.h"
 #include "SurfaceFlinger.h"
 #include "DisplayHardware/DisplayHardware.h"
@@ -464,7 +465,9 @@
                         mTempBitmap->getWidth() < tmp_w || 
                         mTempBitmap->getHeight() < tmp_h) {
                     mTempBitmap.clear();
-                    mTempBitmap = new android::Buffer(tmp_w, tmp_h, src.img.format);
+                    mTempBitmap = new android::Buffer(
+                            tmp_w, tmp_h, src.img.format,
+                            BufferAllocator::USAGE_HW_2D);
                     err = mTempBitmap->initCheck();
                 }
 
diff --git a/libs/surfaceflinger/LayerDim.cpp b/libs/surfaceflinger/LayerDim.cpp
index 8e9df9c..f613767 100644
--- a/libs/surfaceflinger/LayerDim.cpp
+++ b/libs/surfaceflinger/LayerDim.cpp
@@ -21,6 +21,7 @@
 #include <utils/Errors.h>
 #include <utils/Log.h>
 
+#include "BufferAllocator.h"
 #include "LayerDim.h"
 #include "SurfaceFlinger.h"
 #include "DisplayHardware/DisplayHardware.h"
@@ -68,7 +69,10 @@
 
     if (LIKELY(flags & DisplayHardware::DIRECT_TEXTURE)) {
         // TODO: api to pass the usage flags
-        sp<Buffer> buffer = new Buffer(w, h, PIXEL_FORMAT_RGB_565);
+        sp<Buffer> buffer = new Buffer(w, h, PIXEL_FORMAT_RGB_565,
+                 BufferAllocator::USAGE_SW_WRITE_OFTEN |
+                 BufferAllocator::USAGE_HW_TEXTURE);
+        
         android_native_buffer_t* clientBuf = buffer->getNativeBuffer();
 
         glGenTextures(1, &sTexId);
@@ -92,7 +96,7 @@
 
         // initialize the texture with zeros
         GGLSurface t;
-        buffer->lock(&t, GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN);
+        buffer->lock(&t, GRALLOC_USAGE_SW_WRITE_OFTEN);
         memset(t.data, 0, t.stride * t.height * 2);
         buffer->unlock();
         sUseTexture = true;
diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp
index f6c666d..90b5163 100644
--- a/libs/ui/FramebufferNativeWindow.cpp
+++ b/libs/ui/FramebufferNativeWindow.cpp
@@ -132,6 +132,7 @@
     android_native_window_t::lockBuffer = lockBuffer;
     android_native_window_t::queueBuffer = queueBuffer;
     android_native_window_t::query = query;
+    android_native_window_t::perform = perform;
 }
 
 FramebufferNativeWindow::~FramebufferNativeWindow() 
@@ -235,6 +236,18 @@
     return BAD_VALUE;
 }
 
+int FramebufferNativeWindow::perform(android_native_window_t* window,
+        int operation, ...)
+{
+    switch (operation) {
+        case NATIVE_WINDOW_SET_USAGE:
+            break;
+        default:
+            return NAME_NOT_FOUND;
+    }
+    return NO_ERROR;
+}
+
 // ----------------------------------------------------------------------------
 }; // namespace android
 // ----------------------------------------------------------------------------
diff --git a/libs/ui/ISurface.cpp b/libs/ui/ISurface.cpp
index 9fbae1e..b78e8b5 100644
--- a/libs/ui/ISurface.cpp
+++ b/libs/ui/ISurface.cpp
@@ -71,10 +71,11 @@
     {
     }
 
-    virtual sp<SurfaceBuffer> getBuffer()
+    virtual sp<SurfaceBuffer> getBuffer(int usage)
     {
         Parcel data, reply;
         data.writeInterfaceToken(ISurface::getInterfaceDescriptor());
+        data.writeInt32(usage);
         remote()->transact(GET_BUFFER, data, &reply);
         sp<SurfaceBuffer> buffer = new SurfaceBuffer(reply);
         return buffer;
@@ -135,7 +136,8 @@
     switch(code) {
         case GET_BUFFER: {
             CHECK_INTERFACE(ISurface, data, reply);
-            sp<SurfaceBuffer> buffer(getBuffer());
+            int usage = data.readInt32();
+            sp<SurfaceBuffer> buffer(getBuffer(usage));
             return SurfaceBuffer::writeToParcel(reply, buffer.get());
         }
         case REGISTER_BUFFERS: {
diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp
index 4abb7f6..2b6905f 100644
--- a/libs/ui/Surface.cpp
+++ b/libs/ui/Surface.cpp
@@ -414,6 +414,7 @@
     android_native_window_t::lockBuffer       = lockBuffer;
     android_native_window_t::queueBuffer      = queueBuffer;
     android_native_window_t::query            = query;
+    android_native_window_t::perform          = perform;
     mSwapRectangle.makeInvalid();
     DisplayInfo dinfo;
     SurfaceComposerClient::getDisplayInfo(0, &dinfo);
@@ -423,6 +424,8 @@
     const_cast<int&>(android_native_window_t::minSwapInterval) = 1;
     const_cast<int&>(android_native_window_t::maxSwapInterval) = 1;
     const_cast<uint32_t&>(android_native_window_t::flags) = 0;
+    // be default we request a hardware surface
+    mUsage = GRALLOC_USAGE_HW_RENDER;
 }
 
 
@@ -512,6 +515,17 @@
     return self->query(what, value);
 }
 
+int Surface::perform(android_native_window_t* window, 
+        int operation, ...)
+{
+    va_list args;
+    va_start(args, operation);
+    Surface* self = getSelf(window);
+    int res = self->perform(operation, args);
+    va_end(args);
+    return res;
+}
+
 // ----------------------------------------------------------------------------
 
 status_t Surface::dequeueBuffer(sp<SurfaceBuffer>* buffer)
@@ -561,7 +575,7 @@
 
     volatile const surface_info_t* const back = lcblk->surface + backIdx;
     if (back->flags & surface_info_t::eNeedNewBuffer) {
-        err = getBufferLocked(backIdx);
+        err = getBufferLocked(backIdx, mUsage);
     }
 
     if (err == NO_ERROR) {
@@ -627,6 +641,20 @@
     return BAD_VALUE;
 }
 
+int Surface::perform(int operation, va_list args)
+{
+    int res = NO_ERROR;
+    switch (operation) {
+        case NATIVE_WINDOW_SET_USAGE:
+            mUsage = va_arg(args, int);
+            break;
+        default:
+            res = NAME_NOT_FOUND;
+            break;
+    }
+    return res;
+}
+
 // ----------------------------------------------------------------------------
 
 status_t Surface::lock(SurfaceInfo* info, bool blocking) {
@@ -636,6 +664,9 @@
 status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking) 
 {
     // FIXME: needs some locking here
+
+    // we're intending to do software rendering from this point
+    mUsage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN;
     
     sp<SurfaceBuffer> backBuffer;
     status_t err = dequeueBuffer(&backBuffer);
@@ -725,10 +756,10 @@
     mSwapRectangle = r;
 }
 
-status_t Surface::getBufferLocked(int index)
+status_t Surface::getBufferLocked(int index, int usage)
 {
     status_t err = NO_MEMORY;
-    sp<SurfaceBuffer> buffer = mSurface->getBuffer();
+    sp<SurfaceBuffer> buffer = mSurface->getBuffer(usage);
     LOGE_IF(buffer==0, "ISurface::getBuffer() returned NULL");
     if (buffer != 0) {
         sp<SurfaceBuffer>& currentBuffer(mBuffers[index]);
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 645f3f6..6d7c0ae 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -128,7 +128,10 @@
     }
 
     public void setFilename(String filename) {
-        mFilename = filename;
+        if (mFilename == null || !mFilename.equals(filename)) {
+            mFilename = filename;
+            mCachedAttributes = null;
+        }
     }
 
     /**
diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp
index cf66be3..0762ebf 100644
--- a/opengl/libagl/egl.cpp
+++ b/opengl/libagl/egl.cpp
@@ -384,6 +384,10 @@
 
 EGLBoolean egl_window_surface_v2_t::connect() 
 {
+    // we're intending to do software rendering
+    native_window_set_usage(nativeWindow, 
+            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
+
     // dequeue a buffer
     if (nativeWindow->dequeueBuffer(nativeWindow, &buffer) != NO_ERROR) {
         return setError(EGL_BAD_ALLOC, EGL_FALSE);
diff --git a/opengl/tests/filter/filter.cpp b/opengl/tests/filter/filter.cpp
index 82aafbf..2351909 100644
--- a/opengl/tests/filter/filter.cpp
+++ b/opengl/tests/filter/filter.cpp
@@ -10,6 +10,8 @@
 
 using namespace android;
 
+#define USE_DRAW_TEXTURE 1
+
 int main(int argc, char** argv)
 {
     if (argc!=2 && argc!=3) {
@@ -45,9 +47,9 @@
      dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
      eglInitialize(dpy, &majorVersion, &minorVersion);
      if (!usePbuffer) {
-         surface = eglCreateWindowSurface(dpy, config, window, NULL);
          EGLUtils::selectConfigForNativeWindow(
                  dpy, s_configAttribs, window, &config);
+         surface = eglCreateWindowSurface(dpy, config, window, NULL);
      } else {
          printf("using pbuffer\n");
          eglChooseConfig(dpy, s_configAttribs, &config, 1, &numConfigs);
@@ -63,6 +65,12 @@
      eglQuerySurface(dpy, surface, EGL_HEIGHT, &h);
      GLint dim = w<h ? w : h;
 
+     glViewport(0, 0, w, h);
+     glMatrixMode(GL_PROJECTION);
+     glLoadIdentity();
+     glOrthof(0, w, 0, h, 0, 1);
+
+     glClearColor(0,0,0,0);
      glClear(GL_COLOR_BUFFER_BIT);
 
      GLint crop[4] = { 0, 4, 4, -4 };
@@ -128,14 +136,55 @@
          break;
      }
 
-     glDrawTexiOES(0, 0, 0, dim, dim);
+     //glDrawTexiOES(0, 0, 0, dim, dim);
+     
+     const GLfloat vertices[4][2] = {
+             { 0,    0   },
+             { 0,    dim },
+             { dim,  dim },
+             { dim,  0   }
+     };
 
+     const GLfloat texCoords[4][2] = {
+             { 0,  0 },
+             { 0,  1 },
+             { 1,  1 },
+             { 1,  0 }
+     };
+     
      if (!usePbuffer) {
          eglSwapBuffers(dpy, surface);
-     } else {
-         glFinish();
      }
      
+     glMatrixMode(GL_MODELVIEW);
+     glScissor(0,dim,dim,h-dim);
+     glDisable(GL_SCISSOR_TEST);
+     
+     for (int y=0 ; y<dim ; y++) {
+         //glDisable(GL_SCISSOR_TEST);
+         glClear(GL_COLOR_BUFFER_BIT);
+
+         //glEnable(GL_SCISSOR_TEST);
+
+#if USE_DRAW_TEXTURE && GL_OES_draw_texture
+         glDrawTexiOES(0, y, 1, dim, dim);
+#else
+         glLoadIdentity();
+         glTranslatef(0, y, 0);
+         glEnableClientState(GL_VERTEX_ARRAY);
+         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+         glVertexPointer(2, GL_FLOAT, 0, vertices);
+         glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
+         glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+#endif
+
+         if (!usePbuffer) {
+             eglSwapBuffers(dpy, surface);
+         } else {
+             glFinish();
+         }
+     }
+
      eglTerminate(dpy);
      return 0;
 }
diff --git a/packages/VpnServices/src/com/android/server/vpn/VpnService.java b/packages/VpnServices/src/com/android/server/vpn/VpnService.java
index f410c7b..e3ac996 100644
--- a/packages/VpnServices/src/com/android/server/vpn/VpnService.java
+++ b/packages/VpnServices/src/com/android/server/vpn/VpnService.java
@@ -133,11 +133,7 @@
 
         if (VpnState.CONNECTED.equals(mState)) {
             Log.i("VpnService", "     recovered: " + mProfile.getName());
-            new Thread(new Runnable() {
-                public void run() {
-                    enterConnectivityLoop();
-                }
-            }).start();
+            startConnectivityMonitor();
         }
     }
 
@@ -213,16 +209,18 @@
                     SystemProperties.get(VPN_STATUS))) {
                 onConnected();
                 return;
-            } else if (mDaemonHelper.anySocketError()) {
-                return;
+            } else {
+                int err = mDaemonHelper.getSocketError();
+                if (err != 0) {
+                    onError(err);
+                    return;
+                }
             }
             sleep(500); // 0.5 second
         }
 
-        synchronized (VpnService.this) {
-            if (mState == VpnState.CONNECTING) {
-                onError(new IOException("Connecting timed out"));
-            }
+        if (mState == VpnState.CONNECTING) {
+            onError(new IOException("Connecting timed out"));
         }
     }
 
@@ -235,13 +233,15 @@
 
         mStartTime = System.currentTimeMillis();
 
-        // set DNS after saving the states in case the process gets killed
-        // before states are saved
+        // Correct order to make sure VpnService doesn't break when killed:
+        // (1) set state to CONNECTED
+        // (2) save states
+        // (3) set DNS
+        setState(VpnState.CONNECTED);
         saveSelf();
         setVpnDns();
-        setState(VpnState.CONNECTED);
 
-        enterConnectivityLoop();
+        startConnectivityMonitor();
     }
 
     private void saveSelf() throws IOException {
@@ -340,23 +340,28 @@
         }
     }
 
-    private void enterConnectivityLoop() {
-        Log.i(TAG, "VPN connectivity monitor running");
-        try {
-            for (;;) {
-                synchronized (VpnService.this) {
-                    if (mState != VpnState.CONNECTED || !checkConnectivity()) {
-                        break;
+    private void startConnectivityMonitor() {
+        new Thread(new Runnable() {
+            public void run() {
+                Log.i(TAG, "VPN connectivity monitor running");
+                try {
+                    for (;;) {
+                        synchronized (VpnService.this) {
+                            if ((mState != VpnState.CONNECTED)
+                                || !checkConnectivity()) {
+                                break;
+                            }
+                            mNotification.update();
+                            checkDns();
+                            VpnService.this.wait(1000); // 1 second
+                        }
                     }
-                    mNotification.update();
-                    checkDns();
-                    VpnService.this.wait(1000); // 1 second
+                } catch (InterruptedException e) {
+                    onError(e);
                 }
+                Log.i(TAG, "VPN connectivity monitor stopped");
             }
-        } catch (InterruptedException e) {
-            onError(e);
-        }
-        Log.i(TAG, "VPN connectivity monitor stopped");
+        }).start();
     }
 
     private void saveLocalIpAndInterface(String serverIp) throws IOException {
@@ -432,11 +437,7 @@
         }
 
         synchronized void stopAll() {
-            if (mDaemonList.isEmpty()) {
-                onFinalCleanUp();
-            } else {
-                for (DaemonProxy s : mDaemonList) s.stop();
-            }
+            for (DaemonProxy s : mDaemonList) s.stop();
         }
 
         synchronized void closeSockets() {
@@ -461,30 +462,26 @@
             }
         }
 
-        synchronized boolean anySocketError() {
+        synchronized int getSocketError() {
             for (DaemonProxy s : mDaemonList) {
                 switch (getResultFromSocket(s)) {
                     case 0:
                         continue;
 
                     case AUTH_ERROR_CODE:
-                        onError(VpnManager.VPN_ERROR_AUTH);
-                        return true;
+                        return VpnManager.VPN_ERROR_AUTH;
 
                     case CHALLENGE_ERROR_CODE:
-                        onError(VpnManager.VPN_ERROR_CHALLENGE);
-                        return true;
+                        return VpnManager.VPN_ERROR_CHALLENGE;
 
                     case REMOTE_HUNG_UP_ERROR_CODE:
-                        onError(VpnManager.VPN_ERROR_REMOTE_HUNG_UP);
-                        return true;
+                        return VpnManager.VPN_ERROR_REMOTE_HUNG_UP;
 
                     default:
-                        onError(VpnManager.VPN_ERROR_CONNECTION_FAILED);
-                        return true;
+                        return VpnManager.VPN_ERROR_CONNECTION_FAILED;
                 }
             }
-            return false;
+            return 0;
         }
     }
 
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 1e5302e..36dca7d 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -1725,6 +1725,8 @@
                     return 0;
                 }
             }
+
+            Log.w(TAG, "Restore token " + Long.toHexString(token) + " not found");
             return -1;
         }
 
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
index 69d3695..7e80370 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
@@ -630,7 +630,7 @@
         settings.setDatabaseEnabled(true);
         settings.setDatabasePath(getDir("databases",0).getAbsolutePath());
         settings.setDomStorageEnabled(true);
-        settings.setWorkersEnabled(true);
+        settings.setWorkersEnabled(false);
 
         webview.addJavascriptInterface(callbackProxy, "layoutTestController");
         webview.addJavascriptInterface(callbackProxy, "eventSender");
diff --git a/tests/backup/test_backup.sh b/tests/backup/test_backup.sh
index f50d03f..10b809d 100755
--- a/tests/backup/test_backup.sh
+++ b/tests/backup/test_backup.sh
@@ -14,39 +14,32 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# uncomment for debugging
+#export DRY_RUN="echo"
+source test_backup_common.sh
 
-ADB_OPTS="$@"
+# wipe prior backup data for packages
+b_pkgs=$(a shell dumpsys backup | \
+         ruby -ne 'print($1+" ") if $_ =~ /^\s*ApplicationInfo\S+ (.+?)\}/')
 
-#FIXME: what was this for?
-#adb kill-server
-
-b_pkgs=$(adb $ADB_OPTS shell dumpsys backup | \
-         ruby -ne 'print($1+" ") if $_ =~ /^\s*ApplicationInfo\{\S+ (.+?)\}/')
-
-# wipe prior backup data for packages, including the metadata package @pm@
-for pkg in $b_pkgs '@pm@'; do
-    adb $ADB_OPTS shell bmgr wipe "$pkg"
+for pkg in $b_pkgs; do
+    a shell bmgr wipe "$pkg"
 done
 
-# who knows?
 echo 'Waiting 5 seconds for things to settle...'
 sleep 5
 
 # run adb as root so we can poke at com.android.backuptest's data
-root_status=$(adb $ADB_OPTS root)
-if [ "x$root_status" != "xadbd is already running as root" ]; then
-    sleep 2
-    adb $ADB_OPTS 'wait-for-device'
-fi
+adb_root
 
 # show commands as we go
 set -x
 
 # set the transport
-adb $ADB_OPTS shell bmgr transport com.google.android.backup/.BackupTransportService
+a shell bmgr transport com.google.android.backup/.BackupTransportService
 
 # load up the three files
-adb $ADB_OPTS shell \
+a shell \
    "rm /data/data/com.android.backuptest/files/file.txt ; \
     rm /data/data/com.android.backuptest/files/another_file.txt ; \
     rm /data/data/com.android.backuptest/files/empty.txt ; \
@@ -63,8 +56,8 @@
 #    echo -n 3 > /data/data/com.android.backuptest/files/3.txt ; \
 
 # say that the data has changed
-adb $ADB_OPTS shell bmgr backup com.android.backuptest
+a shell bmgr backup com.android.backuptest
 
 # run the backup
-adb $ADB_OPTS shell bmgr run
+a shell bmgr run
 
diff --git a/tests/backup/test_backup_common.sh b/tests/backup/test_backup_common.sh
new file mode 100755
index 0000000..61ec833
--- /dev/null
+++ b/tests/backup/test_backup_common.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+# Copyright (C) 2009 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+export ADB_OPTS="$@"
+
+# run adb with options
+function a { $DRY_RUN adb $ADB_OPTS "$@"; }
+
+# restart adb as root and wait for it to come back again
+function adb_root
+{
+    root_status=$(a root)
+    if [ "$root_status" != "adbd is already running as root" ]; then
+        echo -n "Restarting adb as root..."
+        sleep 2
+        a 'wait-for-device'
+        echo done.
+    fi
+}
+
diff --git a/tests/backup/test_restore.sh b/tests/backup/test_restore.sh
index 44b3a28..4506c16 100755
--- a/tests/backup/test_restore.sh
+++ b/tests/backup/test_restore.sh
@@ -14,76 +14,96 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# uncomment for debugging
+#export DRY_RUN="echo"
+source test_backup_common.sh
 
-ADB_OPTS="$@"
+BUGREPORT_DIR="$HOME/backup/bugreports"
 
 function check_file
 {
-    data=$(adb $ADB_OPTS shell cat /data/data/com.android.backuptest/$1)
+    data=$(a shell cat /data/data/com.android.backuptest/$1)
     if [ "$data" = "$2" ] ; then
         echo "$1 has correct value [$2]"
+        return 0
     else
         echo $1 is INCORRECT
         echo "   value:    [$data]"
         echo "   expected: [$2]"
+        return 1
+    fi
+}
+
+function check_exists
+{
+    # return 0 if file exists, 1 otherwise
+    data=$(a shell "ls $@ 2> /dev/null >/dev/null && echo -n exists")
+    if [ "$data" = "exists" ]; then
+        return 0
+    else
+        return 1
     fi
 }
 
 # run adb as root so we can poke at com.android.backuptest's data
-root_status=$(adb $ADB_OPTS root)
-if [ "x$root_status" != "xadbd is already running as root" ]; then
-    echo -n "Restarting adb as root..."
-    sleep 2
-    adb $ADB_OPTS 'wait-for-device'
-    echo done.
-fi
+adb_root
 
 # delete the old data
 echo --- Previous files
-adb $ADB_OPTS shell "ls -l /data/data/com.android.backuptest/files"
-adb $ADB_OPTS shell "rm /data/data/com.android.backuptest/files/*"
+a shell "ls -l /data/data/com.android.backuptest/files"
+a shell "rm /data/data/com.android.backuptest/files/*"
 echo --- Previous shared_prefs
-adb $ADB_OPTS shell "ls -l /data/data/com.android.backuptest/shared_prefs"
-adb $ADB_OPTS shell "rm /data/data/com.android.backuptest/shared_prefs/*"
+a shell "ls -l /data/data/com.android.backuptest/shared_prefs"
+a shell "rm /data/data/com.android.backuptest/shared_prefs/*"
 echo --- Erased files and shared_prefs
-adb $ADB_OPTS shell "ls -l /data/data/com.android.backuptest/files"
-adb $ADB_OPTS shell "ls -l /data/data/com.android.backuptest/shared_prefs"
+a shell "ls -l /data/data/com.android.backuptest/files"
+a shell "ls -l /data/data/com.android.backuptest/shared_prefs"
 echo ---
 
 echo
 echo
-echo
 
 # FIXME: there's probably a smarter way to do this
 # FIXME: if we can get the android ID, that's probably the safest thing to do
 # pick the most recent set and restore from it
-restore_set=$(adb $ADB_OPTS shell bmgr list sets | head -n1 | awk '{print $1}')
+restore_set=$(a shell bmgr list sets | head -n1 | awk '{print $1}')
 
 # run the restore
-printf "Restoring from set %d (hex: 0x%x)\n" $restore_set $restore_set
-adb $ADB_OPTS shell bmgr restore $restore_set
+echo "Restoring from set [$restore_set]"
+a shell bmgr restore "$restore_set"
 
 echo
 echo
-echo
 
 # check the results
-check_file files/file.txt "first file"
-check_file files/another_file.txt "asdf"
-#check_file files/3.txt "3"
-check_file files/empty.txt ""
-check_file shared_prefs/raw.xml '<map><int name="pref" value="1" /></map>'
+export need_bug=0
+
+# make sure files have the expected contents
+check_file files/file.txt "first file" || need_bug=1
+check_file files/another_file.txt "asdf" || need_bug=1
+#check_file files/3.txt "3" || need_bug=1
+check_file files/empty.txt "" || need_bug=1
+check_file shared_prefs/raw.xml '<map><int name="pref" value="1" /></map>' || need_bug=1
+
+# make sure that missing files weren't somehow created
+check_exists files/file_doesnt_exist.txt && need_bug=1
+check_exists files/no_files_here.txt && need_bug=1
+
+if [ \( "$need_bug" -ne 0 \) -a -d "$BUGREPORT_DIR" ]; then
+    dev_id=$(a get-serialno)
+    filename="${dev_id}_`date +%s`"
+    echo "Grabbing bugreport; filename is $filename"
+    a bugreport > "$BUGREPORT_DIR/$filename.txt"
+fi
 
 echo
-echo
-echo
 echo --- Restored files
-adb $ADB_OPTS shell "ls -l /data/data/com.android.backuptest/files"
+a shell "ls -l /data/data/com.android.backuptest/files"
 echo --- Restored shared_prefs
-adb $ADB_OPTS shell "ls -l /data/data/com.android.backuptest/shared_prefs"
+a shell "ls -l /data/data/com.android.backuptest/shared_prefs"
 echo ---
 echo
 
 echo "Last 3 timestamps in 3.txt:"
-adb $ADB_OPTS shell cat /data/data/com.android.backuptest/files/3.txt | tail -n 3
+a shell cat /data/data/com.android.backuptest/files/3.txt | tail -n 3