Merge "Generate /data/system/packages.list in the PackageManager"
diff --git a/Android.mk b/Android.mk
index ec6f96b..7bb5b5f 100644
--- a/Android.mk
+++ b/Android.mk
@@ -33,6 +33,9 @@
 # FRAMEWORKS_BASE_SUBDIRS comes from build/core/pathmap.mk
 LOCAL_SRC_FILES := $(call find-other-java-files,$(FRAMEWORKS_BASE_SUBDIRS))
 
+# EventLogTags files.
+LOCAL_SRC_FILES += core/java/android/content/EventLogTags.logtags
+
 # The following filters out code we are temporarily not including at all.
 # TODO: Move AWT and beans (and associated harmony code) back into libcore.
 # TODO: Maybe remove javax.microedition entirely?
@@ -367,6 +370,8 @@
 
 sample_dir := development/samples
 
+# the list here should match the list of samples included in the sdk samples package
+# (see development/build/sdk.atree)
 web_docs_sample_code_flags := \
 		-hdf android.hasSamples 1 \
 		-samplecode $(sample_dir)/ApiDemos \
@@ -377,6 +382,8 @@
 		            resources/samples/BusinessCard "Business Card" \
 		-samplecode $(sample_dir)/ContactManager \
 		            resources/samples/ContactManager "Contact Manager" \
+                -samplecode $(sample_dir)/CubeLiveWallpaper \
+                            resources/samples/CubeLiveWallpaper "Live Wallpaper" \
 		-samplecode $(sample_dir)/Home \
 		            resources/samples/Home "Home" \
 		-samplecode $(sample_dir)/JetBoy \
@@ -387,6 +394,8 @@
 		            resources/samples/MultiResolution "Multiple Resolutions" \
 		-samplecode $(sample_dir)/NotePad \
 		            resources/samples/NotePad "Note Pad" \
+                -samplecode $(sample_dir)/SampleSyncAdapter \
+                            resources/samples/SampleSyncAdapter "Sample Sync Adapter" \
 		-samplecode $(sample_dir)/SearchableDictionary \
 		            resources/samples/SearchableDictionary "Searchable Dictionary" \
 		-samplecode $(sample_dir)/Snake \
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index b33be23..bdbe341 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -16,6 +16,8 @@
 
 package android.content;
 
+import android.accounts.Account;
+import android.app.ActivityThread;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.AssetFileDescriptor;
 import android.content.res.Resources;
@@ -30,8 +32,8 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.text.TextUtils;
-import android.accounts.Account;
 import android.util.Config;
+import android.util.EventLog;
 import android.util.Log;
 
 import java.io.File;
@@ -41,6 +43,7 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.List;
+import java.util.Random;
 import java.util.ArrayList;
 
 
@@ -163,6 +166,11 @@
     /** @hide */
     public static final int SYNC_OBSERVER_TYPE_ALL = 0x7fffffff;
 
+    // Always log queries which take 100ms+; shorter queries are
+    // sampled accordingly.
+    private static final int SLOW_THRESHOLD_MILLIS = 100;
+    private final Random mRandom = new Random();  // guarded by itself
+
     public ContentResolver(Context context) {
         mContext = context;
     }
