Merge "add preview functionality to the bug report sender.  lets users preview system logs, memory info, cpu info, and procrank."
diff --git a/build/sdk.atree b/build/sdk.atree
index 845ddea..f3bd0c6 100644
--- a/build/sdk.atree
+++ b/build/sdk.atree
@@ -72,7 +72,10 @@
 # emacs support from sdk.git
 sdk/files/android.el tools/lib/android.el
 
-# samples
+# samples to include in the sdk samples package
+#
+# the list here should match the list of samples that we generate docs for, 
+# (see web_docs_sample_code_flags in frameworks/base/Android.mk)
 development/samples/source.properties     samples/${PLATFORM_NAME}/source.properties
 development/apps/GestureBuilder           samples/${PLATFORM_NAME}/GestureBuilder
 development/samples/BluetoothChat         samples/${PLATFORM_NAME}/BluetoothChat
@@ -80,6 +83,7 @@
 development/samples/LunarLander           samples/${PLATFORM_NAME}/LunarLander
 development/samples/NotePad               samples/${PLATFORM_NAME}/NotePad
 development/samples/ApiDemos              samples/${PLATFORM_NAME}/ApiDemos
+development/samples/SampleSyncAdapter     samples/${PLATFORM_NAME}/SampleSyncAdapter
 development/samples/SkeletonApp           samples/${PLATFORM_NAME}/SkeletonApp
 development/samples/Snake                 samples/${PLATFORM_NAME}/Snake
 development/samples/SoftKeyboard          samples/${PLATFORM_NAME}/SoftKeyboard
diff --git a/samples/ApiDemos/AndroidManifest.xml b/samples/ApiDemos/AndroidManifest.xml
index e45e19c..fb416ed 100644
--- a/samples/ApiDemos/AndroidManifest.xml
+++ b/samples/ApiDemos/AndroidManifest.xml
@@ -28,6 +28,7 @@
     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.SET_WALLPAPER" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 
     <!-- We will request access to the camera, saying we require a camera
          of some sort but not one with autofocus capability. -->
@@ -588,6 +589,14 @@
         <!--        CONTENT PACKAGE SAMPLES        -->
         <!-- ************************************* -->
 
+        <activity android:name=".content.ExternalStorage" android:label="@string/activity_external_storage">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.SAMPLE_CODE" />
+                <category android:name="android.intent.category.EMBED" />
+            </intent-filter>
+        </activity>
+
         <activity android:name=".content.StyledText" android:label="@string/activity_styled_text">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
diff --git a/samples/ApiDemos/res/layout/external_storage.xml b/samples/ApiDemos/res/layout/external_storage.xml
new file mode 100644
index 0000000..28105a3
--- /dev/null
+++ b/samples/ApiDemos/res/layout/external_storage.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:scrollbars="none">
+
+    <LinearLayout
+        android:id="@+id/layout"
+        android:orientation="vertical"
+        android:layout_width="match_parent" android:layout_height="wrap_content">
+    </LinearLayout>
+</ScrollView>
diff --git a/samples/ApiDemos/res/layout/external_storage_item.xml b/samples/ApiDemos/res/layout/external_storage_item.xml
new file mode 100644
index 0000000..6ba058b
--- /dev/null
+++ b/samples/ApiDemos/res/layout/external_storage_item.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent" android:layout_height="wrap_content">
+    <TextView android:id="@+id/label" style="?android:attr/textAppearanceMediumInverse"
+        android:layout_width="match_parent" android:layout_height="wrap_content"
+        android:layout_weight="0"
+        android:padding="4dip"
+        android:singleLine="true"
+        android:color="?android:attr/textColorPrimaryInverse"
+        android:background="#888" />
+    <TextView android:id="@+id/path" style="?android:attr/textAppearanceSmall"
+        android:layout_width="match_parent" android:layout_height="wrap_content"
+        android:layout_weight="0"
+        android:padding="4dip"
+        android:singleLine="true" />
+    <LinearLayout
+        android:orientation="horizontal"
+        android:layout_width="match_parent" android:layout_height="wrap_content">
+        <View
+           android:layout_width="0dip"
+           android:layout_height="0dip"
+           android:layout_weight="1" />
+        <Button android:id="@+id/create"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:text="@string/create" />
+        <View
+           android:layout_width="0dip"
+           android:layout_height="0dip"
+           android:layout_weight="1" />
+        <Button android:id="@+id/delete"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:text="@string/delete" />
+        <View
+           android:layout_width="0dip"
+           android:layout_height="0dip"
+           android:layout_weight="1" />
+    </LinearLayout>
+</LinearLayout>
diff --git a/samples/ApiDemos/res/values/strings.xml b/samples/ApiDemos/res/values/strings.xml
index 415e681..3ab923b 100644
--- a/samples/ApiDemos/res/values/strings.xml
+++ b/samples/ApiDemos/res/values/strings.xml
@@ -228,6 +228,10 @@
     <!--  app/content examples strings  -->
     <!-- ============================== -->
 
+    <string name="activity_external_storage">Content/Storage/External Storage</string>
+    <string name="create">Create</string>
+    <string name="delete">Delete</string>
+    
     <string name="activity_styled_text">Content/Resources/<i>Styled</i> <b>Text</b></string>
     <string name="styled_text_rsrc">Initialized from a resource:</string>
     <string name="styled_text">Plain, <b>bold</b>, <i>italic</i>, <b><i>bold-italic</i></b></string>