@@ -235,12 +243,15 @@
             return null;
         }
         try {
+            long startTime = System.currentTimeMillis();
             Cursor qCursor = provider.query(uri, projection, selection, selectionArgs, sortOrder);
-            if(qCursor == null) {
+            if (qCursor == null) {
                 releaseProvider(provider);
                 return null;
             }
-            //Wrap the cursor object into CursorWrapperInner object
+            long durationMillis = System.currentTimeMillis() - startTime;
+            maybeLogQueryToEventLog(durationMillis, uri, projection, selection, sortOrder);
+            // Wrap the cursor object into CursorWrapperInner object
             return new CursorWrapperInner(qCursor, provider);
         } catch (RemoteException e) {
             releaseProvider(provider);
@@ -572,7 +583,11 @@
             throw new IllegalArgumentException("Unknown URL " + url);
         }
         try {
-            return provider.insert(url, values);
+            long startTime = System.currentTimeMillis();
+            Uri createdRow = provider.insert(url, values);
+            long durationMillis = System.currentTimeMillis() - startTime;
+            maybeLogUpdateToEventLog(durationMillis, url, "insert", null /* where */);
+            return createdRow;
         } catch (RemoteException e) {
             return null;
         } finally {
@@ -627,7 +642,11 @@
             throw new IllegalArgumentException("Unknown URL " + url);
         }
         try {
-            return provider.bulkInsert(url, values);
+            long startTime = System.currentTimeMillis();
+            int rowsCreated = provider.bulkInsert(url, values);
+            long durationMillis = System.currentTimeMillis() - startTime;
+            maybeLogUpdateToEventLog(durationMillis, url, "bulkinsert", null /* where */);
+            return rowsCreated;
         } catch (RemoteException e) {
             return 0;
         } finally {
@@ -652,7 +671,11 @@
             throw new IllegalArgumentException("Unknown URL " + url);
         }
         try {
-            return provider.delete(url, where, selectionArgs);
+            long startTime = System.currentTimeMillis();
+            int rowsDeleted = provider.delete(url, where, selectionArgs);
+            long durationMillis = System.currentTimeMillis() - startTime;
+            maybeLogUpdateToEventLog(durationMillis, url, "delete", where);
+            return rowsDeleted;
         } catch (RemoteException e) {
             return -1;
         } finally {
@@ -680,7 +703,11 @@
             throw new IllegalArgumentException("Unknown URI " + uri);
         }
         try {
-            return provider.update(uri, values, where, selectionArgs);
+            long startTime = System.currentTimeMillis();
+            int rowsUpdated = provider.update(uri, values, where, selectionArgs);
+            long durationMillis = System.currentTimeMillis() - startTime;
+            maybeLogUpdateToEventLog(durationMillis, uri, "update", where);
+            return rowsUpdated;
         } catch (RemoteException e) {
             return -1;
         } finally {
@@ -1217,6 +1244,78 @@
         }
     }
 
+    /**
+     * Returns sampling percentage for a given duration.
+     *
+     * Always returns at least 1%.
+     */
+    private int samplePercentForDuration(long durationMillis) {
+        if (durationMillis >= SLOW_THRESHOLD_MILLIS) {
+            return 100;
+        }
+        return (int) (100 * durationMillis / SLOW_THRESHOLD_MILLIS) + 1;
+    }
+
+    private void maybeLogQueryToEventLog(long durationMillis,
+                                         Uri uri, String[] projection,
+                                         String selection, String sortOrder) {
+        int samplePercent = samplePercentForDuration(durationMillis);
+        if (samplePercent < 100) {
+            synchronized (mRandom) {
+                if (mRandom.nextInt(100) >= samplePercent) {
+                    return;
+                }
+            }
+        }
+
+        StringBuilder projectionBuffer = new StringBuilder(100);
+        if (projection != null) {
+            for (int i = 0; i < projection.length; ++i) {
+                // Note: not using a comma delimiter here, as the
+                // multiple arguments to EventLog.writeEvent later
+                // stringify with a comma delimiter, which would make
+                // parsing uglier later.
+                if (i != 0) projectionBuffer.append('/');
+                projectionBuffer.append(projection[i]);
+            }
+        }
+
+        // ActivityThread.currentPackageName() only returns non-null if the
+        // current thread is an application main thread.  This parameter tells
+        // us whether an event loop is blocked, and if so, which app it is.
+        String blockingPackage = ActivityThread.currentPackageName();
+
+        EventLog.writeEvent(
+            EventLogTags.CONTENT_QUERY_OPERATION,
+            uri.toString(),
+            projectionBuffer.toString(),
+            selection != null ? selection : "",
+            sortOrder != null ? sortOrder : "",
+            durationMillis,
+            blockingPackage != null ? blockingPackage : "",
+            samplePercent);
+    }
+
+    private void maybeLogUpdateToEventLog(
+        long durationMillis, Uri uri, String operation, String selection) {
+        int samplePercent = samplePercentForDuration(durationMillis);
+        if (samplePercent < 100) {
+            synchronized (mRandom) {
+                if (mRandom.nextInt(100) >= samplePercent) {
+                    return;
+                }
+            }
+        }
+        String blockingPackage = ActivityThread.currentPackageName();
+        EventLog.writeEvent(
+            EventLogTags.CONTENT_UPDATE_OPERATION,
+            uri.toString(),
+            operation,
+            selection != null ? selection : "",
+            durationMillis,
+            blockingPackage != null ? blockingPackage : "",
+            samplePercent);
+    }
 
     private final class CursorWrapperInner extends CursorWrapper {
         private IContentProvider mContentProvider;
diff --git a/core/java/android/content/EventLogTags.logtags b/core/java/android/content/EventLogTags.logtags
new file mode 100644
index 0000000..a815b95
--- /dev/null
+++ b/core/java/android/content/EventLogTags.logtags
@@ -0,0 +1,6 @@
+# See system/core/logcat/event.logtags for a description of the format of this file.
+
+option java_package android.content;
+
+52002 content_query_operation (uri|3),(projection|3),(selection|3),(sortorder|3),(time|1|3),(blocking_package|3),(sample_percent|1|6)
+52003 content_update_operation (uri|3),(operation|3),(selection|3),(time|1|3),(blocking_package|3),(sample_percent|1|6)
diff --git a/core/java/android/view/VelocityTracker.java b/core/java/android/view/VelocityTracker.java
index 9581080..9a8ee02 100644
--- a/core/java/android/view/VelocityTracker.java
+++ b/core/java/android/view/VelocityTracker.java
@@ -61,6 +61,7 @@
 
     float mYVelocity[] = new float[MotionEvent.BASE_AVAIL_POINTERS];
     float mXVelocity[] = new float[MotionEvent.BASE_AVAIL_POINTERS];
+    int mLastTouch;
 
     private VelocityTracker mNext;
 
@@ -105,8 +106,11 @@
      * Reset the velocity tracker back to its initial state.
      */
     public void clear() {
-        for (int i = 0; i < MotionEvent.BASE_AVAIL_POINTERS; i++) {
-            mPastTime[i][0] = 0;
+        final long[][] pastTime = mPastTime;
+        for (int p = 0; p < MotionEvent.BASE_AVAIL_POINTERS; p++) {
+            for (int i = 0; i < NUM_PAST; i++) {
+                pastTime[p][i] = 0;
+            }
         }
     }
     
@@ -133,42 +137,11 @@
     }
 
     private void addPoint(int pos, float x, float y, long time) {
-        int drop = -1;
-        int i;
-        if (localLOGV) Log.v(TAG, "Adding past y=" + y + " time=" + time);
-        final long[] pastTime = mPastTime[pos];
-        for (i=0; i<NUM_PAST; i++) {
-            if (pastTime[i] == 0) {
-                break;
-            } else if (pastTime[i] < time-LONGEST_PAST_TIME) {
-                if (localLOGV) Log.v(TAG, "Dropping past too old at "
-                        + i + " time=" + pastTime[i]);
-                drop = i;
-            }
-        }
-        if (localLOGV) Log.v(TAG, "Add index: " + i);
-        if (i == NUM_PAST && drop < 0) {
-            drop = 0;
-        }
-        if (drop == i) drop--;
-        final float[] pastX = mPastX[pos];
-        final float[] pastY = mPastY[pos];
-        if (drop >= 0) {
-            if (localLOGV) Log.v(TAG, "Dropping up to #" + drop);
-            final int start = drop+1;
-            final int count = NUM_PAST-drop-1;
-            System.arraycopy(pastX, start, pastX, 0, count);
-            System.arraycopy(pastY, start, pastY, 0, count);
-            System.arraycopy(pastTime, start, pastTime, 0, count);
-            i -= (drop+1);
-        }
-        pastX[i] = x;
-        pastY[i] = y;
-        pastTime[i] = time;
-        i++;
-        if (i < NUM_PAST) {
-            pastTime[i] = 0;
-        }
+        final int lastTouch = (mLastTouch + 1) % NUM_PAST;
+        mPastX[pos][lastTouch] = x;
+        mPastY[pos][lastTouch] = y;
+        mPastTime[pos][lastTouch] = time;
+        mLastTouch = lastTouch;
     }
 
     /**
@@ -199,36 +172,41 @@
             final float[] pastX = mPastX[pos];
             final float[] pastY = mPastY[pos];
             final long[] pastTime = mPastTime[pos];
-
+            final int lastTouch = mLastTouch;
+        
+            // find oldest acceptable time
+            int oldestTouch = lastTouch;
+            if (pastTime[lastTouch] > 0) { // cleared ?
+                oldestTouch = (lastTouch + 1) % NUM_PAST;
+                final float acceptableTime = pastTime[lastTouch] - LONGEST_PAST_TIME;
+                while (pastTime[oldestTouch] < acceptableTime) {
+                    oldestTouch = (oldestTouch + 1) % NUM_PAST;
+                }
+            }
+        
             // Kind-of stupid.
-            final float oldestX = pastX[0];
-            final float oldestY = pastY[0];
-            final long oldestTime = pastTime[0];
+            final float oldestX = pastX[oldestTouch];
+            final float oldestY = pastY[oldestTouch];
+            final long oldestTime = pastTime[oldestTouch];
             float accumX = 0;
             float accumY = 0;
-            int N=0;
-            while (N < NUM_PAST) {
-                if (pastTime[N] == 0) {
-                    break;
-                }
-                N++;
-            }
+            float N = (lastTouch - oldestTouch + NUM_PAST) % NUM_PAST + 1;
             // Skip the last received event, since it is probably pretty noisy.
             if (N > 3) N--;
 
             for (int i=1; i < N; i++) {
-                final int dur = (int)(pastTime[i] - oldestTime);
+                final int j = (oldestTouch + i) % NUM_PAST;
+                final int dur = (int)(pastTime[j] - oldestTime);
                 if (dur == 0) continue;
-                float dist = pastX[i] - oldestX;
+                float dist = pastX[j] - oldestX;
                 float vel = (dist/dur) * units;   // pixels/frame.
-                if (accumX == 0) accumX = vel;
-                else accumX = (accumX + vel) * .5f;
-
-                dist = pastY[i] - oldestY;
+                accumX = (accumX == 0) ? vel : (accumX + vel) * .5f;
+            
+                dist = pastY[j] - oldestY;
                 vel = (dist/dur) * units;   // pixels/frame.
-                if (accumY == 0) accumY = vel;
-                else accumY = (accumY + vel) * .5f;
+                accumY = (accumY == 0) ? vel : (accumY + vel) * .5f;
             }
+            
             mXVelocity[pos] = accumX < 0.0f ? Math.max(accumX, -maxVelocity)
                     : Math.min(accumX, maxVelocity);
             mYVelocity[pos] = accumY < 0.0f ? Math.max(accumY, -maxVelocity)
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 889985a..fb19dcf 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -8282,7 +8282,7 @@
      */
     public void clearAnimation() {
         if (mCurrentAnimation != null) {
-            mCurrentAnimation.cancel();
+            mCurrentAnimation.detach();
         }
         mCurrentAnimation = null;
     }
diff --git a/core/java/android/view/animation/Animation.java b/core/java/android/view/animation/Animation.java
index ad98259..337fe58 100644
--- a/core/java/android/view/animation/Animation.java
+++ b/core/java/android/view/animation/Animation.java
@@ -277,6 +277,16 @@
     }
 
     /**
+     * @hide
+     */
+    public void detach() {
+        if (mStarted && !mEnded) {
+            if (mListener != null) mListener.onAnimationEnd(this);
+            mEnded = true;
+        }
+    }
+
+    /**
      * Whether or not the animation has been initialized.
      *
      * @return Has this animation been initialized.
diff --git a/docs/html/resources/articles/images/live_wallpapers_small.png b/docs/html/resources/articles/images/live_wallpapers_small.png
new file mode 100644
index 0000000..3b49b24
--- /dev/null
+++ b/docs/html/resources/articles/images/live_wallpapers_small.png
Binary files differ
diff --git a/docs/html/resources/articles/index.jd b/docs/html/resources/articles/index.jd
index 4fda6d7..d2f0996 100644
--- a/docs/html/resources/articles/index.jd
+++ b/docs/html/resources/articles/index.jd
@@ -77,6 +77,11 @@
 </dl>
 
 <dl>
+  <dt><a href="{@docRoot}resources/articles/live-wallpapers.html">Live Wallpapers</a></dt>
+  <dd>Live wallpapers are richer, animated, interactive backgrounds that users can display in their home screens. Learn how to create a live wallpaper and bundle it in an application that users can install on their devices.</dd>
+</dl>
+
+<dl>
   <dt><a href="{@docRoot}resources/articles/on-screen-inputs.html">Onscreen Input Methods</a></dt>
   <dd>The Input Method Framework (IMF) allows users to take advantage of on-screen input methods, such as software keyboards. This article provides an overview of Input Method Editors (IMEs) and how applications interact with them.</dd>
 </dl>
diff --git a/docs/html/resources/articles/live-wallpapers.jd b/docs/html/resources/articles/live-wallpapers.jd
new file mode 100644
index 0000000..8dda879
--- /dev/null
+++ b/docs/html/resources/articles/live-wallpapers.jd
@@ -0,0 +1,84 @@
+page.title=Live Wallpapers
+@jd:body
+
+<p>Starting with Android 2.1 (API Level 7), users can now enjoy <em>live
+wallpapers</em> &mdash; richer, animated, interactive backgrounds &mdash; on
+their home screens. A live wallpaper is very similar to a normal Android
+application and has access to all the facilities of the platform: SGL (2D
+drawing), OpenGL (3D drawing), GPS, accelerometers, network access, etc. The
+live wallpapers included on Nexus One demonstrate the use of some of these APIs
+to create fun and interesting user experiences. For instance, the Grass
+wallpaper uses the phone's location to compute sunrise and sunset times in order
+to display the appropriate sky.</p>
+
+<img src="images/live_wallpapers_small.png" style="align:center" />
+
+<p>Creating your own live wallpaper is easy, especially if you have had
+previous experience with <a
+href="../../../reference/android/view/SurfaceView.html"><code>SurfaceView</code></a> or <a
+href="../../../reference/android/graphics/Canvas.html"><code>Canvas</code></a>. 
+To learn how to create a live wallpaper, you should check out the <a 
+href="../samples/CubeLiveWallpaper/index.html">CubeLiveWallpaper sample code</a>.</p>
+
+<p>In terms of implementation, a live wallpaper is very similar to a regular
+Android <a href="../../../reference/android/app/Service.html">service</a>. The
+only difference is the addition of a new method, <a
+href="../../../reference/android/service/wallpaper/WallpaperService.
+html#onCreateEngine()"><code>onCreateEngine()</code></a>, whose goal is to create a <a
+href="../../../reference/android/service/wallpaper/WallpaperService.Engine.html">
+<code>WallpaperService.Engine</code></a>. The engine is responsible for
+handling the lifecycle and drawing of a wallpaper. The system provides a surface
+on which you can draw, just like you would with a <code>SurfaceView</code></a>.
+Drawing a wallpaper can be very expensive so you should optimize your code
+as much as possible to avoid using too much CPU, not only for battery life
+but also to avoid slowing down the rest of the system. That is also why the
+most important part of the lifecycle of a wallpaper is <a href="../../../reference/android/service/wallpaper/WallpaperService.Engine.html#onVisibilityChanged%28boolean%29">when it becomes invisible</a>. 
+When invisible, such as when the user launches an application that covers
+the home screen, a wallpaper must stop all activity.</p>
+
+<p>The engine can also implement several methods to interact with the user
+or the home application. For instance, if you want your wallpaper to scroll
+along when the user swipes from one home screen to another, you can use <a href="../../../reference/android/service/wallpaper/WallpaperService.Engine.html#onOffsetsChanged%28float,%20float,%20float,%20float,%20int,%20int%29"><code>onOffsetsChanged()</code></a>.
+To react to touch events, simply implement <a href="../../../reference/android/service/wallpaper/WallpaperService.Engine.html#onTouchEvent%28android.view.MotionEvent%29"><code>onTouchEvent(MotionEvent)</code></a>.
+Finally, applications can send arbitrary commands to the live wallpaper.
+Currently, only the standard home application sends commands to the <a
+href="../../../reference/android/service/wallpaper/WallpaperService.Engine.html#onCommand%28java.lang.String,%20int,%20int,%20int,%20android.os.Bundle,%20boolean%29"><code>onCommand()</code></a>
+method of the live wallpaper:</p>
+
+<ul>
+<li><code>android.wallpaper.tap</code>: When the user taps an empty space
+on the workspace. This command is interpreted by the Nexus and Water live
+wallpapers to make the wallpaper react to user interaction. For instance,
+if you tap an empty space on the Water live wallpaper, new ripples appear
+under your finger.</li>
+<li><code>android.home.drop</code>: When the user drops an icon or a widget
+on the workspace. This command is also interpreted by the Nexus and Water
+live wallpapers.</li>
+</ul>
+
+<p>If you are developing a live wallpaper, remember that the feature is
+supported only on Android 2.1 (API level 7) and higher versions of the platform.
+To ensure that your application can only be installed on devices that support
+live wallpapers, remember to add the following to the application's manifest
+before publishing to Android Market:</p>
+
+<ul>
+<li><code>&lt;uses-sdk android:minSdkVersion="7" /&gt;</code>, which indicates
+to Android Market and the platform that your application requires Android 2.1 or
+higher. For more information, see the <a href="../../../guide/appendix/api-levels.html">API
+Levels</a> and the documentation for the
+<a href="../../../guide/topics/manifest/uses-sdk-element.html"><code>&lt;uses-sdk&gt;</code></a>
+element.</li>
+<li><code>&lt;uses-feature android:name="android.software.live_wallpaper" /&gt;</code>,
+which tells Android Market that your application includes a live wallpaper
+Android Market uses this feature as a filter, when presenting users lists of
+available applications. When you declaring this feature, Android Market
+displays your application only to users whose devices support live wallpapers,
+while hiding it from other devices on which it would not be able to run. For
+more information, see the documentation for the
+<a href="../../../guide/topics/manifest/uses-feature-element.html"><code>&lt;uses-feature&gt;</code></a>
+element.</li>
+</ul>
+
+<p>Many great live wallpapers are already available on Android Market and
+we can't wait to see more!</p>
diff --git a/docs/html/resources/resources_toc.cs b/docs/html/resources/resources_toc.cs
index e337e38..0972029 100644
--- a/docs/html/resources/resources_toc.cs
+++ b/docs/html/resources/resources_toc.cs
@@ -83,6 +83,9 @@
         <li><a href="<?cs var:toroot ?>resources/articles/live-folders.html">
                 <span class="en">Live Folders</span>
                 </a></li>
+        <li><a href="<?cs var:toroot ?>resources/articles/live-wallpapers.html">
+                <span class="en">Live Wallpapers</span>
+                </a> <span class="new">new!</span></li>
         <li><a href="<?cs var:toroot ?>resources/articles/on-screen-inputs.html">
                 <span class="en">Onscreen Input Methods</span>
                 </a></li>
@@ -178,28 +181,34 @@
               </a></li>
           <li><a href="<?cs var:toroot ?>resources/samples/BluetoothChat/index.html">
                 <span class="en">Bluetooth Chat</span>
-              </a> <span class="new">new!</span></li>
+              </a></li>
           <li><a href="<?cs var:toroot ?>resources/samples/BusinessCard/index.html">
                 <span class="en">Business Card</span>
-              </a> <span class="new">new!</span></li>
+              </a></li>
           <li><a href="<?cs var:toroot ?>resources/samples/ContactManager/index.html">
                 <span class="en">Contact Manager</span>
-              </a> <span class="new">new!</span></li>
+              </a></li>
           <li><a href="<?cs var:toroot ?>resources/samples/Home/index.html">
                 <span class="en">Home</span>
               </a></li>
           <li><a href="<?cs var:toroot ?>resources/samples/JetBoy/index.html">
                 <span class="en">JetBoy</span>
               </a></li>
+          <li><a href="<?cs var:toroot ?>resources/samples/CubeLiveWallpaper/index.html">
+                <span class="en">Live Wallpaper</span>
+                </a> <span class="new">new!</span></li>
           <li><a href="<?cs var:toroot ?>resources/samples/LunarLander/index.html">
                 <span class="en">Lunar Lander</span>
               </a></li>
           <li><a href="<?cs var:toroot ?>resources/samples/MultiResolution/index.html">
                 <span class="en">Multiple Resolutions</span>
-              </a> <span class="new">new!</span></li>
+              </a></li>
           <li><a href="<?cs var:toroot ?>resources/samples/NotePad/index.html">
                 <span class="en">Note Pad</span>
               </a></li>
+          <li><a href="<?cs var:toroot ?>resources/samples/SampleSyncAdapter/index.html">
+                <span class="en">Sample Sync Adapter</span>
+              </a> <span class="new">new!</span></li>
           <li><a href="<?cs var:toroot ?>resources/samples/SearchableDictionary/index.html">
                 <span class="en">Searchable Dictionary</span>
               </a></li>
@@ -211,10 +220,10 @@
               </a></li>
           <li><a href="<?cs var:toroot ?>resources/samples/Wiktionary/index.html">
                 <span class="en">Wiktionary</span>
-              </a> <span class="new">new!</span></li>
+              </a></li>
           <li><a href="<?cs var:toroot ?>resources/samples/WiktionarySimple/index.html">
                 <span class="en">Wiktionary (Simplified)</span>
-              </a> <span class="new">new!</span></li>
+              </a></li>
         </ul>
       </li>
     </ul>
diff --git a/docs/html/resources/samples/images/CubeLiveWallpaper1.png b/docs/html/resources/samples/images/CubeLiveWallpaper1.png
new file mode 100644
index 0000000..55bc1e9
--- /dev/null
+++ b/docs/html/resources/samples/images/CubeLiveWallpaper1.png
Binary files differ
diff --git a/docs/html/resources/samples/images/CubeLiveWallpaper3.png b/docs/html/resources/samples/images/CubeLiveWallpaper3.png
new file mode 100644
index 0000000..2747a88
--- /dev/null
+++ b/docs/html/resources/samples/images/CubeLiveWallpaper3.png
Binary files differ
diff --git a/docs/html/resources/samples/index.jd b/docs/html/resources/samples/index.jd
index 0beb781..5ebf41c 100644
--- a/docs/html/resources/samples/index.jd
+++ b/docs/html/resources/samples/index.jd
@@ -27,10 +27,10 @@
 platforms) and allow you to view the source files in your browser. </p>
 
 <div class="special">
-  <p>Some of the samples in this listing are not yet available in the
-  SDK. While we work to update the SDK, you can
-  <a href="{@docRoot}shareables/latest_samples.zip">download the latest samples</a> as a ZIP
-  archive.</p>
+  <p>Some of the samples in this listing may not yet be available in the
+  SDK. To ensure that you have the latest versions of the samples, you can
+  <a href="{@docRoot}shareables/latest_samples.zip">download the samples pack</a>
+  as a .zip archive.</p>
 </div>
 
 <dl>
@@ -55,11 +55,15 @@
 
  <dt><a href="Home/index.html">Home</a></dt>
   <dd>A home screen replacement application.</dd>
-  
+
  <dt><a href="JetBoy/index.html">JetBoy</a></dt>
   <dd>A game that demonstrates the SONiVOX JET interactive music technology,
   with {@link android.media.JetPlayer}.</dd>
-    
+
+ <dt><a href="CubeLiveWallpaper/index.html">Live Wallpaper</a></dt>
+  <dd>An application that demonstrates how to create a live wallpaper and 
+  bundle it in an application that users can install on their devices.</dd>
+
  <dt><a href="LunarLander/index.html">Lunar Lander</a></dt>
   <dd>A classic Lunar Lander game.</dd>
 
@@ -70,14 +74,21 @@
  <dt><a href="NotePad/index.html">Note Pad</a></dt>
   <dd>An application for saving notes. Similar (but not identical) to the 
     <a href="{@docRoot}resources/tutorials/notepad/index.html">Notepad tutorial</a>.</dd>
-  
+
+ <dt><a href="SampleSyncAdapter/index.html">SampleSyncAdapter</a></dt>
+  <dd>Demonstrates how an application can communicate with a
+cloud-based service and synchronize its data with data stored locally in a
+content provider. The sample uses two related parts of the Android framework
+&mdash; the account manager and the synchronization manager (through a sync
+adapter).</dd>
+
  <dt><a href="SearchableDictionary/index.html">Searchable Dictionary</a></dt>
   <dd>A sample application that demonstrates Android's search framework, 
   including how to provide search suggestions for Quick Search Box.</dd>
-  
+
  <dt><a href="Snake/index.html">Snake</a></dt>
   <dd>An implementation of the classic game "Snake."</dd>
-  
+
  <dt><a href="SoftKeyboard/index.html">Soft Keyboard</a></dt>
   <dd>An example of writing an input method for a software keyboard.</dd>