diff --git a/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java b/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java
new file mode 100644
index 0000000..d950a2c
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java
@@ -0,0 +1,376 @@
+/*
+ * Copyright (C) 2010 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 com.example.android.apis.content;
+
+//Need the following import to get access to the app resources, since this
+//class is in a sub-package.
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.media.MediaScannerConnection;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Environment;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.TextView;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+
+/**
+* Demonstration of styled text resources.
+*/
+public class ExternalStorage extends Activity {
+    ViewGroup mLayout;
+    
+    static class Item {
+        View mRoot;
+        Button mCreate;
+        Button mDelete;
+    }
+    
+    Item mExternalStoragePublicPicture;
+    Item mExternalStoragePrivatePicture;
+    Item mExternalStoragePrivateFile;
+    
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.external_storage);
+        mLayout = (ViewGroup)findViewById(R.id.layout);
+        mExternalStoragePublicPicture = createStorageControls(
+                "Picture: getExternalStoragePublicDirectory",
+                Environment.getExternalStoragePublicDirectory(
+                        Environment.DIRECTORY_PICTURES),
+                new View.OnClickListener() {
+                    public void onClick(View v) {
+                        createExternalStoragePublicPicture();
+                        updateExternalStorageState();
+                    }
+                },
+                new View.OnClickListener() {
+                    public void onClick(View v) {
+                        deleteExternalStoragePublicPicture();
+                        updateExternalStorageState();
+                    }
+                });
+        mLayout.addView(mExternalStoragePublicPicture.mRoot);
+        mExternalStoragePrivatePicture = createStorageControls(
+                "Picture getExternalFilesDir",
+                getExternalFilesDir(Environment.DIRECTORY_PICTURES),
+                new View.OnClickListener() {
+                    public void onClick(View v) {
+                        createExternalStoragePrivatePicture();
+                        updateExternalStorageState();
+                    }
+                },
+                new View.OnClickListener() {
+                    public void onClick(View v) {
+                        deleteExternalStoragePrivatePicture();
+                        updateExternalStorageState();
+                    }
+                });
+        mLayout.addView(mExternalStoragePrivatePicture.mRoot);
+        mExternalStoragePrivateFile = createStorageControls(
+                "File getExternalFilesDir",
+                getExternalFilesDir(null),
+                new View.OnClickListener() {
+                    public void onClick(View v) {
+                        createExternalStoragePrivateFile();
+                        updateExternalStorageState();
+                    }
+                },
+                new View.OnClickListener() {
+                    public void onClick(View v) {
+                        deleteExternalStoragePrivateFile();
+                        updateExternalStorageState();
+                    }
+                });
+        mLayout.addView(mExternalStoragePrivateFile.mRoot);
+        
+        startWatchingExternalStorage();
+    }
+    
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        stopWatchingExternalStorage();
+    }
+
+    void handleExternalStorageState(boolean available, boolean writeable) {
+        boolean has = hasExternalStoragePublicPicture();
+        mExternalStoragePublicPicture.mCreate.setEnabled(writeable && !has);
+        mExternalStoragePublicPicture.mDelete.setEnabled(writeable && has);
+        has = hasExternalStoragePrivatePicture();
+        mExternalStoragePrivatePicture.mCreate.setEnabled(writeable && !has);
+        mExternalStoragePrivatePicture.mDelete.setEnabled(writeable && has);
+        has = hasExternalStoragePrivateFile();
+        mExternalStoragePrivateFile.mCreate.setEnabled(writeable && !has);
+        mExternalStoragePrivateFile.mDelete.setEnabled(writeable && has);
+    }
+    
+// BEGIN_INCLUDE(monitor_storage)
+    BroadcastReceiver mExternalStorageReceiver;
+    boolean mExternalStorageAvailable = false;
+    boolean mExternalStorageWriteable = false;
+    
+    void updateExternalStorageState() {
+        String state = Environment.getExternalStorageState();
+        if (Environment.MEDIA_MOUNTED.equals(state)) {
+            mExternalStorageAvailable = mExternalStorageWriteable = true;
+        } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
+            mExternalStorageAvailable = true;
+            mExternalStorageWriteable = false;
+        } else {
+            mExternalStorageAvailable = mExternalStorageWriteable = false;
+        }
+        handleExternalStorageState(mExternalStorageAvailable,
+                mExternalStorageWriteable);
+    }
+    
+    void startWatchingExternalStorage() {
+        mExternalStorageReceiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                Log.i("test", "Storage: " + intent.getData());
+                updateExternalStorageState();
+            }
+        };
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
+        filter.addAction(Intent.ACTION_MEDIA_REMOVED);
+        registerReceiver(mExternalStorageReceiver, filter);
+        updateExternalStorageState();
+    }
+    
+    void stopWatchingExternalStorage() {
+        unregisterReceiver(mExternalStorageReceiver);
+    }
+ // END_INCLUDE(monitor_storage)
+    
+ // BEGIN_INCLUDE(public_picture)
+    void createExternalStoragePublicPicture() {
+        // Create a path where we will place our picture in the user's
+        // public pictures directory.  Note that you should be careful about
+        // what you place here, since the user often manages these files.  For
+        // pictures and other media owned by the application, consider
+        // Context.getExternalMediaDir().
+        File path = Environment.getExternalStoragePublicDirectory(
+                Environment.DIRECTORY_PICTURES);
+        File file = new File(path, "DemoPicture.jpg");
+        
+        try {
+            // Make sure the Pictures directory exists.
+            path.mkdirs();
+            
+            // Very simple code to copy a picture from the application's
+            // resource into the external file.  Note that this code does
+            // no error checking, and assumes the picture is small (does not
+            // try to copy it in chunks).  Note that if external storage is
+            // not currently mounted this will silently fail.
+            InputStream is = getResources().openRawResource(R.drawable.balloons);
+            OutputStream os = new FileOutputStream(file);
+            byte[] data = new byte[is.available()];
+            is.read(data);
+            os.write(data);
+            is.close();
+            os.close();
+            
+            // Tell the media scanner about the new file so that it is
+            // immediately available to the user.
+            MediaScannerConnection.scanFile(this,
+                    new String[] { file.toString() }, null,
+                    new MediaScannerConnection.ScanResultListener() {
+                public void onScanCompleted(String path, Uri uri) {
+                    Log.i("ExternalStorage", "Scanned " + path + ":");
+                    Log.i("ExternalStorage", "-> uri=" + uri);
+                }
+            });
+        } catch (IOException e) {
+            // Unable to create file, likely because external storage is
+            // not currently mounted.
+            Log.w("ExternalStorage", "Error writing " + file, e);
+        }
+    }
+    
+    void deleteExternalStoragePublicPicture() {
+        // Create a path where we will place our picture in the user's
+        // public pictures directory and delete the file.  If external
+        // storage is not currently mounted this will fail.
+        File path = Environment.getExternalStoragePublicDirectory(
+                Environment.DIRECTORY_PICTURES);
+        File file = new File(path, "DemoPicture.jpg");
+        file.delete();
+    }
+    
+    boolean hasExternalStoragePublicPicture() {
+        // Create a path where we will place our picture in the user's
+        // public pictures directory and check if the file exists.  If
+        // external storage is not currently mounted this will think the
+        // picture doesn't exist.
+        File path = Environment.getExternalStoragePublicDirectory(
+                Environment.DIRECTORY_PICTURES);
+        File file = new File(path, "DemoPicture.jpg");
+        return file.exists();
+    }
+// END_INCLUDE(public_picture)
+    
+// BEGIN_INCLUDE(private_picture)
+    void createExternalStoragePrivatePicture() {
+        // Create a path where we will place our picture in our own private
+        // pictures directory.  Note that we don't really need to place a
+        // picture in DIRECTORY_PICTURES, since the media scanner will see
+        // all media in these directories; this may be useful with other
+        // media types such as DIRECTORY_MUSIC however to help it classify
+        // your media for display to the user.
+        File path = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
+        File file = new File(path, "DemoPicture.jpg");
+        
+        try {
+            // Very simple code to copy a picture from the application's
+            // resource into the external file.  Note that this code does
+            // no error checking, and assumes the picture is small (does not
+            // try to copy it in chunks).  Note that if external storage is
+            // not currently mounted this will silently fail.
+            InputStream is = getResources().openRawResource(R.drawable.balloons);
+            OutputStream os = new FileOutputStream(file);
+            byte[] data = new byte[is.available()];
+            is.read(data);
+            os.write(data);
+            is.close();
+            os.close();
+            
+            // Tell the media scanner about the new file so that it is
+            // immediately available to the user.
+            MediaScannerConnection.scanFile(this,
+                    new String[] { file.toString() }, null,
+                    new MediaScannerConnection.ScanResultListener() {
+                public void onScanCompleted(String path, Uri uri) {
+                    Log.i("ExternalStorage", "Scanned " + path + ":");
+                    Log.i("ExternalStorage", "-> uri=" + uri);
+                }
+            });
+        } catch (IOException e) {
+            // Unable to create file, likely because external storage is
+            // not currently mounted.
+            Log.w("ExternalStorage", "Error writing " + file, e);
+        }
+    }
+    
+    void deleteExternalStoragePrivatePicture() {
+        // Create a path where we will place our picture in the user's
+        // public pictures directory and delete the file.  If external
+        // storage is not currently mounted this will fail.
+        File path = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
+        if (path != null) {
+            File file = new File(path, "DemoPicture.jpg");
+            file.delete();
+        }
+    }
+    
+    boolean hasExternalStoragePrivatePicture() {
+        // Create a path where we will place our picture in the user's
+        // public pictures directory and check if the file exists.  If
+        // external storage is not currently mounted this will think the
+        // picture doesn't exist.
+        File path = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
+        if (path != null) {
+            File file = new File(path, "DemoPicture.jpg");
+            return file.exists();
+        }
+        return false;
+    }
+// END_INCLUDE(private_picture)
+        
+// BEGIN_INCLUDE(private_file)
+     void createExternalStoragePrivateFile() {
+         // Create a path where we will place our private file on external
+         // storage.
+         File file = new File(getExternalFilesDir(null), "DemoFile.jpg");
+         
+         try {
+             // Very simple code to copy a picture from the application's
+             // resource into the external file.  Note that this code does
+             // no error checking, and assumes the picture is small (does not
+             // try to copy it in chunks).  Note that if external storage is
+             // not currently mounted this will silently fail.
+             InputStream is = getResources().openRawResource(R.drawable.balloons);
+             OutputStream os = new FileOutputStream(file);
+             byte[] data = new byte[is.available()];
+             is.read(data);
+             os.write(data);
+             is.close();
+             os.close();
+         } catch (IOException e) {
+             // Unable to create file, likely because external storage is
+             // not currently mounted.
+             Log.w("ExternalStorage", "Error writing " + file, e);
+         }
+     }
+     
+     void deleteExternalStoragePrivateFile() {
+         // Get path for the file on external storage.  If external
+         // storage is not currently mounted this will fail.
+         File file = new File(getExternalFilesDir(null), "DemoFile.jpg");
+         if (file != null) {
+             file.delete();
+         }
+     }
+     
+     boolean hasExternalStoragePrivateFile() {
+         // Get path for the file on external storage.  If external
+         // storage is not currently mounted this will fail.
+         File file = new File(getExternalFilesDir(null), "DemoFile.jpg");
+         if (file != null) {
+             return file.exists();
+         }
+         return false;
+     }
+ // END_INCLUDE(private_file)
+     
+    Item createStorageControls(CharSequence label, File path,
+            View.OnClickListener createClick,
+            View.OnClickListener deleteClick) {
+        LayoutInflater inflater = (LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE);
+        Item item = new Item();
+        item.mRoot = inflater.inflate(R.layout.external_storage_item, null);
+        TextView tv = (TextView)item.mRoot.findViewById(R.id.label);
+        tv.setText(label);
+        if (path != null) {
+            tv = (TextView)item.mRoot.findViewById(R.id.path);
+            tv.setText(path.toString());
+        }
+        item.mCreate = (Button)item.mRoot.findViewById(R.id.create);
+        item.mCreate.setOnClickListener(createClick);
+        item.mDelete = (Button)item.mRoot.findViewById(R.id.delete);
+        item.mDelete.setOnClickListener(deleteClick);
+        return item;
+    }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/content/_index.html b/samples/ApiDemos/src/com/example/android/apis/content/_index.html
index 1aa52b3..769a927 100644
--- a/samples/ApiDemos/src/com/example/android/apis/content/_index.html
+++ b/samples/ApiDemos/src/com/example/android/apis/content/_index.html
@@ -1,5 +1,8 @@
 <h3>Resources</h3>
 <dl>
+  <dt><a href="StyledText.html">External Storage</a></dt>
+  <dd>Demonstrates reading and writing files in external storage. </dd>
+
   <dt><a href="StyledText.html">Styled Text</a></dt>
   <dd>Demonstrates loading styled text (bold, italic) defined in a resource file. </dd>
 
diff --git a/samples/CubeLiveWallpaper/AndroidManifest.xml b/samples/CubeLiveWallpaper/AndroidManifest.xml
index c317fe2..8a7d527 100644
--- a/samples/CubeLiveWallpaper/AndroidManifest.xml
+++ b/samples/CubeLiveWallpaper/AndroidManifest.xml
@@ -21,6 +21,7 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.example.android.livecubes">
 
+    <uses-sdk android:minSdkVersion="7" />
     <uses-feature android:name="android.software.live_wallpaper" />
 
     <uses-feature android:name="android.software.live_wallpaper" />
diff --git a/samples/CubeLiveWallpaper/_index.html b/samples/CubeLiveWallpaper/_index.html
new file mode 100644
index 0000000..f6aa931
--- /dev/null
+++ b/samples/CubeLiveWallpaper/_index.html
@@ -0,0 +1,83 @@
+<p>This sample demonstrates how to create a live wallpaper and bundle it in an
+<code>.apk</code> that users can install on their devices.</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 <a
+href="../../../reference/android/view/SurfaceView.html"><code>SurfaceView</code></a>.
+The wallpapers you create can respond to touch events on the screen and
+have access to all the facilities of the platform: SGL (2D drawing), OpenGL (3D
+drawing), GPS, accelerometers, network access, and so on. </p>
+
+<p>The examples in this application show how to set up a wallpaper service that
+creates a <code>WallpaperService.Engine</code> to manage the service lifecycle,
+render the wallpaper, handle touch events, and so on. The examples also show how
+a wallpaper should stop drawing when its visibility changes, for example, when
+the user launches an application that covers the home screen. Drawing only when
+visible is an important implementation guideline for live wallpapers because it
+minimizes the wallpaper's impact on system performance and battery life.
+</p>
+
+<p>The application includes two wallpaper services and a wallpaper settings 
+activity:<p>
+
+<ul>
+<li><a
+href="src/com/example/android/livecubes/cube1/CubeWallpaper1.html"><code>
+CubeWallpaper1</code></a> &mdash; a wallpaper service that draws and animates a
+wire-frame cube to a <a
+href="../../../reference/android/graphics/Canvas.html"><code>Canvas</code></a>.
+</li>
+<li><a
+href="src/com/example/android/livecubes/cube2/CubeWallpaper2.html"><code>CubeWallpaper2</code></a>
+&mdash; a wallpaper service that draws and animates a
+wire-frame shape to a <code>Canvas</code>. The shape is set by the user, by means
+of the <code>cube2.CubeWallpaper2Settings</code> settings activity (see below). The
+wallpaper service implements a listener callback method that captures the user's
+wallpaper shape preference. </li>
+<li><a
+href="src/com/example/android/livecubes/cube2/CubeWallpaper2Settings.html"><code>CubeWallpaper2Settings</code></a>
+&mdash; a wallpaper service that draws and
+animates a wire-frame shape to a <code>Canvas</code>. The shape is set by the
+user through a simple settings activity,
+<code>cube2.CubeWallpaper2Settings</code>, also included in the app. The
+wallpaper service implements a listener callback method that captures the user's
+wallpaper shape preference. </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>For more information about live wallpapers, see the 
+<a href="../../articles/live-wallpapers.html">Live Wallpapers</a> article. </p>
+
+<img alt="Screenshot 1" src="../images/CubeLiveWallpaper1.png" />
+<img alt="Screenshot 3" src="../images/CubeLiveWallpaper3.png" />
diff --git a/samples/MarketLicensing/src/com/android/vending/licensing/ILicenseResultListener.aidl b/samples/MarketLicensing/src/com/android/vending/licensing/ILicenseResultListener.aidl
deleted file mode 100755
index 869cb16..0000000
--- a/samples/MarketLicensing/src/com/android/vending/licensing/ILicenseResultListener.aidl
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2010 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 com.android.vending.licensing;
-
-oneway interface ILicenseResultListener {
-  void verifyLicense(int responseCode, String signedData, String signature);
-}
diff --git a/samples/MarketLicensing/src/com/android/vending/licensing/ILicensingService.aidl b/samples/MarketLicensing/src/com/android/vending/licensing/ILicensingService.aidl
deleted file mode 100755
index 9541a20..0000000
--- a/samples/MarketLicensing/src/com/android/vending/licensing/ILicensingService.aidl
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2010 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 com.android.vending.licensing;
-
-import com.android.vending.licensing.ILicenseResultListener;
-
-oneway interface ILicensingService {
-  void checkLicense(long nonce, String packageName, in ILicenseResultListener listener);
-}
diff --git a/samples/MarketLicensing/src/com/android/vending/licensing/LicenseChecker.java b/samples/MarketLicensing/src/com/android/vending/licensing/LicenseChecker.java
deleted file mode 100755
index 773b8cd..0000000
--- a/samples/MarketLicensing/src/com/android/vending/licensing/LicenseChecker.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*

- * Copyright (C) 2010 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 com.android.vending.licensing;

-

-import java.security.SecureRandom;

-

-import android.content.ComponentName;

-import android.content.Context;

-import android.content.Intent;

-import android.content.ServiceConnection;

-import android.content.pm.PackageManager.NameNotFoundException;

-import android.os.IBinder;

-import android.os.RemoteException;

-import android.util.Log;

-

-import com.android.vending.licensing.LicenseCheckerCallback.ApplicationErrorCode;

-import com.android.vending.licensing.Policy.LicenseResponse;

-

-/**

- * Client library for Android Market license verifications.

- *

- * The LicenseChecker is configured via a {@link Policy} which contains the

- * logic to determine whether a user should have access to the application.

- * For example, the Policy can define a threshold for allowable number of

- * server or client failures before the library reports the user as not having

- * access.

- *

- * This library is not thread-safe. Multiple, concurrent checks will result in

- * an error.

- */

-public class LicenseChecker implements ServiceConnection {

-    private static final String TAG = "LicenseChecker";

-

-    private static final SecureRandom RANDOM = new SecureRandom();

-

-    private ILicensingService mService;

-

-    /** Validator for the request in progress. */

-    private LicenseValidator mValidator;

-

-    private final Context mContext;

-    private final Policy mPolicy;

-    /** Listener for service (IPC) calls. */

-    private final ResultListener mListener;

-    private final String mPackageName;

-    private final String mVersionCode;

-

-    public LicenseChecker(Context context, Policy policy) {

-        mContext = context;

-        mPolicy = policy;

-        mListener = new ResultListener();

-        mPackageName = mContext.getPackageName();

-        mVersionCode = getVersionCode(context, mPackageName);

-    }

-

-    private boolean isInProgress() {

-        return mValidator != null;

-    }

-

-    /**

-     * Checks if the user should have access to the app.

-     *

-     * @param callback

-     */

-    public synchronized void checkAccess(LicenseCheckerCallback callback) {

-        if (isInProgress()) {

-            callback.applicationError(ApplicationErrorCode.CHECK_IN_PROGRESS);

-        }

-

-        mValidator = new LicenseValidator(mPolicy, callback, generateNonce(), mPackageName,

-            mVersionCode);

-

-        Log.i(TAG, "Binding to licensing service.");

-        boolean bindResult = mContext.bindService(new Intent(ILicensingService.class.getName()),

-            this,  // ServiceConnection.

-            Context.BIND_AUTO_CREATE);

-

-        if (!bindResult) {

-            Log.e(TAG, "Could not bind to service.");

-            callback.dontAllow();

-            // No need to unbind at this point.

-            return;

-        }

-    }

-

-    private class ResultListener extends ILicenseResultListener.Stub {

-        public void verifyLicense(int responseCode, String signedData, String signature) {

-            mValidator.verify(responseCode, signedData, signature);

-            cleanup();

-        }

-    }

-

-    public void onServiceConnected(ComponentName name, IBinder service) {

-        mService = ILicensingService.Stub.asInterface(service);

-

-        try {

-            Log.i(TAG, "Calling checkLicense on service for " + mValidator.getPackageName());

-            mService.checkLicense(mValidator.getNonce(), mValidator.getPackageName(), mListener);

-        } catch (RemoteException e) {

-            Log.w(TAG, "RemoteException in checkLicense call.", e);

-            handleServiceConnectionError();

-            // cleanup unbinds service.

-            cleanup();

-        }

-    }

-

-    public void onServiceDisconnected(ComponentName name) {

-        // Called when the connection with the service has been

-        // unexpectedly disconnected. That is, Market crashed.

-        Log.w(TAG, "Service unexpectedly disconnected.");

-        handleServiceConnectionError();

-        // cleanup unbinds service.

-        cleanup();

-    }

-

-    private void handleServiceConnectionError() {

-        if (mPolicy.allowAccess(LicenseResponse.CLIENT_RETRY)) {

-            mValidator.getCallback().allow();

-        } else {

-            mValidator.getCallback().dontAllow();

-        }

-    }

-

-    /** Resets request state. */

-    private synchronized void cleanup() {

-        mContext.unbindService(this);

-        mValidator = null;

-    }

-

-    /** Generates a nonce (number used once). */

-    private int generateNonce() {

-        return RANDOM.nextInt();

-    }

-

-    /**

-     * Get version code for the application package name.

-     *

-     * @param context

-     * @param packageName application package name

-     * @return the version code or empty string if package not found

-     */

-    private static String getVersionCode(Context context, String packageName) {

-        try {

-            return String.valueOf(context.getPackageManager().getPackageInfo(packageName, 0).

-                versionCode);

-        } catch (NameNotFoundException e) {

-            Log.e(TAG, "Package not found. could not get version code.");

-            return "";

-        }

-    }

-}

diff --git a/samples/MarketLicensing/src/com/android/vending/licensing/LicenseCheckerCallback.java b/samples/MarketLicensing/src/com/android/vending/licensing/LicenseCheckerCallback.java
deleted file mode 100755
index 1567497..0000000
--- a/samples/MarketLicensing/src/com/android/vending/licensing/LicenseCheckerCallback.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*

- * Copyright (C) 2010 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 com.android.vending.licensing;

-

-/**

- * Callback for the license checker library.

- *

- * Upon checking with the Market server and conferring with the policy, the

- * library calls a appropriate callback method to communicate the result.

- */

-public interface LicenseCheckerCallback {

-

-    /**

-     * Allow use. App should proceed as normal.

-     */

-    public void allow();

-

-    /**

-     * Don't allow use. App should inform user and take appropriate action.

-     */

-    public void dontAllow();

-

-    /** Application error codes. */

-    public enum ApplicationErrorCode {

-        /** Package is not installed. */

-        INVALID_PACKAGE_NAME,

-        /** Requested for a package that is not the current app. */

-        NON_MATCHING_UID,

-        /** Market does not know about the package. */

-        NOT_MARKET_MANAGED,

-        /** A previous check request is already in progress.

-         * Only one check is allowed at a time. */

-        CHECK_IN_PROGRESS

-    }

-

-    /**

-     * Error in application code. Caller did not call or set up license

-     * checker correctly. Should be considered fatal.

-     */

-    public void applicationError(ApplicationErrorCode errorCode);

-}

diff --git a/samples/MarketLicensing/src/com/android/vending/licensing/LicenseValidator.java b/samples/MarketLicensing/src/com/android/vending/licensing/LicenseValidator.java
deleted file mode 100755
index 135d98e..0000000
--- a/samples/MarketLicensing/src/com/android/vending/licensing/LicenseValidator.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*

- * Copyright (C) 2010 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 com.android.vending.licensing;

-

-import android.util.Log;

-

-import com.android.vending.licensing.LicenseCheckerCallback.ApplicationErrorCode;

-import com.android.vending.licensing.Policy.LicenseResponse;

-

-/**

- * Contains data related to a licensing request and methods to verify

- * and process the response.

- */

-class LicenseValidator {

-    private static final String TAG = "LicenseValidator";

-

-    // Server response codes.

-    private static final int LICENSED = 0x0;

-    private static final int NOT_LICENSED = 0x1;

-    private static final int LICENSED_OLD_KEY = 0x2;

-    private static final int ERROR_NOT_MARKET_MANAGED = 0x3;

-    private static final int ERROR_INVALID_KEYS = 0x4;

-    private static final int ERROR_OVER_QUOTA = 0x5;

-

-    private static final int ERROR_CONTACTING_SERVER = 0x101;

-    private static final int ERROR_INVALID_PACKAGE_NAME = 0x102;

-    private static final int ERROR_NON_MATCHING_UID = 0x103;

-

-    private final Policy mPolicy;

-    private final LicenseCheckerCallback mCallback;

-    private final int mNonce;

-    private final String mPackageName;

-    private final String mVersionCode;

-

-    LicenseValidator(Policy policy, LicenseCheckerCallback callback, int nonce, String packageName,

-        String versionCode) {

-        mPolicy = policy;

-        mCallback = callback;

-        mNonce = nonce;

-        mPackageName = packageName;

-        mVersionCode = versionCode;

-    }

-

-    public LicenseCheckerCallback getCallback() {

-        return mCallback;

-    }

-

-    public int getNonce() {

-        return mNonce;

-    }

-

-    public String getPackageName() {

-        return mPackageName;

-    }

-

-    /**

-     * Verifies the response from server and calls appropriate callback method.

-     *

-     * @param responseCode server response code

-     * @param signedData signed data from server

-     * @param signature server signature

-     */

-    public void verify(int responseCode, String signedData, String signature) {

-        // Parse and validate response.

-        // TODO(jyum): decode data with signature.

-        // TODO(jyum): verify timestamp is within reason. However, relying

-        // on device clock may lead to problems?

-        ResponseData data;

-        try {

-            data = ResponseData.parse(signedData);

-        } catch (IllegalArgumentException e) {

-            Log.e(TAG, "Could not parse response.");

-            handleInvalidResponse();

-            return;

-        }

-

-        if (data.responseCode != responseCode) {

-            Log.e(TAG, "Response codes don't match.");

-            handleInvalidResponse();

-            return;

-        }

-

-        if (data.nonce != mNonce) {

-            Log.e(TAG, "Nonce doesn't match.");

-            handleInvalidResponse();

-            return;

-        }

-

-        if (!data.packageName.equals(mPackageName)) {

-            Log.e(TAG, "Package name doesn't match.");

-            handleInvalidResponse();

-            return;

-        }

-

-        if (!data.versionCode.equals(mVersionCode)) {

-            Log.e(TAG, "Version codes don't match.");

-            handleInvalidResponse();

-            return;

-        }

-

-        switch (responseCode) {

-            case LICENSED:

-            case LICENSED_OLD_KEY:

-                handleResponse(LicenseResponse.LICENSED);

-                break;

-            case NOT_LICENSED:

-                handleResponse(LicenseResponse.NOT_LICENSED);

-                break;

-            case ERROR_CONTACTING_SERVER:

-                handleResponse(LicenseResponse.CLIENT_RETRY);

-                break;

-            case ERROR_INVALID_KEYS:

-            case ERROR_OVER_QUOTA:

-                handleResponse(LicenseResponse.SERVER_RETRY);

-                break;

-            case ERROR_INVALID_PACKAGE_NAME:

-                handleApplicationError(ApplicationErrorCode.INVALID_PACKAGE_NAME);

-                break;

-            case ERROR_NON_MATCHING_UID:

-                handleApplicationError(ApplicationErrorCode.NON_MATCHING_UID);

-                break;

-            case ERROR_NOT_MARKET_MANAGED:

-                handleApplicationError(ApplicationErrorCode.NOT_MARKET_MANAGED);

-                break;

-            default:

-                Log.e(TAG, "Unknown response code for license check.");

-                handleInvalidResponse();

-        }

-    }

-

-    /**

-     * Confers with policy and calls appropriate callback method.

-     *

-     * @param response

-     */

-    private void handleResponse(LicenseResponse response) {

-        if (mPolicy.allowAccess(response)) {

-            mCallback.allow();

-        } else {

-            mCallback.dontAllow();

-        }

-    }

-

-    private void handleApplicationError(ApplicationErrorCode code) {

-        mCallback.applicationError(code);

-    }

-

-    private void handleInvalidResponse() {

-        mCallback.dontAllow();

-    }

-}

diff --git a/samples/MarketLicensing/src/com/android/vending/licensing/Policy.java b/samples/MarketLicensing/src/com/android/vending/licensing/Policy.java
deleted file mode 100755
index 461c08e..0000000
--- a/samples/MarketLicensing/src/com/android/vending/licensing/Policy.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*

- * Copyright (C) 2010 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 com.android.vending.licensing;

-

-/**

- * Policy used by {@link LicenseChecker} to determine whether a user should

- * have access to the application.

- */

-public interface Policy {

-

-    /**

-     * Result of a license check.

-     */

-    public enum LicenseResponse {

-        /**

-         * User is licensed to use the app.

-         */

-        LICENSED,

-        /**

-         * User is not licensed to use the app.

-         */

-        NOT_LICENSED,

-        /**

-         * Retryable error on the client side e.g. no network.

-         */

-        CLIENT_RETRY,

-        /**

-         * Retryable error on the server side e.g. application is over request

-         * quota.

-         */

-        SERVER_RETRY,

-    }

-

-    /**

-     * Determines whether the user should be allowed access.

-     *

-     * @param response result of the license check request

-     * @return true iff access should be allowed

-     */

-    boolean allowAccess(LicenseResponse response);

-}

diff --git a/samples/MarketLicensing/src/com/android/vending/licensing/ResponseData.java b/samples/MarketLicensing/src/com/android/vending/licensing/ResponseData.java
deleted file mode 100755
index 3882d56..0000000
--- a/samples/MarketLicensing/src/com/android/vending/licensing/ResponseData.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*

- * Copyright (C) 2010 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 com.android.vending.licensing;

-

-import java.util.Iterator;

-import java.util.regex.Pattern;

-

-import android.text.TextUtils;

-

-/**

- * ResponseData from licensing server.

- */

-class ResponseData {

-

-    public int responseCode;

-    public int nonce;

-    public String packageName;

-    public String versionCode;

-    public String userId;

-    public long timestamp;

-    /** Response-specific data. */

-    public String extra;

-

-    /**

-     * Parses response string into ResponseData.

-     *

-     * @param responseData response data string

-     * @throws IllegalArgumentException upon parsing error

-     * @return ResponseData object

-     */

-    public static ResponseData parse(String responseData) {

-        // Must parse out main response data and response-specific data.

-        TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(':');

-        splitter.setString(responseData);

-        Iterator<String> it = splitter.iterator();

-        if (!it.hasNext()) {

-            throw new IllegalArgumentException("Blank response.");

-        }

-        final String mainData = it.next();

-

-        // Response-specific (extra) data is optional.

-        String extraData = "";

-        if (it.hasNext()) {

-            extraData = it.next();

-        }

-

-        String [] fields = TextUtils.split(mainData, Pattern.quote("|"));

-        if (fields.length < 5) {

-            throw new IllegalArgumentException("Wrong number of fields.");

-        }

-

-        ResponseData data = new ResponseData();

-        data.extra = extraData;

-        data.responseCode = Integer.parseInt(fields[0]);

-        data.nonce = Integer.parseInt(fields[1]);

-        data.packageName = fields[2];

-        data.versionCode = fields[3];

-        // TODO(jyum): userId is not there yet.

-        // data.userId = fields[4];

-        data.timestamp = Long.parseLong(fields[4]);

-

-        return data;

-    }

-

-    @Override

-    public String toString() {

-        return TextUtils.join("|", new Object [] { responseCode, nonce, packageName, versionCode,

-            userId, timestamp });

-    }

-}

diff --git a/samples/MarketLicensing/src/com/android/vending/licensing/StrictPolicy.java b/samples/MarketLicensing/src/com/android/vending/licensing/StrictPolicy.java
deleted file mode 100755
index ddff8e9..0000000
--- a/samples/MarketLicensing/src/com/android/vending/licensing/StrictPolicy.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*

- * Copyright (C) 2010 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 com.android.vending.licensing;

-

-/**

- * Strict policy.

- *

- * Should never be used in a real application as it strictly disallows access

- * upon retryable errors such as no connection present.

- */

-public class StrictPolicy implements Policy {

-

-    public boolean allowAccess(LicenseResponse response) {

-        return LicenseResponse.LICENSED == response;

-    }

-}

diff --git a/samples/SampleSyncAdapter/_index.html b/samples/SampleSyncAdapter/_index.html
index b0fbd4a..4191ba5 100644
--- a/samples/SampleSyncAdapter/_index.html
+++ b/samples/SampleSyncAdapter/_index.html
@@ -1,26 +1,37 @@
-<p>A sample that demonstrates how an application can communicate with cloud-based services and synchronize their 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).</p>
+<p>This sample 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).</p>
 
-<p> The <a href="../../../android/accounts/AccountManager">account manager</a> allows sharing of credentials across multiple applications and services. 
-Users enter the credentials for each account only once &mdash; applications with the <code>USE_CREDENTIALS</code> permission can then query the account manager
- to obtain an auth token for the account.The authenticator (a pluggable component of account manager) requests credentials from the user, validates them
-  with an authentication server running in the cloud, and then stores them to the AccountManager. 
-This sample demonstrates how to write an authenticator for your
-service by extending the new  <code><a href="../../../android/accounts/AbstractAccountAuthenticator.html">AbstractAccountAuthenticator</a></code> abstract class.
-</p>
+<p> The <a
+href="../../../reference/android/accounts/AccountManager.html">account
+manager</a> allows sharing of credentials across multiple applications and
+services. Users enter the credentials for each account only once &mdash;
+applications with the <code>USE_CREDENTIALS</code> permission can then query the
+account manager to obtain an auth token for the account. An authenticator (a
+pluggable component of account manager) requests credentials from the user,
+validates them with an authentication server running in the cloud, and then
+stores them to the account manager. This sample demonstrates how to write an
+authenticator for your service by extending the new  <code><a
+href="../../../reference/android/accounts/AbstractAccountAuthenticator.html">
+AbstractAccountAuthenticator</a></code> abstract class. </p>
 
-<p>The sync adapter (essential to the synchronization service) declares the account type and ContentProvider authority to the sync manager.
-This sample demosntrates how to write your own sync adapters by extending the <code><a href="../../../android/content/AbstractThreadedSyncAdapter.html">AbstractThreadedSyncAdapter</a></code>
-abstract class and implementing the onPerformSync() method that gets called whenever the sync manager issues a sync operation for that sync adapter.
-</p>
+<p>The sync adapter (essential to the synchronization service) declares the
+account type and ContentProvider authority to the sync manager. This sample
+demosntrates how to write your own sync adapters by extending the <code><a
+href="../../../reference/android/content/AbstractThreadedSyncAdapter.html">
+AbstractThreadedSyncAdapter</a></code> abstract class and implementing the
+<code>onPerformSync()</code> method, which gets called whenever the sync manager
+issues a sync operation for that sync adapter. </p>
 
-<p> The service for this sample application is running at: <br>
-http://samplesyncadapter.appspot.com/users
-</p>
+<p> The cloud-based service for this sample application is running at: </p>
+<p style="margin-left:2em;">http://samplesyncadapter.appspot.com/users</p>
 
-<p class="note">When you install this sample application, a new syncable "SampleSyncAdapter" account will be added to your phone's account manager.
-You can go to "Settings | Accounts & sync" to view the accounts that are stored in the account manager and to change their sync settings. </p>
+<p>When you install this sample application, a new syncable "SampleSyncAdapter"
+account will be added to your phone's account manager. You can go to "Settings |
+Accounts &amp; Sync" to view the account and change its sync settings. </p>
 
 <img alt="Screenshot 1" src="../images/SampleSyncAdapter1.png" />
 <img alt="Screenshot 2" src="../images/SampleSyncAdapter2.png" />
-<img alt="Screenshot 3" src="../images/SampleSyncAdapter3.png" />
\ No newline at end of file
+<img alt="Screenshot 3" src="../images/SampleSyncAdapter3.png" />
diff --git a/testrunner/test_defs.xml b/testrunner/test_defs.xml
index 2307cfa..68eab5d 100644
--- a/testrunner/test_defs.xml
+++ b/testrunner/test_defs.xml
@@ -561,12 +561,12 @@
     description="Android STL."
     extra_build_args="ASTL_TESTS=1" />
 
-<!-- pending patch 820
+<!-- Google Test -->
 <test-native name="gtest"
     build_path="external/gtest"
     description="Google test."
     extra_build_args="GTEST_TESTS=1" />
--->
+
 
 <!-- host java tests -->
 <test-host name="cts-appsecurity"
diff --git a/testrunner/test_defs/native_test.py b/testrunner/test_defs/native_test.py
index e6917c9..dc26c73 100644
--- a/testrunner/test_defs/native_test.py
+++ b/testrunner/test_defs/native_test.py
@@ -86,7 +86,7 @@
 
       # Single quotes are needed to prevent the shell splitting it.
       output = adb.SendShellCommand("'%s 2>&1;echo -n exit code:$?'" %
-                                    full_path,
+                                    "(cd /sdcard;%s)" % full_path,
                                     int(options.timeout))
       success = output.endswith("exit code:0")
       logger.Log("%s... %s" % (f, success and "ok" or "failed"))