Merge "Remove AccessibilityNodeProvider sample code."
diff --git a/apps/Development/res/layout/connectivity.xml b/apps/Development/res/layout/connectivity.xml
index 2df645c..53f1ed7 100644
--- a/apps/Development/res/layout/connectivity.xml
+++ b/apps/Development/res/layout/connectivity.xml
@@ -213,6 +213,33 @@
 
     <LinearLayout
       android:orientation="horizontal"
+      android:layout_width="match_parent"
+      android:layout_height="wrap_content">
+        <Button android:id="@+id/startTdls"
+          android:layout_width="wrap_content"
+          android:layout_height="wrap_content"
+          android:text="@string/start_tdls" />
+        <TextView
+          android:layout_width="wrap_content"
+          android:layout_height="wrap_content"
+          android:text="@string/mac_tdls" />
+        <EditText android:id="@+id/sc_ip_mac"
+          android:layout_width="wrap_content"
+          android:layout_height="wrap_content"
+          android:minEms="10" />
+        <Button android:id="@+id/stopTdls"
+          android:layout_width="wrap_content"
+          android:layout_height="wrap_content"
+          android:text="@string/stop_tdls" />
+    </LinearLayout>
+
+    <!-- divider line -->
+    <View android:background="#FFFFFFFF"
+      android:layout_width="match_parent"
+      android:layout_height="3dip" />
+
+    <LinearLayout
+      android:orientation="horizontal"
       android:paddingTop="4dip"
       android:layout_width="match_parent"
       android:layout_height="wrap_content">
diff --git a/apps/Development/res/values/strings.xml b/apps/Development/res/values/strings.xml
index b7ed5e1..ced7b72 100644
--- a/apps/Development/res/values/strings.xml
+++ b/apps/Development/res/values/strings.xml
@@ -34,6 +34,10 @@
     <string name="scan_cycles">Scan Cycles: </string>
     <string name="disconnect">Disconnect</string>
 
+    <string name="start_tdls">Start TDLS</string>
+    <string name="stop_tdls">Stop TDLS</string>
+    <string name="mac_tdls"> IP/MAC: </string>
+
     <string name="start_mms">Start MMS</string>
     <string name="stop_mms">Stop MMS</string>
     <string name="start_hipri">Start HiPri</string>
diff --git a/apps/Development/src/com/android/development/Connectivity.java b/apps/Development/src/com/android/development/Connectivity.java
index 63f23ae..0da1410 100644
--- a/apps/Development/src/com/android/development/Connectivity.java
+++ b/apps/Development/src/com/android/development/Connectivity.java
@@ -117,6 +117,8 @@
     private long mTotalScanTime = 0;
     private long mTotalScanCount = 0;
 
+    private String mTdlsAddr = null;
+
     private WifiManager mWm;
     private PowerManager mPm;
     private ConnectivityManager mCm;
@@ -290,6 +292,9 @@
         mIntentFilter = new IntentFilter();
         mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
 
+        findViewById(R.id.startTdls).setOnClickListener(mClickListener);
+        findViewById(R.id.stopTdls).setOnClickListener(mClickListener);
+
         findViewById(R.id.start_mms).setOnClickListener(mClickListener);
         findViewById(R.id.stop_mms).setOnClickListener(mClickListener);
         findViewById(R.id.start_hipri).setOnClickListener(mClickListener);
@@ -339,6 +344,12 @@
                 case R.id.startScan:
                     onStartScanCycle();
                     break;
+                case R.id.startTdls:
+                    onStartTdls();
+                    break;
+                case R.id.stopTdls:
+                    onStopTdls();
+                    break;
                 case R.id.start_mms:
                     mCm.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
                             Phone.FEATURE_ENABLE_MMS);
@@ -487,6 +498,30 @@
         }
     }
 
+    private void onStartTdls() {
+        mTdlsAddr = ((EditText)findViewById(R.id.sc_ip_mac)).getText().toString();
+        Log.d(TAG, "TDLS: START " + mTdlsAddr);
+        InetAddress inetAddress = null;
+        try {
+            inetAddress = InetAddress.getByName(mTdlsAddr);
+            mWm.enableTdls(inetAddress, true);
+        } catch (Exception e) {
+            mWm.enableTdlsWithMacAddress(mTdlsAddr, true);
+        }
+    }
+
+    private void onStopTdls() {
+        if (mTdlsAddr == null) return;
+        Log.d(TAG, "TDLS: STOP " + mTdlsAddr);
+        InetAddress inetAddress = null;
+        try {
+            inetAddress = InetAddress.getByName(mTdlsAddr);
+            mWm.enableTdls(inetAddress, false);
+        } catch (Exception e) {
+            mWm.enableTdlsWithMacAddress(mTdlsAddr, false);
+        }
+    }
+
     private void onAddDefaultRoute() {
         try {
             mNetd.addRoute("eth0", new RouteInfo(null,
diff --git a/build/sdk-darwin-x86.atree b/build/sdk-darwin-x86.atree
index 118ed1c..53bbc1f 100644
--- a/build/sdk-darwin-x86.atree
+++ b/build/sdk-darwin-x86.atree
@@ -15,6 +15,19 @@
 #
 
 ##############################################################################
+# Build Tools Component
+##############################################################################
+# Note that the build-tools sub-folder uses the platform-name as a placeholder
+# at build-time. Packaging will later change that to the actual build-tools
+# revision as specified in the source.properties.
+
+
+lib/libLLVM.dylib            strip build-tools/${PLATFORM_NAME}/libLLVM.dylib
+lib/libbcc.dylib             strip build-tools/${PLATFORM_NAME}/libbcc.dylib
+lib/libbcinfo.dylib          strip build-tools/${PLATFORM_NAME}/libbcinfo.dylib
+lib/libclang.dylib           strip build-tools/${PLATFORM_NAME}/libclang.dylib
+
+##############################################################################
 # Docs Component
 ##############################################################################
 
diff --git a/build/sdk-linux-x86.atree b/build/sdk-linux-x86.atree
index e21785e..86f7754 100644
--- a/build/sdk-linux-x86.atree
+++ b/build/sdk-linux-x86.atree
@@ -14,4 +14,17 @@
 # limitations under the License.
 #
 
+##############################################################################
+# Build Tools Component
+##############################################################################
+# Note that the build-tools sub-folder uses the platform-name as a placeholder
+# at build-time. Packaging will later change that to the actual build-tools
+# revision as specified in the source.properties.
+
+
+lib/libLLVM.so                 strip build-tools/${PLATFORM_NAME}/libLLVM.so
+lib/libbcc.so                  strip build-tools/${PLATFORM_NAME}/libbcc.so
+lib/libbcinfo.so               strip build-tools/${PLATFORM_NAME}/libbcinfo.so
+lib/libclang.so                strip build-tools/${PLATFORM_NAME}/libclang.so
+
 
diff --git a/build/sdk-windows-x86.atree b/build/sdk-windows-x86.atree
index c9ec5f9..44b7fcb 100644
--- a/build/sdk-windows-x86.atree
+++ b/build/sdk-windows-x86.atree
@@ -41,6 +41,9 @@
 ##############################################################################
 # Build Tools Component
 ##############################################################################
+# Note that the build-tools sub-folder uses the platform-name as a placeholder
+# at build-time. Packaging will later change that to the actual build-tools
+# revision as specified in the source.properties.
 
 rm build-tools/${PLATFORM_NAME}/aapt
 bin/aapt.exe                            strip build-tools/${PLATFORM_NAME}/aapt.exe
@@ -56,6 +59,20 @@
 rm build-tools/${PLATFORM_NAME}/llvm-rs-cc
 bin/llvm-rs-cc.exe                      strip build-tools/${PLATFORM_NAME}/llvm-rs-cc.exe
 
+rm build-tools/${PLATFORM_NAME}/libLLVM.so
+lib/libLLVM.dll                         strip build-tools/${PLATFORM_NAME}/libLLVM.dll
+
+rm build-tools/${PLATFORM_NAME}/libclang.so
+lib/libclang.dll                        strip build-tools/${PLATFORM_NAME}/libclang.dll
+
+#bcc not yet compiled on windows
+
+rm build-tools/${PLATFORM_NAME}/libbcc.so
+#lib/libbcc.dll                          strip build-tools/${PLATFORM_NAME}/libbcc.dll
+
+rm build-tools/${PLATFORM_NAME}/libbcinfo.so
+#lib/libbcinfo.dll                       strip build-tools/${PLATFORM_NAME}/libbcinfo.dll
+
 
 
 ##############################################################################
diff --git a/build/sdk.atree b/build/sdk.atree
index ca79644..72612af 100644
--- a/build/sdk.atree
+++ b/build/sdk.atree
@@ -48,6 +48,17 @@
 # API database for tools such as lint
 development/sdk/api-versions.xml              platform-tools/api/api-versions.xml
 
+# systrace
+external/chromium-trace/systrace.py           platform-tools/systrace/systrace.py
+external/chromium-trace/systrace-legacy.py    platform-tools/systrace/systrace-legacy.py
+external/chromium-trace/script.js             platform-tools/systrace/script.js
+external/chromium-trace/style.css             platform-tools/systrace/style.css
+external/chromium-trace/prefix.html           platform-tools/systrace/prefix.html
+external/chromium-trace/suffix.html           platform-tools/systrace/suffix.html
+external/chromium-trace/LICENSE               platform-tools/systrace/LICENSE
+external/chromium-trace/AUTHORS               platform-tools/systrace/AUTHORS
+external/chromium-trace/NOTICE                platform-tools/systrace/NOTICE
+external/chromium-trace/UPSTREAM_REVISION     platform-tools/systrace/UPSTREAM_REVISION
 
 ##############################################################################
 # Build Tools Component
@@ -62,11 +73,14 @@
 # build tools from out/host/$(HOST_OS)-$(HOST_ARCH)/
 bin/aapt                                strip build-tools/${PLATFORM_NAME}/aapt
 bin/aidl                                strip build-tools/${PLATFORM_NAME}/aidl
+
 # renderscript (cc + headers)
 bin/llvm-rs-cc                          strip build-tools/${PLATFORM_NAME}/llvm-rs-cc
 frameworks/rs/scriptc                         build-tools/${PLATFORM_NAME}/renderscript/include
 external/clang/lib/Headers                    build-tools/${PLATFORM_NAME}/renderscript/clang-include
 external/clang/LICENSE.TXT                    build-tools/${PLATFORM_NAME}/renderscript/clang-include/LICENSE.TXT
+prebuilts/sdk/renderscript/lib                build-tools/${PLATFORM_NAME}/renderscript/lib
+
 # dx
 bin/dx                                        build-tools/${PLATFORM_NAME}/dx
 framework/dx.jar                              build-tools/${PLATFORM_NAME}/lib/dx.jar
@@ -169,59 +183,70 @@
 #
 # 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/apps/GestureBuilder                samples/${PLATFORM_NAME}/GestureBuilder
+development/apps/GestureBuilder                samples/${PLATFORM_NAME}/legacy/GestureBuilder
 development/samples/samples_source.properties  samples/${PLATFORM_NAME}/source.properties
 #
 # PLEASE KEEP THE SAMPLES IN ALPHABETICAL ORDER.
 #
-development/samples/AccelerometerPlay          samples/${PLATFORM_NAME}/AccelerometerPlay
-development/samples/ActionBarCompat            samples/${PLATFORM_NAME}/ActionBarCompat
-development/samples/AndroidBeamDemo            samples/${PLATFORM_NAME}/AndroidBeamDemo
-development/samples/ApiDemos                   samples/${PLATFORM_NAME}/ApiDemos
-development/samples/AppNavigation              samples/${PLATFORM_NAME}/AppNavigation
-development/samples/BackupRestore              samples/${PLATFORM_NAME}/BackupRestore
-development/samples/BasicGLSurfaceView         samples/${PLATFORM_NAME}/BasicGLSurfaceView
-development/samples/BluetoothChat              samples/${PLATFORM_NAME}/BluetoothChat
-development/samples/BluetoothHDP               samples/${PLATFORM_NAME}/BluetoothHDP
-development/samples/ContactManager             samples/${PLATFORM_NAME}/ContactManager
-development/samples/CrossCompatibility         samples/${PLATFORM_NAME}/CrossCompatibility
-development/samples/CubeLiveWallpaper          samples/${PLATFORM_NAME}/CubeLiveWallpaper
-development/samples/HelloEffects               samples/${PLATFORM_NAME}/HelloEffects
-development/samples/Home                       samples/${PLATFORM_NAME}/Home
-development/samples/HoneycombGallery           samples/${PLATFORM_NAME}/HoneycombGallery
-development/samples/JetBoy                     samples/${PLATFORM_NAME}/JetBoy
-development/samples/KeyChainDemo               samples/${PLATFORM_NAME}/KeyChainDemo
-development/samples/LunarLander                samples/${PLATFORM_NAME}/LunarLander
-development/samples/MultiResolution            samples/${PLATFORM_NAME}/MultiResolution
-development/samples/NotePad                    samples/${PLATFORM_NAME}/NotePad
-development/samples/RandomMusicPlayer          samples/${PLATFORM_NAME}/RandomMusicPlayer
-development/samples/SpellChecker/SampleSpellCheckerService samples/${PLATFORM_NAME}/SpellChecker/SampleSpellCheckerService
-development/samples/SpellChecker/HelloSpellChecker         samples/${PLATFORM_NAME}/SpellChecker/HelloSpellChecker
-development/samples/SampleSyncAdapter          samples/${PLATFORM_NAME}/SampleSyncAdapter
-development/samples/SearchableDictionary       samples/${PLATFORM_NAME}/SearchableDictionary
-development/samples/SipDemo                    samples/${PLATFORM_NAME}/SipDemo
-development/samples/SkeletonApp                samples/${PLATFORM_NAME}/SkeletonApp
-development/samples/Snake                      samples/${PLATFORM_NAME}/Snake
-development/samples/SoftKeyboard               samples/${PLATFORM_NAME}/SoftKeyboard
-development/samples/Spinner                    samples/${PLATFORM_NAME}/Spinner
-development/samples/SpinnerTest                samples/${PLATFORM_NAME}/SpinnerTest
-development/samples/TicTacToeLib               samples/${PLATFORM_NAME}/TicTacToeLib
-development/samples/TicTacToeMain              samples/${PLATFORM_NAME}/TicTacToeMain
-development/samples/TtsEngine                  samples/${PLATFORM_NAME}/TtsEngine
-development/samples/ToyVpn                     samples/${PLATFORM_NAME}/ToyVpn
-development/samples/UiAutomator                samples/${PLATFORM_NAME}/UiAutomator
-development/samples/USB/MissileLauncher        samples/${PLATFORM_NAME}/USB/MissileLauncher
-development/samples/USB/AdbTest                samples/${PLATFORM_NAME}/USB/AdbTest
-development/samples/VoiceRecognitionService    samples/${PLATFORM_NAME}/VoiceRecognitionService
-development/samples/VoicemailProviderDemo      samples/${PLATFORM_NAME}/VoicemailProviderDemo
-development/samples/WeatherListWidget          samples/${PLATFORM_NAME}/WeatherListWidget
-development/apps/WidgetPreview                 samples/${PLATFORM_NAME}/WidgetPreview
-development/samples/WiFiDirectDemo             samples/${PLATFORM_NAME}/WiFiDirectDemo
-development/samples/WiFiDirectServiceDiscovery samples/${PLATFORM_NAME}/WiFiDirectServiceDiscovery
-development/samples/Wiktionary                 samples/${PLATFORM_NAME}/Wiktionary
-development/samples/WiktionarySimple           samples/${PLATFORM_NAME}/WiktionarySimple
-development/samples/XmlAdapters                samples/${PLATFORM_NAME}/XmlAdapters
-development/samples/RenderScript/HelloCompute  samples/${PLATFORM_NAME}/RenderScript/HelloCompute
+
+# New sample tree
+developers/samples/android/connectivity        samples/${PLATFORM_NAME}/connectivity
+developers/samples/android/content             samples/${PLATFORM_NAME}/content
+developers/samples/android/input               samples/${PLATFORM_NAME}/input
+developers/samples/android/media               samples/${PLATFORM_NAME}/media
+developers/samples/android/security            samples/${PLATFORM_NAME}/security
+developers/samples/android/testing             samples/${PLATFORM_NAME}/testing
+developers/samples/android/ui                  samples/${PLATFORM_NAME}/ui
+
+# Old sample tree
+development/samples/AccelerometerPlay          samples/${PLATFORM_NAME}/legacy/AccelerometerPlay
+development/samples/ActionBarCompat            samples/${PLATFORM_NAME}/legacy/ActionBarCompat
+development/samples/AndroidBeamDemo            samples/${PLATFORM_NAME}/legacy/AndroidBeamDemo
+development/samples/ApiDemos                   samples/${PLATFORM_NAME}/legacy/ApiDemos
+development/samples/AppNavigation              samples/${PLATFORM_NAME}/legacy/AppNavigation
+development/samples/BackupRestore              samples/${PLATFORM_NAME}/legacy/BackupRestore
+development/samples/BasicGLSurfaceView         samples/${PLATFORM_NAME}/legacy/BasicGLSurfaceView
+development/samples/BluetoothChat              samples/${PLATFORM_NAME}/legacy/BluetoothChat
+development/samples/BluetoothHDP               samples/${PLATFORM_NAME}/legacy/BluetoothHDP
+development/samples/ContactManager             samples/${PLATFORM_NAME}/legacy/ContactManager
+development/samples/CrossCompatibility         samples/${PLATFORM_NAME}/legacy/CrossCompatibility
+development/samples/CubeLiveWallpaper          samples/${PLATFORM_NAME}/legacy/CubeLiveWallpaper
+development/samples/HelloEffects               samples/${PLATFORM_NAME}/legacy/HelloEffects
+development/samples/Home                       samples/${PLATFORM_NAME}/legacy/Home
+development/samples/HoneycombGallery           samples/${PLATFORM_NAME}/legacy/HoneycombGallery
+development/samples/JetBoy                     samples/${PLATFORM_NAME}/legacy/JetBoy
+development/samples/KeyChainDemo               samples/${PLATFORM_NAME}/legacy/KeyChainDemo
+development/samples/LunarLander                samples/${PLATFORM_NAME}/legacy/LunarLander
+development/samples/MultiResolution            samples/${PLATFORM_NAME}/legacy/MultiResolution
+development/samples/NotePad                    samples/${PLATFORM_NAME}/legacy/NotePad
+development/samples/RandomMusicPlayer          samples/${PLATFORM_NAME}/legacy/RandomMusicPlayer
+development/samples/SpellChecker/SampleSpellCheckerService samples/${PLATFORM_NAME}/legacy/SpellChecker/SampleSpellCheckerService
+development/samples/SpellChecker/HelloSpellChecker         samples/${PLATFORM_NAME}/legacy/SpellChecker/HelloSpellChecker
+development/samples/SampleSyncAdapter          samples/${PLATFORM_NAME}/legacy/SampleSyncAdapter
+development/samples/SearchableDictionary       samples/${PLATFORM_NAME}/legacy/SearchableDictionary
+development/samples/SipDemo                    samples/${PLATFORM_NAME}/legacy/SipDemo
+development/samples/SkeletonApp                samples/${PLATFORM_NAME}/legacy/SkeletonApp
+development/samples/Snake                      samples/${PLATFORM_NAME}/legacy/Snake
+development/samples/SoftKeyboard               samples/${PLATFORM_NAME}/legacy/SoftKeyboard
+development/samples/Spinner                    samples/${PLATFORM_NAME}/legacy/Spinner
+development/samples/SpinnerTest                samples/${PLATFORM_NAME}/legacy/SpinnerTest
+development/samples/TicTacToeLib               samples/${PLATFORM_NAME}/legacy/TicTacToeLib
+development/samples/TicTacToeMain              samples/${PLATFORM_NAME}/legacy/TicTacToeMain
+development/samples/TtsEngine                  samples/${PLATFORM_NAME}/legacy/TtsEngine
+development/samples/ToyVpn                     samples/${PLATFORM_NAME}/legacy/ToyVpn
+development/samples/UiAutomator                samples/${PLATFORM_NAME}/legacy/UiAutomator
+development/samples/USB/MissileLauncher        samples/${PLATFORM_NAME}/legacy/USB/MissileLauncher
+development/samples/USB/AdbTest                samples/${PLATFORM_NAME}/legacy/USB/AdbTest
+development/samples/VoiceRecognitionService    samples/${PLATFORM_NAME}/legacy/VoiceRecognitionService
+development/samples/VoicemailProviderDemo      samples/${PLATFORM_NAME}/legacy/VoicemailProviderDemo
+development/samples/WeatherListWidget          samples/${PLATFORM_NAME}/legacy/WeatherListWidget
+development/apps/WidgetPreview                 samples/${PLATFORM_NAME}/legacy/WidgetPreview
+development/samples/WiFiDirectDemo             samples/${PLATFORM_NAME}/legacy/WiFiDirectDemo
+development/samples/WiFiDirectServiceDiscovery samples/${PLATFORM_NAME}/legacy/WiFiDirectServiceDiscovery
+development/samples/Wiktionary                 samples/${PLATFORM_NAME}/legacy/Wiktionary
+development/samples/WiktionarySimple           samples/${PLATFORM_NAME}/legacy/WiktionarySimple
+development/samples/XmlAdapters                samples/${PLATFORM_NAME}/legacy/XmlAdapters
+development/samples/RenderScript/HelloCompute  samples/${PLATFORM_NAME}/legacy/RenderScript/HelloCompute
 
 # NOTICE files are copied by build/core/Makefile from sdk.git
 sdk/files/sdk_files_NOTICE.txt                 samples/${PLATFORM_NAME}/NOTICE.txt
@@ -268,6 +293,7 @@
 frameworks/support/v7/appcompat/res                                                               extras/android/support/v7/appcompat/res
 frameworks/support/v7/appcompat/src/.readme                                                       extras/android/support/v7/appcompat/src/.readme
 ${OUT_DIR}/target/common/obj/PACKAGING/android-support-v7-appcompat_intermediates/android-support-v7-appcompat.jar    extras/android/support/v7/appcompat/libs/android-support-v7-appcompat.jar
+${OUT_DIR}/target/common/obj/PACKAGING/android-support-v4_intermediates/android-support-v4.jar                        extras/android/support/v7/appcompat/libs/android-support-v4.jar
 
 frameworks/support/v7/mediarouter/README.txt                                                       extras/android/support/v7/mediarouter/README.txt
 frameworks/support/v7/mediarouter/.project                                                         extras/android/support/v7/mediarouter/.project
diff --git a/build/windows_sdk_whitelist.mk b/build/windows_sdk_whitelist.mk
index 523883a..b9f7196 100644
--- a/build/windows_sdk_whitelist.mk
+++ b/build/windows_sdk_whitelist.mk
@@ -53,6 +53,7 @@
 	system/core/liblog \
 	system/core/libsparse \
 	system/core/libzipfile \
+	system/core/libs/utils \
 	system/extras/ext4_utils
 
 # -----
@@ -65,6 +66,7 @@
 	libcore \
 	development/apps \
 	development/tools/mkstubs \
+	frameworks/compile/libbcc \
 	packages
 
 else
diff --git a/cmds/monkey/src/com/android/commands/monkey/Monkey.java b/cmds/monkey/src/com/android/commands/monkey/Monkey.java
index d878bda..a2655e1 100644
--- a/cmds/monkey/src/com/android/commands/monkey/Monkey.java
+++ b/cmds/monkey/src/com/android/commands/monkey/Monkey.java
@@ -812,9 +812,6 @@
                 } else if (opt.equals("--pct-pinchzoom")) {
                     int i = MonkeySourceRandom.FACTOR_PINCHZOOM;
                     mFactors[i] = -nextOptionLong("pinch zoom events percentage");
-                } else if (opt.equals("--pct-fling")) {
-                    int i = MonkeySourceRandom.FACTOR_FLING;
-                    mFactors[i] = -nextOptionLong("fling events percentage");
                 } else if (opt.equals("--pkg-blacklist-file")) {
                     mPkgBlacklistFile = nextOptionData();
                 } else if (opt.equals("--pkg-whitelist-file")) {
@@ -1353,8 +1350,7 @@
         usage.append("              [--pct-trackball PERCENT] [--pct-syskeys PERCENT]\n");
         usage.append("              [--pct-nav PERCENT] [--pct-majornav PERCENT]\n");
         usage.append("              [--pct-appswitch PERCENT] [--pct-flip PERCENT]\n");
-        usage.append("              [--pct-pinchzoom PERCENT] [--pct-fling PERCENT]\n");
-        usage.append("              [--pct-anyevent PERCENT]\n");
+        usage.append("              [--pct-anyevent PERCENT] [--pct-pinchzoom PERCENT]\n");
         usage.append("              [--pkg-blacklist-file PACKAGE_BLACKLIST_FILE]\n");
         usage.append("              [--pkg-whitelist-file PACKAGE_WHITELIST_FILE]\n");
         usage.append("              [--wait-dbg] [--dbg-no-events]\n");
diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeySourceNetworkViews.java b/cmds/monkey/src/com/android/commands/monkey/MonkeySourceNetworkViews.java
index 89679a1..e41a069 100644
--- a/cmds/monkey/src/com/android/commands/monkey/MonkeySourceNetworkViews.java
+++ b/cmds/monkey/src/com/android/commands/monkey/MonkeySourceNetworkViews.java
@@ -139,7 +139,8 @@
         int viewId = Integer.parseInt(viewString);
         int connectionId = sUiTestAutomationBridge.getConnectionId();
         AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
-        return client.findAccessibilityNodeInfoByAccessibilityId(connectionId, windowId, viewId, 0);
+        return client.findAccessibilityNodeInfoByAccessibilityId(connectionId, windowId, viewId,
+                false, 0);
     }
 
     private static AccessibilityNodeInfo getNodeByViewId(String viewId) throws MonkeyViewException {
diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeySourceRandom.java b/cmds/monkey/src/com/android/commands/monkey/MonkeySourceRandom.java
index 7d9d045..a7f538d 100644
--- a/cmds/monkey/src/com/android/commands/monkey/MonkeySourceRandom.java
+++ b/cmds/monkey/src/com/android/commands/monkey/MonkeySourceRandom.java
@@ -75,21 +75,19 @@
     public static final int FACTOR_TOUCH        = 0;
     public static final int FACTOR_MOTION       = 1;
     public static final int FACTOR_PINCHZOOM    = 2;
-    public static final int FACTOR_FLING        = 3;
-    public static final int FACTOR_TRACKBALL    = 4;
-    public static final int FACTOR_ROTATION     = 5;
-    public static final int FACTOR_NAV          = 6;
-    public static final int FACTOR_MAJORNAV     = 7;
-    public static final int FACTOR_SYSOPS       = 8;
-    public static final int FACTOR_APPSWITCH    = 9;
-    public static final int FACTOR_FLIP         = 10;
-    public static final int FACTOR_ANYTHING     = 11;
-    public static final int FACTORZ_COUNT       = 12;    // should be last+1
+    public static final int FACTOR_TRACKBALL    = 3;
+    public static final int FACTOR_ROTATION     = 4;
+    public static final int FACTOR_NAV          = 5;
+    public static final int FACTOR_MAJORNAV     = 6;
+    public static final int FACTOR_SYSOPS       = 7;
+    public static final int FACTOR_APPSWITCH    = 8;
+    public static final int FACTOR_FLIP         = 9;
+    public static final int FACTOR_ANYTHING     = 10;
+    public static final int FACTORZ_COUNT       = 11;    // should be last+1
 
     private static final int GESTURE_TAP = 0;
     private static final int GESTURE_DRAG = 1;
     private static final int GESTURE_PINCH_OR_ZOOM = 2;
-    private static final int GESTURE_FLING = 3;
 
     /** percentages for each type of event.  These will be remapped to working
      * values after we read any optional values.
@@ -134,9 +132,8 @@
         mFactors[FACTOR_SYSOPS] = 2.0f;
         mFactors[FACTOR_APPSWITCH] = 2.0f;
         mFactors[FACTOR_FLIP] = 1.0f;
-        mFactors[FACTOR_ANYTHING] = 11.0f;
+        mFactors[FACTOR_ANYTHING] = 13.0f;
         mFactors[FACTOR_PINCHZOOM] = 2.0f;
-        mFactors[FACTOR_FLING] = 2.0f;
 
         mRandom = random;
         mMainApps = MainApps;
@@ -262,38 +259,13 @@
      *
      */
     private void generatePointerEvent(Random random, int gesture) {
-        Display display = DisplayManagerGlobal.getInstance().getRealDisplay(
-                Display.DEFAULT_DISPLAY);
+        Display display = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
 
-        if (gesture == GESTURE_FLING) {
-            PointF start, end;
-            // 1 out of 10 is up-and-down fling and the rest are left-and-right flings.
-            if (random.nextInt(10) == 0) {
-                if (random.nextInt(2) == 0) {
-                    start = new PointF(display.getWidth()/2, display.getHeight());
-                    end = new PointF(display.getWidth()/2, 0);
-                } else {
-                    start = new PointF(display.getWidth()/2, 0);
-                    end = new PointF(display.getWidth()/2, display.getHeight());
-                }
-            } else {
-                if (random.nextInt(2) == 0) {
-                    start = new PointF(0, display.getHeight()/2);
-                    end = new PointF(display.getWidth(), display.getHeight()/2);
-                } else {
-                    start = new PointF(display.getWidth(), display.getHeight()/2);
-                    end = new PointF(0, display.getHeight()/2);
-                }
-            }
-
-            generateFlingEvents(start, end, mQ);
-            return;
-        }
-
-        long downAt = SystemClock.uptimeMillis();
         PointF p1 = randomPoint(random, display);
         PointF v1 = randomVector(random);
 
+        long downAt = SystemClock.uptimeMillis();
+
         mQ.addLast(new MonkeyTouchEvent(MotionEvent.ACTION_DOWN)
                 .setDownTime(downAt)
                 .addPointer(0, p1.x, p1.y)
@@ -364,56 +336,6 @@
     }
 
     /**
-     * Generates a fling event. This method counts a down, move, and up as multiple events.
-     *
-     * @param start The starting point.
-     * @param end The ending point.
-     * @param q The event queue to hold the results.
-     *
-     */
-    static void generateFlingEvents(PointF start, PointF end, MonkeyEventQueue q) {
-        // Experiments showed 20 is a good step length while a random step between 0 and 50
-        // doesn't work well.
-        float step = 20.0f;
-        float xSpan = Math.abs(end.x - start.x);
-        float ySpan = Math.abs(end.y - start.y);
-        float segNum, xInc, yInc;
-        if (xSpan > ySpan) {
-            segNum = xSpan / step;
-            if (segNum < 1.0f) {
-                return;
-            }
-            xInc = end.x > start.x ? step : -step;
-            yInc = (end.y - start.y) / segNum;
-        } else {
-            segNum = ySpan / step;
-            if (segNum < 1.0f) {
-                return;
-            }
-            yInc = end.y > start.y ? step : -step;
-            xInc = (end.x - start.x) / segNum;
-        }
-        long downAt = SystemClock.uptimeMillis();
-        q.addLast(new MonkeyTouchEvent(MotionEvent.ACTION_DOWN)
-            .setDownTime(downAt)
-            .addPointer(0, start.x, start.y)
-            .setIntermediateNote(false));
-        PointF point = new PointF(start.x, start.y);
-        for (float i = 1.0f; i < segNum; i++) {
-            point.x += xInc;
-            point.y += yInc;
-            q.addLast(new MonkeyTouchEvent(MotionEvent.ACTION_MOVE)
-                .setDownTime(downAt)
-                .addPointer(0, point.x, point.y)
-                .setIntermediateNote(true));
-        }
-        q.addLast(new MonkeyTouchEvent(MotionEvent.ACTION_UP)
-            .setDownTime(downAt)
-            .addPointer(0, end.x, end.y)
-            .setIntermediateNote(false));
-    }
-
-    /**
      * Generates a random trackball event. This consists of a sequence of small moves, followed by
      * an optional single click.
      *
@@ -482,9 +404,6 @@
         } else if (cls < mFactors[FACTOR_PINCHZOOM]) {
             generatePointerEvent(mRandom, GESTURE_PINCH_OR_ZOOM);
             return;
-        } else if (cls < mFactors[FACTOR_FLING]) {
-            generatePointerEvent(mRandom, GESTURE_FLING);
-            return;
         } else if (cls < mFactors[FACTOR_TRACKBALL]) {
             generateTrackballEvent(mRandom);
             return;
diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeySourceScript.java b/cmds/monkey/src/com/android/commands/monkey/MonkeySourceScript.java
index bebcf01..59aeb55 100644
--- a/cmds/monkey/src/com/android/commands/monkey/MonkeySourceScript.java
+++ b/cmds/monkey/src/com/android/commands/monkey/MonkeySourceScript.java
@@ -17,7 +17,6 @@
 package com.android.commands.monkey;
 
 import android.content.ComponentName;
-import android.graphics.PointF;
 import android.os.SystemClock;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
@@ -128,8 +127,6 @@
 
     private static final String EVENT_KEYWORD_PINCH_ZOOM = "PinchZoom";
 
-    private static final String EVENT_KEYWORD_FLING = "Fling";
-
     private static final String EVENT_KEYWORD_START_FRAMERATE_CAPTURE = "StartCaptureFramerate";
 
     private static final String EVENT_KEYWORD_END_FRAMERATE_CAPTURE = "EndCaptureFramerate";
@@ -589,17 +586,6 @@
             }
         }
 
-        // Handle fling action
-        if ((s.indexOf(EVENT_KEYWORD_FLING) >= 0) && args.length == 4) {
-            float xStart = Float.parseFloat(args[0]);
-            float yStart = Float.parseFloat(args[1]);
-            float xEnd = Float.parseFloat(args[2]);
-            float yEnd = Float.parseFloat(args[3]);
-            PointF start = new PointF(xStart, yStart);
-            PointF end = new PointF(xEnd, yEnd);
-            MonkeySourceRandom.generateFlingEvents(start, end, mQ);
-        }
-
         // Handle flip events
         if (s.indexOf(EVENT_KEYWORD_FLIP) >= 0 && args.length == 1) {
             boolean keyboardOpen = Boolean.parseBoolean(args[0]);
diff --git a/docs/copyright-templates/asm.txt b/docs/copyright-templates/asm.txt
index f33c86d..22f9dd2 100644
--- a/docs/copyright-templates/asm.txt
+++ b/docs/copyright-templates/asm.txt
@@ -1,4 +1,4 @@
-; Copyright (C) 2011 The Android Open Source Project
+; Copyright 2013 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.
diff --git a/docs/copyright-templates/bash.txt b/docs/copyright-templates/bash.txt
index ae90a87..389b21a 100644
--- a/docs/copyright-templates/bash.txt
+++ b/docs/copyright-templates/bash.txt
@@ -1,6 +1,6 @@
 #!/bin/bash
 #
-# Copyright (C) 2011 The Android Open Source Project
+# Copyright 2013 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.
diff --git a/docs/copyright-templates/bsd/c.txt b/docs/copyright-templates/bsd/c.txt
index 39e77f0..55932e7 100644
--- a/docs/copyright-templates/bsd/c.txt
+++ b/docs/copyright-templates/bsd/c.txt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright 2013 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/docs/copyright-templates/c.txt b/docs/copyright-templates/c.txt
index efa50f3..11644d2 100644
--- a/docs/copyright-templates/c.txt
+++ b/docs/copyright-templates/c.txt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright 2013 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.
diff --git a/docs/copyright-templates/java.txt b/docs/copyright-templates/java.txt
index efa50f3..11644d2 100644
--- a/docs/copyright-templates/java.txt
+++ b/docs/copyright-templates/java.txt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright 2013 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.
diff --git a/docs/copyright-templates/make.txt b/docs/copyright-templates/make.txt
index 851a7a8..317c4e6 100644
--- a/docs/copyright-templates/make.txt
+++ b/docs/copyright-templates/make.txt
@@ -1,4 +1,4 @@
-# Copyright (C) 2011 The Android Open Source Project
+# Copyright 2013 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.
diff --git a/docs/copyright-templates/plain.txt b/docs/copyright-templates/plain.txt
index 12f1016..5db9282 100644
--- a/docs/copyright-templates/plain.txt
+++ b/docs/copyright-templates/plain.txt
@@ -1,4 +1,4 @@
-Copyright (C) 2011 The Android Open Source Project
+Copyright 2013 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.
diff --git a/docs/copyright-templates/sh.txt b/docs/copyright-templates/sh.txt
index 7a3adb8..7bf532b 100644
--- a/docs/copyright-templates/sh.txt
+++ b/docs/copyright-templates/sh.txt
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# Copyright (C) 2011 The Android Open Source Project
+# Copyright 2013 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.
diff --git a/docs/copyright-templates/xml.txt b/docs/copyright-templates/xml.txt
index 1be0191..9d10d88 100644
--- a/docs/copyright-templates/xml.txt
+++ b/docs/copyright-templates/xml.txt
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
+<!-- Copyright 2013 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.
diff --git a/host/windows/usb/android_winusb.inf b/host/windows/usb/android_winusb.inf
index f26a75c..8dbfe09 100755
--- a/host/windows/usb/android_winusb.inf
+++ b/host/windows/usb/android_winusb.inf
@@ -6,7 +6,7 @@
 Class               = AndroidUsbDeviceClass

 ClassGuid           = {3F966BD9-FA04-4ec5-991C-D326973B5128}

 Provider            = %ProviderName%

-DriverVer           = 08/27/2012,7.0.0000.00001

+DriverVer           = 07/09/2013,8.0.0000.00000

 CatalogFile.NTx86   = androidwinusb86.cat

 CatalogFile.NTamd64 = androidwinusba64.cat

 

@@ -38,8 +38,6 @@
 

 ;Google Nexus 7

 %SingleBootLoaderInterface% = USB_Install, USB\VID_18D1&PID_4E40

-%SingleAdbInterface%        = USB_Install, USB\VID_18D1&PID_4E41

-%CompositeAdbInterface%     = USB_Install, USB\VID_18D1&PID_4E42

 %CompositeAdbInterface%     = USB_Install, USB\VID_18D1&PID_4E42&MI_01

 %CompositeAdbInterface%     = USB_Install, USB\VID_18D1&PID_4E44&MI_01

 

@@ -49,12 +47,8 @@
 

 ;Google Nexus (generic)

 %SingleBootLoaderInterface% = USB_Install, USB\VID_18D1&PID_4EE0

-%SingleAdbInterface%        = USB_Install, USB\VID_18D1&PID_4EE1

-%CompositeAdbInterface%     = USB_Install, USB\VID_18D1&PID_4EE2

 %CompositeAdbInterface%     = USB_Install, USB\VID_18D1&PID_4EE2&MI_01

-%SingleAdbInterface%        = USB_Install, USB\VID_18D1&PID_4EE3

-%CompositeAdbInterface%     = USB_Install, USB\VID_18D1&PID_4EE4&MI_01

-%SingleAdbInterface%        = USB_Install, USB\VID_18D1&PID_4EE5

+%CompositeAdbInterface%     = USB_Install, USB\VID_18D1&PID_4EE4&MI_02

 %CompositeAdbInterface%     = USB_Install, USB\VID_18D1&PID_4EE6&MI_01

 

 

@@ -74,8 +68,6 @@
 

 ;Google Nexus 7

 %SingleBootLoaderInterface% = USB_Install, USB\VID_18D1&PID_4E40

-%SingleAdbInterface%        = USB_Install, USB\VID_18D1&PID_4E41

-%CompositeAdbInterface%     = USB_Install, USB\VID_18D1&PID_4E42

 %CompositeAdbInterface%     = USB_Install, USB\VID_18D1&PID_4E42&MI_01

 %CompositeAdbInterface%     = USB_Install, USB\VID_18D1&PID_4E44&MI_01

 

@@ -85,12 +77,8 @@
 

 ;Google Nexus (generic)

 %SingleBootLoaderInterface% = USB_Install, USB\VID_18D1&PID_4EE0

-%SingleAdbInterface%        = USB_Install, USB\VID_18D1&PID_4EE1

-%CompositeAdbInterface%     = USB_Install, USB\VID_18D1&PID_4EE2

 %CompositeAdbInterface%     = USB_Install, USB\VID_18D1&PID_4EE2&MI_01

-%SingleAdbInterface%        = USB_Install, USB\VID_18D1&PID_4EE3

-%CompositeAdbInterface%     = USB_Install, USB\VID_18D1&PID_4EE4&MI_01

-%SingleAdbInterface%        = USB_Install, USB\VID_18D1&PID_4EE5

+%CompositeAdbInterface%     = USB_Install, USB\VID_18D1&PID_4EE4&MI_02

 %CompositeAdbInterface%     = USB_Install, USB\VID_18D1&PID_4EE6&MI_01

 

 [USB_Install]

diff --git a/ide/eclipse/.classpath b/ide/eclipse/.classpath
index 6a8b47f..3e30be1 100644
--- a/ide/eclipse/.classpath
+++ b/ide/eclipse/.classpath
@@ -16,6 +16,7 @@
 	<classpathentry kind="src" path="packages/apps/Gallery2/src_pd"/>
 	<classpathentry kind="src" path="packages/apps/Gallery2/gallerycommon/src"/>
 	<classpathentry kind="src" path="packages/apps/HTMLViewer/src"/>
+	<classpathentry kind="src" path="packages/apps/InCallUI/src"/>
 	<classpathentry kind="src" path="packages/apps/Launcher2/src"/>
 	<classpathentry kind="src" path="packages/apps/Mms/src"/>
 	<classpathentry kind="src" path="packages/apps/Nfc/src"/>
@@ -38,6 +39,8 @@
 	<classpathentry kind="src" path="packages/screensavers/Basic/src"/>
 	<classpathentry kind="src" path="packages/screensavers/PhotoTable/src"/>
 	<classpathentry kind="src" path="packages/screensavers/WebView/src"/>
+	<classpathentry kind="src" path="packages/services/Telephony/src"/>
+	<classpathentry kind="src" path="packages/services/Telephony/common/src"/>
 	<classpathentry kind="src" path="frameworks/base/cmds/am/src"/>
 	<classpathentry kind="src" path="frameworks/base/cmds/input/src"/>
 	<classpathentry kind="src" path="frameworks/base/cmds/pm/src"/>
@@ -50,6 +53,7 @@
 	<classpathentry kind="src" path="frameworks/base/location/java"/>
 	<classpathentry kind="src" path="frameworks/base/location/lib/java"/>
 	<classpathentry kind="src" path="frameworks/base/media/java"/>
+	<classpathentry kind="src" path="frameworks/base/media/tests/MediaFrameworkTest/src"/>
 	<classpathentry kind="src" path="frameworks/base/media/mca/effect/java"/>
 	<classpathentry kind="src" path="frameworks/base/media/mca/filterfw/java"/>
 	<classpathentry kind="src" path="frameworks/base/media/mca/filterpacks/java"/>
@@ -95,8 +99,8 @@
 	<classpathentry kind="src" path="development/samples/Snake/src"/>
 	<classpathentry kind="src" path="development/samples/Snake/tests/src"/>
 	<classpathentry kind="src" path="libcore/dalvik/src/main/java"/>
-	<classpathentry kind="src" path="libcore/libdvm/src/main/java"/>
 	<classpathentry kind="src" path="libcore/json/src/main/java"/>
+	<classpathentry kind="src" path="libcore/libdvm/src/main/java"/>
 	<classpathentry kind="src" path="libcore/luni/src/main/java"/>
 	<classpathentry kind="src" path="libcore/xml/src/main/java"/>
 	<classpathentry kind="src" path="out/target/common/obj/APPS/ApiDemos_intermediates/src/src"/>
@@ -111,21 +115,24 @@
 	<classpathentry kind="src" path="out/target/common/obj/APPS/SystemUI_intermediates/src/src"/>
 	<classpathentry kind="src" path="out/target/common/obj/JAVA_LIBRARIES/android-common-carousel_intermediates/src/renderscript/src"/>
 	<classpathentry kind="src" path="out/target/common/obj/JAVA_LIBRARIES/com.android.emailcommon_intermediates/src/src"/>
-	<classpathentry kind="src" path="out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java"/>
-	<classpathentry kind="src" path="out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/keystore/java"/>
-	<classpathentry kind="src" path="out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/location/java"/>
-	<classpathentry kind="src" path="out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/media/java"/>
-	<classpathentry kind="src" path="out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/telephony/java"/>
-	<classpathentry kind="src" path="out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/wifi/java"/>
+	<classpathentry kind="src" path="out/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java"/>
+	<classpathentry kind="src" path="out/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/keystore/java"/>
+	<classpathentry kind="src" path="out/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/location/java"/>
+	<classpathentry kind="src" path="out/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/media/java"/>
+	<classpathentry kind="src" path="out/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/telephony/java"/>
+	<classpathentry kind="src" path="out/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/wifi/java"/>
 	<classpathentry kind="src" path="out/target/common/obj/JAVA_LIBRARIES/NfcLogTags_intermediates/src/src"/>
 	<classpathentry kind="src" path="out/target/common/obj/JAVA_LIBRARIES/services_intermediates/src"/>
 	<classpathentry kind="src" path="out/target/common/obj/JAVA_LIBRARIES/telephony-common_intermediates/src/src/java"/>
 	<classpathentry kind="src" path="out/target/common/obj/JAVA_LIBRARIES/voip-common_intermediates/src/src/java"/>
 	<classpathentry kind="src" path="out/target/common/R"/>
+	<classpathentry kind="src" path="pdk/apps/TestingCamera2/src"/>
 	<classpathentry kind="src" path="external/apache-http/src"/>
 	<classpathentry kind="src" path="external/bouncycastle/bcprov/src/main/java"/>
 	<classpathentry kind="src" path="external/guava/guava/src"/>
+	<classpathentry kind="src" path="external/junit/src"/>
 	<classpathentry kind="src" path="external/libphonenumber/java/src"/>
+	<classpathentry kind="src" path="external/mockito/src"/>
 	<classpathentry kind="src" path="external/mp4parser/isoparser/src/main/java"/>
 	<classpathentry kind="src" path="external/nist-sip/java"/>
 	<classpathentry kind="src" path="external/tagsoup/src"/>
diff --git a/ide/eclipse/README.importing-to-eclipse.txt b/ide/eclipse/README.importing-to-eclipse.txt
index dffa0ab..c98bf52 100644
--- a/ide/eclipse/README.importing-to-eclipse.txt
+++ b/ide/eclipse/README.importing-to-eclipse.txt
@@ -1,6 +1,33 @@
+(Java)
+
 To import the formatter, go to the preferences, section Java > Code Style >
 formatter, then click on import and choose
 development/ide/eclipse/android-formatting.xml
 
 To import the import order, to go into Java > Code Style > Organize Import,
 then click on import and choose development/ide/eclipse/android.importorder
+
+(C++)
+
+To import the include paths, go to Project > Properties > C/C++ General >
+Paths and Symbols, then click on "Includes" and then click on "Import Settings".
+Choose development/ide/eclipse/android-include-paths.xml and hit Finish.
+You will need to re-index for the changes to get picked up (right click project
+in Package Explorer, then Index > Rebuild).
+
+To import the symbols, go to Project > Properties > C/C++ General >
+Paths and Symbols, then click on "Symbols" and then click on "Import Settings".
+Choose development/ide/eclipse/android-symbols.xml and hit Finish.
+You will need to re-index for the changes to get picked up (right click project
+in Package Explorer, then Index > Rebuild).
+
+In addition, you will need to add some include files (no way to import this
+from an XML file) by hand. Go to Project > Properties > C/C++ General >
+Paths and Symbols, then click on "Include Files" and click on "Add". Check
+"Add to all configurations" and "Add to all languages". Repeat for these files:
+
+    ${ProjDirPath}/build/core/combo/include/arch/linux-arm/AndroidConfig.h
+
+If you are having trouble seeing the "Include Files" tab, you will need to
+enable it in the global preference panel under "C/C++" /
+"Property Pages Settings".
diff --git a/ide/eclipse/android-include-paths.xml b/ide/eclipse/android-include-paths.xml
index be188bd..4487fa4 100644
--- a/ide/eclipse/android-include-paths.xml
+++ b/ide/eclipse/android-include-paths.xml
@@ -31,6 +31,7 @@
 <includepath>${ProjDirPath}/system/core/include/arch/linux-arm</includepath>
 <includepath>${ProjDirPath}/dalvik/libnativehelper/include</includepath>
 <includepath>${ProjDirPath}/dalvik/libnativehelper/include/nativehelper</includepath>
+<includepath>${ProjDirPath}/system/media/camera/include</includepath>
 
 </language>
 <language name="GNU C++">
@@ -60,6 +61,7 @@
 <includepath>${ProjDirPath}/system/core/include/arch/linux-arm</includepath>
 <includepath>${ProjDirPath}/dalvik/libnativehelper/include</includepath>
 <includepath>${ProjDirPath}/dalvik/libnativehelper/include/nativehelper</includepath>
+<includepath>${ProjDirPath}/system/media/camera/include</includepath>
 
 </language>
 <language name="GNU C">
@@ -89,6 +91,7 @@
 <includepath>${ProjDirPath}/system/core/include/arch/linux-arm</includepath>
 <includepath>${ProjDirPath}/dalvik/libnativehelper/include</includepath>
 <includepath>${ProjDirPath}/dalvik/libnativehelper/include/nativehelper</includepath>
+<includepath>${ProjDirPath}/system/media/camera/include</includepath>
 
 </language>
 </section>
diff --git a/ndk/platforms/android-18/arch-arm/symbols/libGLESv3.so.functions.txt b/ndk/platforms/android-18/arch-arm/symbols/libGLESv3.so.functions.txt
new file mode 100644
index 0000000..6ee108b
--- /dev/null
+++ b/ndk/platforms/android-18/arch-arm/symbols/libGLESv3.so.functions.txt
@@ -0,0 +1,263 @@
+glActiveTexture
+glAttachShader
+glBeginQuery
+glBeginTransformFeedback
+glBindAttribLocation
+glBindBuffer
+glBindBufferBase
+glBindBufferRange
+glBindFramebuffer
+glBindRenderbuffer
+glBindSampler
+glBindTexture
+glBindTransformFeedback
+glBindVertexArray
+glBindVertexArrayOES
+glBlendColor
+glBlendEquation
+glBlendEquationSeparate
+glBlendFunc
+glBlendFuncSeparate
+glBlitFramebuffer
+glBufferData
+glBufferSubData
+glCheckFramebufferStatus
+glClear
+glClearBufferfi
+glClearBufferfv
+glClearBufferiv
+glClearBufferuiv
+glClearColor
+glClearDepthf
+glClearStencil
+glClientWaitSync
+glColorMask
+glCompileShader
+glCompressedTexImage2D
+glCompressedTexImage3D
+glCompressedTexImage3DOES
+glCompressedTexSubImage2D
+glCompressedTexSubImage3D
+glCompressedTexSubImage3DOES
+glCopyBufferSubData
+glCopyTexImage2D
+glCopyTexSubImage2D
+glCopyTexSubImage3D
+glCopyTexSubImage3DOES
+glCreateProgram
+glCreateShader
+glCullFace
+glDeleteBuffers
+glDeleteFramebuffers
+glDeleteProgram
+glDeleteQueries
+glDeleteRenderbuffers
+glDeleteSamplers
+glDeleteShader
+glDeleteSync
+glDeleteTextures
+glDeleteTransformFeedbacks
+glDeleteVertexArrays
+glDeleteVertexArraysOES
+glDepthFunc
+glDepthMask
+glDepthRangef
+glDetachShader
+glDisable
+glDisableVertexAttribArray
+glDrawArrays
+glDrawArraysInstanced
+glDrawBuffers
+glDrawElements
+glDrawElementsInstanced
+glDrawRangeElements
+glEGLImageTargetRenderbufferStorageOES
+glEGLImageTargetTexture2DOES
+glEnable
+glEnableVertexAttribArray
+glEndQuery
+glEndTransformFeedback
+glFenceSync
+glFinish
+glFlush
+glFlushMappedBufferRange
+glFramebufferRenderbuffer
+glFramebufferTexture2D
+glFramebufferTexture3DOES
+glFramebufferTextureLayer
+glFrontFace
+glGenBuffers
+glGenFramebuffers
+glGenQueries
+glGenRenderbuffers
+glGenSamplers
+glGenTextures
+glGenTransformFeedbacks
+glGenVertexArrays
+glGenVertexArraysOES
+glGenerateMipmap
+glGetActiveAttrib
+glGetActiveUniform
+glGetActiveUniformBlockName
+glGetActiveUniformBlockiv
+glGetActiveUniformsiv
+glGetAttachedShaders
+glGetAttribLocation
+glGetBooleanv
+glGetBufferParameteri64v
+glGetBufferParameteriv
+glGetBufferPointerv
+glGetBufferPointervOES
+glGetError
+glGetFloatv
+glGetFragDataLocation
+glGetFramebufferAttachmentParameteriv
+glGetInteger64i_v
+glGetInteger64v
+glGetIntegeri_v
+glGetIntegerv
+glGetInternalformativ
+glGetProgramBinary
+glGetProgramBinaryOES
+glGetProgramInfoLog
+glGetProgramiv
+glGetQueryObjectuiv
+glGetQueryiv
+glGetRenderbufferParameteriv
+glGetSamplerParameterfv
+glGetSamplerParameteriv
+glGetShaderInfoLog
+glGetShaderPrecisionFormat
+glGetShaderSource
+glGetShaderiv
+glGetString
+glGetStringi
+glGetSynciv
+glGetTexParameterfv
+glGetTexParameteriv
+glGetTransformFeedbackVarying
+glGetUniformBlockIndex
+glGetUniformIndices
+glGetUniformLocation
+glGetUniformfv
+glGetUniformiv
+glGetUniformuiv
+glGetVertexAttribIiv
+glGetVertexAttribIuiv
+glGetVertexAttribPointerv
+glGetVertexAttribfv
+glGetVertexAttribiv
+glHint
+glInvalidateFramebuffer
+glInvalidateSubFramebuffer
+glIsBuffer
+glIsEnabled
+glIsFramebuffer
+glIsProgram
+glIsQuery
+glIsRenderbuffer
+glIsSampler
+glIsShader
+glIsSync
+glIsTexture
+glIsTransformFeedback
+glIsVertexArray
+glIsVertexArrayOES
+glLineWidth
+glLinkProgram
+glMapBufferOES
+glMapBufferRange
+glPauseTransformFeedback
+glPixelStorei
+glPolygonOffset
+glProgramBinary
+glProgramBinaryOES
+glProgramParameteri
+glReadBuffer
+glReadPixels
+glReleaseShaderCompiler
+glRenderbufferStorage
+glRenderbufferStorageMultisample
+glResumeTransformFeedback
+glSampleCoverage
+glSamplerParameterf
+glSamplerParameterfv
+glSamplerParameteri
+glSamplerParameteriv
+glScissor
+glShaderBinary
+glShaderSource
+glStencilFunc
+glStencilFuncSeparate
+glStencilMask
+glStencilMaskSeparate
+glStencilOp
+glStencilOpSeparate
+glTexImage2D
+glTexImage3D
+glTexImage3DOES
+glTexParameterf
+glTexParameterfv
+glTexParameteri
+glTexParameteriv
+glTexStorage2D
+glTexStorage3D
+glTexSubImage2D
+glTexSubImage3D
+glTexSubImage3DOES
+glTransformFeedbackVaryings
+glUniform1f
+glUniform1fv
+glUniform1i
+glUniform1iv
+glUniform1ui
+glUniform1uiv
+glUniform2f
+glUniform2fv
+glUniform2i
+glUniform2iv
+glUniform2ui
+glUniform2uiv
+glUniform3f
+glUniform3fv
+glUniform3i
+glUniform3iv
+glUniform3ui
+glUniform3uiv
+glUniform4f
+glUniform4fv
+glUniform4i
+glUniform4iv
+glUniform4ui
+glUniform4uiv
+glUniformBlockBinding
+glUniformMatrix2fv
+glUniformMatrix2x3fv
+glUniformMatrix2x4fv
+glUniformMatrix3fv
+glUniformMatrix3x2fv
+glUniformMatrix3x4fv
+glUniformMatrix4fv
+glUniformMatrix4x2fv
+glUniformMatrix4x3fv
+glUnmapBuffer
+glUnmapBufferOES
+glUseProgram
+glValidateProgram
+glVertexAttrib1f
+glVertexAttrib1fv
+glVertexAttrib2f
+glVertexAttrib2fv
+glVertexAttrib3f
+glVertexAttrib3fv
+glVertexAttrib4f
+glVertexAttrib4fv
+glVertexAttribDivisor
+glVertexAttribI4i
+glVertexAttribI4iv
+glVertexAttribI4ui
+glVertexAttribI4uiv
+glVertexAttribIPointer
+glVertexAttribPointer
+glViewport
+glWaitSync
diff --git a/ndk/platforms/android-18/arch-arm/symbols/libGLESv3.so.variables.txt b/ndk/platforms/android-18/arch-arm/symbols/libGLESv3.so.variables.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/ndk/platforms/android-18/arch-arm/symbols/libGLESv3.so.variables.txt
@@ -0,0 +1 @@
+
diff --git a/ndk/platforms/android-18/arch-mips/symbols/libGLESv3.so.functions.txt b/ndk/platforms/android-18/arch-mips/symbols/libGLESv3.so.functions.txt
new file mode 100644
index 0000000..6ee108b
--- /dev/null
+++ b/ndk/platforms/android-18/arch-mips/symbols/libGLESv3.so.functions.txt
@@ -0,0 +1,263 @@
+glActiveTexture
+glAttachShader
+glBeginQuery
+glBeginTransformFeedback
+glBindAttribLocation
+glBindBuffer
+glBindBufferBase
+glBindBufferRange
+glBindFramebuffer
+glBindRenderbuffer
+glBindSampler
+glBindTexture
+glBindTransformFeedback
+glBindVertexArray
+glBindVertexArrayOES
+glBlendColor
+glBlendEquation
+glBlendEquationSeparate
+glBlendFunc
+glBlendFuncSeparate
+glBlitFramebuffer
+glBufferData
+glBufferSubData
+glCheckFramebufferStatus
+glClear
+glClearBufferfi
+glClearBufferfv
+glClearBufferiv
+glClearBufferuiv
+glClearColor
+glClearDepthf
+glClearStencil
+glClientWaitSync
+glColorMask
+glCompileShader
+glCompressedTexImage2D
+glCompressedTexImage3D
+glCompressedTexImage3DOES
+glCompressedTexSubImage2D
+glCompressedTexSubImage3D
+glCompressedTexSubImage3DOES
+glCopyBufferSubData
+glCopyTexImage2D
+glCopyTexSubImage2D
+glCopyTexSubImage3D
+glCopyTexSubImage3DOES
+glCreateProgram
+glCreateShader
+glCullFace
+glDeleteBuffers
+glDeleteFramebuffers
+glDeleteProgram
+glDeleteQueries
+glDeleteRenderbuffers
+glDeleteSamplers
+glDeleteShader
+glDeleteSync
+glDeleteTextures
+glDeleteTransformFeedbacks
+glDeleteVertexArrays
+glDeleteVertexArraysOES
+glDepthFunc
+glDepthMask
+glDepthRangef
+glDetachShader
+glDisable
+glDisableVertexAttribArray
+glDrawArrays
+glDrawArraysInstanced
+glDrawBuffers
+glDrawElements
+glDrawElementsInstanced
+glDrawRangeElements
+glEGLImageTargetRenderbufferStorageOES
+glEGLImageTargetTexture2DOES
+glEnable
+glEnableVertexAttribArray
+glEndQuery
+glEndTransformFeedback
+glFenceSync
+glFinish
+glFlush
+glFlushMappedBufferRange
+glFramebufferRenderbuffer
+glFramebufferTexture2D
+glFramebufferTexture3DOES
+glFramebufferTextureLayer
+glFrontFace
+glGenBuffers
+glGenFramebuffers
+glGenQueries
+glGenRenderbuffers
+glGenSamplers
+glGenTextures
+glGenTransformFeedbacks
+glGenVertexArrays
+glGenVertexArraysOES
+glGenerateMipmap
+glGetActiveAttrib
+glGetActiveUniform
+glGetActiveUniformBlockName
+glGetActiveUniformBlockiv
+glGetActiveUniformsiv
+glGetAttachedShaders
+glGetAttribLocation
+glGetBooleanv
+glGetBufferParameteri64v
+glGetBufferParameteriv
+glGetBufferPointerv
+glGetBufferPointervOES
+glGetError
+glGetFloatv
+glGetFragDataLocation
+glGetFramebufferAttachmentParameteriv
+glGetInteger64i_v
+glGetInteger64v
+glGetIntegeri_v
+glGetIntegerv
+glGetInternalformativ
+glGetProgramBinary
+glGetProgramBinaryOES
+glGetProgramInfoLog
+glGetProgramiv
+glGetQueryObjectuiv
+glGetQueryiv
+glGetRenderbufferParameteriv
+glGetSamplerParameterfv
+glGetSamplerParameteriv
+glGetShaderInfoLog
+glGetShaderPrecisionFormat
+glGetShaderSource
+glGetShaderiv
+glGetString
+glGetStringi
+glGetSynciv
+glGetTexParameterfv
+glGetTexParameteriv
+glGetTransformFeedbackVarying
+glGetUniformBlockIndex
+glGetUniformIndices
+glGetUniformLocation
+glGetUniformfv
+glGetUniformiv
+glGetUniformuiv
+glGetVertexAttribIiv
+glGetVertexAttribIuiv
+glGetVertexAttribPointerv
+glGetVertexAttribfv
+glGetVertexAttribiv
+glHint
+glInvalidateFramebuffer
+glInvalidateSubFramebuffer
+glIsBuffer
+glIsEnabled
+glIsFramebuffer
+glIsProgram
+glIsQuery
+glIsRenderbuffer
+glIsSampler
+glIsShader
+glIsSync
+glIsTexture
+glIsTransformFeedback
+glIsVertexArray
+glIsVertexArrayOES
+glLineWidth
+glLinkProgram
+glMapBufferOES
+glMapBufferRange
+glPauseTransformFeedback
+glPixelStorei
+glPolygonOffset
+glProgramBinary
+glProgramBinaryOES
+glProgramParameteri
+glReadBuffer
+glReadPixels
+glReleaseShaderCompiler
+glRenderbufferStorage
+glRenderbufferStorageMultisample
+glResumeTransformFeedback
+glSampleCoverage
+glSamplerParameterf
+glSamplerParameterfv
+glSamplerParameteri
+glSamplerParameteriv
+glScissor
+glShaderBinary
+glShaderSource
+glStencilFunc
+glStencilFuncSeparate
+glStencilMask
+glStencilMaskSeparate
+glStencilOp
+glStencilOpSeparate
+glTexImage2D
+glTexImage3D
+glTexImage3DOES
+glTexParameterf
+glTexParameterfv
+glTexParameteri
+glTexParameteriv
+glTexStorage2D
+glTexStorage3D
+glTexSubImage2D
+glTexSubImage3D
+glTexSubImage3DOES
+glTransformFeedbackVaryings
+glUniform1f
+glUniform1fv
+glUniform1i
+glUniform1iv
+glUniform1ui
+glUniform1uiv
+glUniform2f
+glUniform2fv
+glUniform2i
+glUniform2iv
+glUniform2ui
+glUniform2uiv
+glUniform3f
+glUniform3fv
+glUniform3i
+glUniform3iv
+glUniform3ui
+glUniform3uiv
+glUniform4f
+glUniform4fv
+glUniform4i
+glUniform4iv
+glUniform4ui
+glUniform4uiv
+glUniformBlockBinding
+glUniformMatrix2fv
+glUniformMatrix2x3fv
+glUniformMatrix2x4fv
+glUniformMatrix3fv
+glUniformMatrix3x2fv
+glUniformMatrix3x4fv
+glUniformMatrix4fv
+glUniformMatrix4x2fv
+glUniformMatrix4x3fv
+glUnmapBuffer
+glUnmapBufferOES
+glUseProgram
+glValidateProgram
+glVertexAttrib1f
+glVertexAttrib1fv
+glVertexAttrib2f
+glVertexAttrib2fv
+glVertexAttrib3f
+glVertexAttrib3fv
+glVertexAttrib4f
+glVertexAttrib4fv
+glVertexAttribDivisor
+glVertexAttribI4i
+glVertexAttribI4iv
+glVertexAttribI4ui
+glVertexAttribI4uiv
+glVertexAttribIPointer
+glVertexAttribPointer
+glViewport
+glWaitSync
diff --git a/ndk/platforms/android-18/arch-mips/symbols/libGLESv3.so.variables.txt b/ndk/platforms/android-18/arch-mips/symbols/libGLESv3.so.variables.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/ndk/platforms/android-18/arch-mips/symbols/libGLESv3.so.variables.txt
@@ -0,0 +1 @@
+
diff --git a/ndk/platforms/android-18/arch-x86/symbols/libGLESv3.so.functions.txt b/ndk/platforms/android-18/arch-x86/symbols/libGLESv3.so.functions.txt
new file mode 100644
index 0000000..6ee108b
--- /dev/null
+++ b/ndk/platforms/android-18/arch-x86/symbols/libGLESv3.so.functions.txt
@@ -0,0 +1,263 @@
+glActiveTexture
+glAttachShader
+glBeginQuery
+glBeginTransformFeedback
+glBindAttribLocation
+glBindBuffer
+glBindBufferBase
+glBindBufferRange
+glBindFramebuffer
+glBindRenderbuffer
+glBindSampler
+glBindTexture
+glBindTransformFeedback
+glBindVertexArray
+glBindVertexArrayOES
+glBlendColor
+glBlendEquation
+glBlendEquationSeparate
+glBlendFunc
+glBlendFuncSeparate
+glBlitFramebuffer
+glBufferData
+glBufferSubData
+glCheckFramebufferStatus
+glClear
+glClearBufferfi
+glClearBufferfv
+glClearBufferiv
+glClearBufferuiv
+glClearColor
+glClearDepthf
+glClearStencil
+glClientWaitSync
+glColorMask
+glCompileShader
+glCompressedTexImage2D
+glCompressedTexImage3D
+glCompressedTexImage3DOES
+glCompressedTexSubImage2D
+glCompressedTexSubImage3D
+glCompressedTexSubImage3DOES
+glCopyBufferSubData
+glCopyTexImage2D
+glCopyTexSubImage2D
+glCopyTexSubImage3D
+glCopyTexSubImage3DOES
+glCreateProgram
+glCreateShader
+glCullFace
+glDeleteBuffers
+glDeleteFramebuffers
+glDeleteProgram
+glDeleteQueries
+glDeleteRenderbuffers
+glDeleteSamplers
+glDeleteShader
+glDeleteSync
+glDeleteTextures
+glDeleteTransformFeedbacks
+glDeleteVertexArrays
+glDeleteVertexArraysOES
+glDepthFunc
+glDepthMask
+glDepthRangef
+glDetachShader
+glDisable
+glDisableVertexAttribArray
+glDrawArrays
+glDrawArraysInstanced
+glDrawBuffers
+glDrawElements
+glDrawElementsInstanced
+glDrawRangeElements
+glEGLImageTargetRenderbufferStorageOES
+glEGLImageTargetTexture2DOES
+glEnable
+glEnableVertexAttribArray
+glEndQuery
+glEndTransformFeedback
+glFenceSync
+glFinish
+glFlush
+glFlushMappedBufferRange
+glFramebufferRenderbuffer
+glFramebufferTexture2D
+glFramebufferTexture3DOES
+glFramebufferTextureLayer
+glFrontFace
+glGenBuffers
+glGenFramebuffers
+glGenQueries
+glGenRenderbuffers
+glGenSamplers
+glGenTextures
+glGenTransformFeedbacks
+glGenVertexArrays
+glGenVertexArraysOES
+glGenerateMipmap
+glGetActiveAttrib
+glGetActiveUniform
+glGetActiveUniformBlockName
+glGetActiveUniformBlockiv
+glGetActiveUniformsiv
+glGetAttachedShaders
+glGetAttribLocation
+glGetBooleanv
+glGetBufferParameteri64v
+glGetBufferParameteriv
+glGetBufferPointerv
+glGetBufferPointervOES
+glGetError
+glGetFloatv
+glGetFragDataLocation
+glGetFramebufferAttachmentParameteriv
+glGetInteger64i_v
+glGetInteger64v
+glGetIntegeri_v
+glGetIntegerv
+glGetInternalformativ
+glGetProgramBinary
+glGetProgramBinaryOES
+glGetProgramInfoLog
+glGetProgramiv
+glGetQueryObjectuiv
+glGetQueryiv
+glGetRenderbufferParameteriv
+glGetSamplerParameterfv
+glGetSamplerParameteriv
+glGetShaderInfoLog
+glGetShaderPrecisionFormat
+glGetShaderSource
+glGetShaderiv
+glGetString
+glGetStringi
+glGetSynciv
+glGetTexParameterfv
+glGetTexParameteriv
+glGetTransformFeedbackVarying
+glGetUniformBlockIndex
+glGetUniformIndices
+glGetUniformLocation
+glGetUniformfv
+glGetUniformiv
+glGetUniformuiv
+glGetVertexAttribIiv
+glGetVertexAttribIuiv
+glGetVertexAttribPointerv
+glGetVertexAttribfv
+glGetVertexAttribiv
+glHint
+glInvalidateFramebuffer
+glInvalidateSubFramebuffer
+glIsBuffer
+glIsEnabled
+glIsFramebuffer
+glIsProgram
+glIsQuery
+glIsRenderbuffer
+glIsSampler
+glIsShader
+glIsSync
+glIsTexture
+glIsTransformFeedback
+glIsVertexArray
+glIsVertexArrayOES
+glLineWidth
+glLinkProgram
+glMapBufferOES
+glMapBufferRange
+glPauseTransformFeedback
+glPixelStorei
+glPolygonOffset
+glProgramBinary
+glProgramBinaryOES
+glProgramParameteri
+glReadBuffer
+glReadPixels
+glReleaseShaderCompiler
+glRenderbufferStorage
+glRenderbufferStorageMultisample
+glResumeTransformFeedback
+glSampleCoverage
+glSamplerParameterf
+glSamplerParameterfv
+glSamplerParameteri
+glSamplerParameteriv
+glScissor
+glShaderBinary
+glShaderSource
+glStencilFunc
+glStencilFuncSeparate
+glStencilMask
+glStencilMaskSeparate
+glStencilOp
+glStencilOpSeparate
+glTexImage2D
+glTexImage3D
+glTexImage3DOES
+glTexParameterf
+glTexParameterfv
+glTexParameteri
+glTexParameteriv
+glTexStorage2D
+glTexStorage3D
+glTexSubImage2D
+glTexSubImage3D
+glTexSubImage3DOES
+glTransformFeedbackVaryings
+glUniform1f
+glUniform1fv
+glUniform1i
+glUniform1iv
+glUniform1ui
+glUniform1uiv
+glUniform2f
+glUniform2fv
+glUniform2i
+glUniform2iv
+glUniform2ui
+glUniform2uiv
+glUniform3f
+glUniform3fv
+glUniform3i
+glUniform3iv
+glUniform3ui
+glUniform3uiv
+glUniform4f
+glUniform4fv
+glUniform4i
+glUniform4iv
+glUniform4ui
+glUniform4uiv
+glUniformBlockBinding
+glUniformMatrix2fv
+glUniformMatrix2x3fv
+glUniformMatrix2x4fv
+glUniformMatrix3fv
+glUniformMatrix3x2fv
+glUniformMatrix3x4fv
+glUniformMatrix4fv
+glUniformMatrix4x2fv
+glUniformMatrix4x3fv
+glUnmapBuffer
+glUnmapBufferOES
+glUseProgram
+glValidateProgram
+glVertexAttrib1f
+glVertexAttrib1fv
+glVertexAttrib2f
+glVertexAttrib2fv
+glVertexAttrib3f
+glVertexAttrib3fv
+glVertexAttrib4f
+glVertexAttrib4fv
+glVertexAttribDivisor
+glVertexAttribI4i
+glVertexAttribI4iv
+glVertexAttribI4ui
+glVertexAttribI4uiv
+glVertexAttribIPointer
+glVertexAttribPointer
+glViewport
+glWaitSync
diff --git a/ndk/platforms/android-18/arch-x86/symbols/libGLESv3.so.variables.txt b/ndk/platforms/android-18/arch-x86/symbols/libGLESv3.so.variables.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/ndk/platforms/android-18/arch-x86/symbols/libGLESv3.so.variables.txt
@@ -0,0 +1 @@
+
diff --git a/ndk/platforms/android-18/include/GLES3/gl3.h b/ndk/platforms/android-18/include/GLES3/gl3.h
new file mode 100644
index 0000000..9c79862
--- /dev/null
+++ b/ndk/platforms/android-18/include/GLES3/gl3.h
@@ -0,0 +1,1061 @@
+#ifndef __gl3_h_
+#define __gl3_h_
+
+/* 
+ * gl3.h last updated on $Date: 2013-02-12 14:37:24 -0800 (Tue, 12 Feb 2013) $
+ */
+
+#include <GLES3/gl3platform.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright (c) 2007-2013 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+/*-------------------------------------------------------------------------
+ * Data type definitions
+ *-----------------------------------------------------------------------*/
+
+/* OpenGL ES 2.0 */
+
+typedef void             GLvoid;
+typedef char             GLchar;
+typedef unsigned int     GLenum;
+typedef unsigned char    GLboolean;
+typedef unsigned int     GLbitfield;
+typedef khronos_int8_t   GLbyte;
+typedef short            GLshort;
+typedef int              GLint;
+typedef int              GLsizei;
+typedef khronos_uint8_t  GLubyte;
+typedef unsigned short   GLushort;
+typedef unsigned int     GLuint;
+typedef khronos_float_t  GLfloat;
+typedef khronos_float_t  GLclampf;
+typedef khronos_int32_t  GLfixed;
+typedef khronos_intptr_t GLintptr;
+typedef khronos_ssize_t  GLsizeiptr;
+
+/* OpenGL ES 3.0 */
+
+typedef unsigned short   GLhalf;
+typedef khronos_int64_t  GLint64;
+typedef khronos_uint64_t GLuint64;
+typedef struct __GLsync *GLsync;
+
+/*-------------------------------------------------------------------------
+ * Token definitions
+ *-----------------------------------------------------------------------*/
+
+/* OpenGL ES core versions */
+#define GL_ES_VERSION_3_0                                1
+#define GL_ES_VERSION_2_0                                1
+
+/* OpenGL ES 2.0 */
+
+/* ClearBufferMask */
+#define GL_DEPTH_BUFFER_BIT                              0x00000100
+#define GL_STENCIL_BUFFER_BIT                            0x00000400
+#define GL_COLOR_BUFFER_BIT                              0x00004000
+
+/* Boolean */
+#define GL_FALSE                                         0
+#define GL_TRUE                                          1
+
+/* BeginMode */
+#define GL_POINTS                                        0x0000
+#define GL_LINES                                         0x0001
+#define GL_LINE_LOOP                                     0x0002
+#define GL_LINE_STRIP                                    0x0003
+#define GL_TRIANGLES                                     0x0004
+#define GL_TRIANGLE_STRIP                                0x0005
+#define GL_TRIANGLE_FAN                                  0x0006
+
+/* BlendingFactorDest */
+#define GL_ZERO                                          0
+#define GL_ONE                                           1
+#define GL_SRC_COLOR                                     0x0300
+#define GL_ONE_MINUS_SRC_COLOR                           0x0301
+#define GL_SRC_ALPHA                                     0x0302
+#define GL_ONE_MINUS_SRC_ALPHA                           0x0303
+#define GL_DST_ALPHA                                     0x0304
+#define GL_ONE_MINUS_DST_ALPHA                           0x0305
+
+/* BlendingFactorSrc */
+/*      GL_ZERO */
+/*      GL_ONE */
+#define GL_DST_COLOR                                     0x0306
+#define GL_ONE_MINUS_DST_COLOR                           0x0307
+#define GL_SRC_ALPHA_SATURATE                            0x0308
+/*      GL_SRC_ALPHA */
+/*      GL_ONE_MINUS_SRC_ALPHA */
+/*      GL_DST_ALPHA */
+/*      GL_ONE_MINUS_DST_ALPHA */
+
+/* BlendEquationSeparate */
+#define GL_FUNC_ADD                                      0x8006
+#define GL_BLEND_EQUATION                                0x8009
+#define GL_BLEND_EQUATION_RGB                            0x8009    /* same as BLEND_EQUATION */
+#define GL_BLEND_EQUATION_ALPHA                          0x883D
+
+/* BlendSubtract */
+#define GL_FUNC_SUBTRACT                                 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT                         0x800B
+
+/* Separate Blend Functions */
+#define GL_BLEND_DST_RGB                                 0x80C8
+#define GL_BLEND_SRC_RGB                                 0x80C9
+#define GL_BLEND_DST_ALPHA                               0x80CA
+#define GL_BLEND_SRC_ALPHA                               0x80CB
+#define GL_CONSTANT_COLOR                                0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR                      0x8002
+#define GL_CONSTANT_ALPHA                                0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA                      0x8004
+#define GL_BLEND_COLOR                                   0x8005
+
+/* Buffer Objects */
+#define GL_ARRAY_BUFFER                                  0x8892
+#define GL_ELEMENT_ARRAY_BUFFER                          0x8893
+#define GL_ARRAY_BUFFER_BINDING                          0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING                  0x8895
+
+#define GL_STREAM_DRAW                                   0x88E0
+#define GL_STATIC_DRAW                                   0x88E4
+#define GL_DYNAMIC_DRAW                                  0x88E8
+
+#define GL_BUFFER_SIZE                                   0x8764
+#define GL_BUFFER_USAGE                                  0x8765
+
+#define GL_CURRENT_VERTEX_ATTRIB                         0x8626
+
+/* CullFaceMode */
+#define GL_FRONT                                         0x0404
+#define GL_BACK                                          0x0405
+#define GL_FRONT_AND_BACK                                0x0408
+
+/* DepthFunction */
+/*      GL_NEVER */
+/*      GL_LESS */
+/*      GL_EQUAL */
+/*      GL_LEQUAL */
+/*      GL_GREATER */
+/*      GL_NOTEQUAL */
+/*      GL_GEQUAL */
+/*      GL_ALWAYS */
+
+/* EnableCap */
+#define GL_TEXTURE_2D                                    0x0DE1
+#define GL_CULL_FACE                                     0x0B44
+#define GL_BLEND                                         0x0BE2
+#define GL_DITHER                                        0x0BD0
+#define GL_STENCIL_TEST                                  0x0B90
+#define GL_DEPTH_TEST                                    0x0B71
+#define GL_SCISSOR_TEST                                  0x0C11
+#define GL_POLYGON_OFFSET_FILL                           0x8037
+#define GL_SAMPLE_ALPHA_TO_COVERAGE                      0x809E
+#define GL_SAMPLE_COVERAGE                               0x80A0
+
+/* ErrorCode */
+#define GL_NO_ERROR                                      0
+#define GL_INVALID_ENUM                                  0x0500
+#define GL_INVALID_VALUE                                 0x0501
+#define GL_INVALID_OPERATION                             0x0502
+#define GL_OUT_OF_MEMORY                                 0x0505
+
+/* FrontFaceDirection */
+#define GL_CW                                            0x0900
+#define GL_CCW                                           0x0901
+
+/* GetPName */
+#define GL_LINE_WIDTH                                    0x0B21
+#define GL_ALIASED_POINT_SIZE_RANGE                      0x846D
+#define GL_ALIASED_LINE_WIDTH_RANGE                      0x846E
+#define GL_CULL_FACE_MODE                                0x0B45
+#define GL_FRONT_FACE                                    0x0B46
+#define GL_DEPTH_RANGE                                   0x0B70
+#define GL_DEPTH_WRITEMASK                               0x0B72
+#define GL_DEPTH_CLEAR_VALUE                             0x0B73
+#define GL_DEPTH_FUNC                                    0x0B74
+#define GL_STENCIL_CLEAR_VALUE                           0x0B91
+#define GL_STENCIL_FUNC                                  0x0B92
+#define GL_STENCIL_FAIL                                  0x0B94
+#define GL_STENCIL_PASS_DEPTH_FAIL                       0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS                       0x0B96
+#define GL_STENCIL_REF                                   0x0B97
+#define GL_STENCIL_VALUE_MASK                            0x0B93
+#define GL_STENCIL_WRITEMASK                             0x0B98
+#define GL_STENCIL_BACK_FUNC                             0x8800
+#define GL_STENCIL_BACK_FAIL                             0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL                  0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS                  0x8803
+#define GL_STENCIL_BACK_REF                              0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK                       0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK                        0x8CA5
+#define GL_VIEWPORT                                      0x0BA2
+#define GL_SCISSOR_BOX                                   0x0C10
+/*      GL_SCISSOR_TEST */
+#define GL_COLOR_CLEAR_VALUE                             0x0C22
+#define GL_COLOR_WRITEMASK                               0x0C23
+#define GL_UNPACK_ALIGNMENT                              0x0CF5
+#define GL_PACK_ALIGNMENT                                0x0D05
+#define GL_MAX_TEXTURE_SIZE                              0x0D33
+#define GL_MAX_VIEWPORT_DIMS                             0x0D3A
+#define GL_SUBPIXEL_BITS                                 0x0D50
+#define GL_RED_BITS                                      0x0D52
+#define GL_GREEN_BITS                                    0x0D53
+#define GL_BLUE_BITS                                     0x0D54
+#define GL_ALPHA_BITS                                    0x0D55
+#define GL_DEPTH_BITS                                    0x0D56
+#define GL_STENCIL_BITS                                  0x0D57
+#define GL_POLYGON_OFFSET_UNITS                          0x2A00
+/*      GL_POLYGON_OFFSET_FILL */
+#define GL_POLYGON_OFFSET_FACTOR                         0x8038
+#define GL_TEXTURE_BINDING_2D                            0x8069
+#define GL_SAMPLE_BUFFERS                                0x80A8
+#define GL_SAMPLES                                       0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE                         0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT                        0x80AB
+
+/* GetTextureParameter */
+/*      GL_TEXTURE_MAG_FILTER */
+/*      GL_TEXTURE_MIN_FILTER */
+/*      GL_TEXTURE_WRAP_S */
+/*      GL_TEXTURE_WRAP_T */
+
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS                0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS                    0x86A3
+
+/* HintMode */
+#define GL_DONT_CARE                                     0x1100
+#define GL_FASTEST                                       0x1101
+#define GL_NICEST                                        0x1102
+
+/* HintTarget */
+#define GL_GENERATE_MIPMAP_HINT                          0x8192
+
+/* DataType */
+#define GL_BYTE                                          0x1400
+#define GL_UNSIGNED_BYTE                                 0x1401
+#define GL_SHORT                                         0x1402
+#define GL_UNSIGNED_SHORT                                0x1403
+#define GL_INT                                           0x1404
+#define GL_UNSIGNED_INT                                  0x1405
+#define GL_FLOAT                                         0x1406
+#define GL_FIXED                                         0x140C
+
+/* PixelFormat */
+#define GL_DEPTH_COMPONENT                               0x1902
+#define GL_ALPHA                                         0x1906
+#define GL_RGB                                           0x1907
+#define GL_RGBA                                          0x1908
+#define GL_LUMINANCE                                     0x1909
+#define GL_LUMINANCE_ALPHA                               0x190A
+
+/* PixelType */
+/*      GL_UNSIGNED_BYTE */
+#define GL_UNSIGNED_SHORT_4_4_4_4                        0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1                        0x8034
+#define GL_UNSIGNED_SHORT_5_6_5                          0x8363
+
+/* Shaders */
+#define GL_FRAGMENT_SHADER                               0x8B30
+#define GL_VERTEX_SHADER                                 0x8B31
+#define GL_MAX_VERTEX_ATTRIBS                            0x8869
+#define GL_MAX_VERTEX_UNIFORM_VECTORS                    0x8DFB
+#define GL_MAX_VARYING_VECTORS                           0x8DFC
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS              0x8B4D
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS                0x8B4C
+#define GL_MAX_TEXTURE_IMAGE_UNITS                       0x8872
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS                  0x8DFD
+#define GL_SHADER_TYPE                                   0x8B4F
+#define GL_DELETE_STATUS                                 0x8B80
+#define GL_LINK_STATUS                                   0x8B82
+#define GL_VALIDATE_STATUS                               0x8B83
+#define GL_ATTACHED_SHADERS                              0x8B85
+#define GL_ACTIVE_UNIFORMS                               0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH                     0x8B87
+#define GL_ACTIVE_ATTRIBUTES                             0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH                   0x8B8A
+#define GL_SHADING_LANGUAGE_VERSION                      0x8B8C
+#define GL_CURRENT_PROGRAM                               0x8B8D
+
+/* StencilFunction */
+#define GL_NEVER                                         0x0200
+#define GL_LESS                                          0x0201
+#define GL_EQUAL                                         0x0202
+#define GL_LEQUAL                                        0x0203
+#define GL_GREATER                                       0x0204
+#define GL_NOTEQUAL                                      0x0205
+#define GL_GEQUAL                                        0x0206
+#define GL_ALWAYS                                        0x0207
+
+/* StencilOp */
+/*      GL_ZERO */
+#define GL_KEEP                                          0x1E00
+#define GL_REPLACE                                       0x1E01
+#define GL_INCR                                          0x1E02
+#define GL_DECR                                          0x1E03
+#define GL_INVERT                                        0x150A
+#define GL_INCR_WRAP                                     0x8507
+#define GL_DECR_WRAP                                     0x8508
+
+/* StringName */
+#define GL_VENDOR                                        0x1F00
+#define GL_RENDERER                                      0x1F01
+#define GL_VERSION                                       0x1F02
+#define GL_EXTENSIONS                                    0x1F03
+
+/* TextureMagFilter */
+#define GL_NEAREST                                       0x2600
+#define GL_LINEAR                                        0x2601
+
+/* TextureMinFilter */
+/*      GL_NEAREST */
+/*      GL_LINEAR */
+#define GL_NEAREST_MIPMAP_NEAREST                        0x2700
+#define GL_LINEAR_MIPMAP_NEAREST                         0x2701
+#define GL_NEAREST_MIPMAP_LINEAR                         0x2702
+#define GL_LINEAR_MIPMAP_LINEAR                          0x2703
+
+/* TextureParameterName */
+#define GL_TEXTURE_MAG_FILTER                            0x2800
+#define GL_TEXTURE_MIN_FILTER                            0x2801
+#define GL_TEXTURE_WRAP_S                                0x2802
+#define GL_TEXTURE_WRAP_T                                0x2803
+
+/* TextureTarget */
+/*      GL_TEXTURE_2D */
+#define GL_TEXTURE                                       0x1702
+
+#define GL_TEXTURE_CUBE_MAP                              0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP                      0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X                   0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X                   0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y                   0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y                   0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z                   0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z                   0x851A
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE                     0x851C
+
+/* TextureUnit */
+#define GL_TEXTURE0                                      0x84C0
+#define GL_TEXTURE1                                      0x84C1
+#define GL_TEXTURE2                                      0x84C2
+#define GL_TEXTURE3                                      0x84C3
+#define GL_TEXTURE4                                      0x84C4
+#define GL_TEXTURE5                                      0x84C5
+#define GL_TEXTURE6                                      0x84C6
+#define GL_TEXTURE7                                      0x84C7
+#define GL_TEXTURE8                                      0x84C8
+#define GL_TEXTURE9                                      0x84C9
+#define GL_TEXTURE10                                     0x84CA
+#define GL_TEXTURE11                                     0x84CB
+#define GL_TEXTURE12                                     0x84CC
+#define GL_TEXTURE13                                     0x84CD
+#define GL_TEXTURE14                                     0x84CE
+#define GL_TEXTURE15                                     0x84CF
+#define GL_TEXTURE16                                     0x84D0
+#define GL_TEXTURE17                                     0x84D1
+#define GL_TEXTURE18                                     0x84D2
+#define GL_TEXTURE19                                     0x84D3
+#define GL_TEXTURE20                                     0x84D4
+#define GL_TEXTURE21                                     0x84D5
+#define GL_TEXTURE22                                     0x84D6
+#define GL_TEXTURE23                                     0x84D7
+#define GL_TEXTURE24                                     0x84D8
+#define GL_TEXTURE25                                     0x84D9
+#define GL_TEXTURE26                                     0x84DA
+#define GL_TEXTURE27                                     0x84DB
+#define GL_TEXTURE28                                     0x84DC
+#define GL_TEXTURE29                                     0x84DD
+#define GL_TEXTURE30                                     0x84DE
+#define GL_TEXTURE31                                     0x84DF
+#define GL_ACTIVE_TEXTURE                                0x84E0
+
+/* TextureWrapMode */
+#define GL_REPEAT                                        0x2901
+#define GL_CLAMP_TO_EDGE                                 0x812F
+#define GL_MIRRORED_REPEAT                               0x8370
+
+/* Uniform Types */
+#define GL_FLOAT_VEC2                                    0x8B50
+#define GL_FLOAT_VEC3                                    0x8B51
+#define GL_FLOAT_VEC4                                    0x8B52
+#define GL_INT_VEC2                                      0x8B53
+#define GL_INT_VEC3                                      0x8B54
+#define GL_INT_VEC4                                      0x8B55
+#define GL_BOOL                                          0x8B56
+#define GL_BOOL_VEC2                                     0x8B57
+#define GL_BOOL_VEC3                                     0x8B58
+#define GL_BOOL_VEC4                                     0x8B59
+#define GL_FLOAT_MAT2                                    0x8B5A
+#define GL_FLOAT_MAT3                                    0x8B5B
+#define GL_FLOAT_MAT4                                    0x8B5C
+#define GL_SAMPLER_2D                                    0x8B5E
+#define GL_SAMPLER_CUBE                                  0x8B60
+
+/* Vertex Arrays */
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED                   0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE                      0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE                    0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE                      0x8625
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED                0x886A
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER                   0x8645
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING            0x889F
+
+/* Read Format */
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE                0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT              0x8B9B
+
+/* Shader Source */
+#define GL_COMPILE_STATUS                                0x8B81
+#define GL_INFO_LOG_LENGTH                               0x8B84
+#define GL_SHADER_SOURCE_LENGTH                          0x8B88
+#define GL_SHADER_COMPILER                               0x8DFA
+
+/* Shader Binary */
+#define GL_SHADER_BINARY_FORMATS                         0x8DF8
+#define GL_NUM_SHADER_BINARY_FORMATS                     0x8DF9
+
+/* Shader Precision-Specified Types */
+#define GL_LOW_FLOAT                                     0x8DF0
+#define GL_MEDIUM_FLOAT                                  0x8DF1
+#define GL_HIGH_FLOAT                                    0x8DF2
+#define GL_LOW_INT                                       0x8DF3
+#define GL_MEDIUM_INT                                    0x8DF4
+#define GL_HIGH_INT                                      0x8DF5
+
+/* Framebuffer Object. */
+#define GL_FRAMEBUFFER                                   0x8D40
+#define GL_RENDERBUFFER                                  0x8D41
+
+#define GL_RGBA4                                         0x8056
+#define GL_RGB5_A1                                       0x8057
+#define GL_RGB565                                        0x8D62
+#define GL_DEPTH_COMPONENT16                             0x81A5
+#define GL_STENCIL_INDEX8                                0x8D48
+
+#define GL_RENDERBUFFER_WIDTH                            0x8D42
+#define GL_RENDERBUFFER_HEIGHT                           0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT                  0x8D44
+#define GL_RENDERBUFFER_RED_SIZE                         0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE                       0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE                        0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE                       0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE                       0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE                     0x8D55
+
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE            0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME            0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL          0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE  0x8CD3
+
+#define GL_COLOR_ATTACHMENT0                             0x8CE0
+#define GL_DEPTH_ATTACHMENT                              0x8D00
+#define GL_STENCIL_ATTACHMENT                            0x8D20
+
+#define GL_NONE                                          0
+
+#define GL_FRAMEBUFFER_COMPLETE                          0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT             0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT     0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS             0x8CD9
+#define GL_FRAMEBUFFER_UNSUPPORTED                       0x8CDD
+
+#define GL_FRAMEBUFFER_BINDING                           0x8CA6
+#define GL_RENDERBUFFER_BINDING                          0x8CA7
+#define GL_MAX_RENDERBUFFER_SIZE                         0x84E8
+
+#define GL_INVALID_FRAMEBUFFER_OPERATION                 0x0506
+
+/* OpenGL ES 3.0 */
+
+#define GL_READ_BUFFER                                   0x0C02
+#define GL_UNPACK_ROW_LENGTH                             0x0CF2
+#define GL_UNPACK_SKIP_ROWS                              0x0CF3
+#define GL_UNPACK_SKIP_PIXELS                            0x0CF4
+#define GL_PACK_ROW_LENGTH                               0x0D02
+#define GL_PACK_SKIP_ROWS                                0x0D03
+#define GL_PACK_SKIP_PIXELS                              0x0D04
+#define GL_COLOR                                         0x1800
+#define GL_DEPTH                                         0x1801
+#define GL_STENCIL                                       0x1802
+#define GL_RED                                           0x1903
+#define GL_RGB8                                          0x8051
+#define GL_RGBA8                                         0x8058
+#define GL_RGB10_A2                                      0x8059
+#define GL_TEXTURE_BINDING_3D                            0x806A
+#define GL_UNPACK_SKIP_IMAGES                            0x806D
+#define GL_UNPACK_IMAGE_HEIGHT                           0x806E
+#define GL_TEXTURE_3D                                    0x806F
+#define GL_TEXTURE_WRAP_R                                0x8072
+#define GL_MAX_3D_TEXTURE_SIZE                           0x8073
+#define GL_UNSIGNED_INT_2_10_10_10_REV                   0x8368
+#define GL_MAX_ELEMENTS_VERTICES                         0x80E8
+#define GL_MAX_ELEMENTS_INDICES                          0x80E9
+#define GL_TEXTURE_MIN_LOD                               0x813A
+#define GL_TEXTURE_MAX_LOD                               0x813B
+#define GL_TEXTURE_BASE_LEVEL                            0x813C
+#define GL_TEXTURE_MAX_LEVEL                             0x813D
+#define GL_MIN                                           0x8007
+#define GL_MAX                                           0x8008
+#define GL_DEPTH_COMPONENT24                             0x81A6
+#define GL_MAX_TEXTURE_LOD_BIAS                          0x84FD
+#define GL_TEXTURE_COMPARE_MODE                          0x884C
+#define GL_TEXTURE_COMPARE_FUNC                          0x884D
+#define GL_CURRENT_QUERY                                 0x8865
+#define GL_QUERY_RESULT                                  0x8866
+#define GL_QUERY_RESULT_AVAILABLE                        0x8867
+#define GL_BUFFER_MAPPED                                 0x88BC
+#define GL_BUFFER_MAP_POINTER                            0x88BD
+#define GL_STREAM_READ                                   0x88E1
+#define GL_STREAM_COPY                                   0x88E2
+#define GL_STATIC_READ                                   0x88E5
+#define GL_STATIC_COPY                                   0x88E6
+#define GL_DYNAMIC_READ                                  0x88E9
+#define GL_DYNAMIC_COPY                                  0x88EA
+#define GL_MAX_DRAW_BUFFERS                              0x8824
+#define GL_DRAW_BUFFER0                                  0x8825
+#define GL_DRAW_BUFFER1                                  0x8826
+#define GL_DRAW_BUFFER2                                  0x8827
+#define GL_DRAW_BUFFER3                                  0x8828
+#define GL_DRAW_BUFFER4                                  0x8829
+#define GL_DRAW_BUFFER5                                  0x882A
+#define GL_DRAW_BUFFER6                                  0x882B
+#define GL_DRAW_BUFFER7                                  0x882C
+#define GL_DRAW_BUFFER8                                  0x882D
+#define GL_DRAW_BUFFER9                                  0x882E
+#define GL_DRAW_BUFFER10                                 0x882F
+#define GL_DRAW_BUFFER11                                 0x8830
+#define GL_DRAW_BUFFER12                                 0x8831
+#define GL_DRAW_BUFFER13                                 0x8832
+#define GL_DRAW_BUFFER14                                 0x8833
+#define GL_DRAW_BUFFER15                                 0x8834
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS               0x8B49
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS                 0x8B4A
+#define GL_SAMPLER_3D                                    0x8B5F
+#define GL_SAMPLER_2D_SHADOW                             0x8B62
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT               0x8B8B
+#define GL_PIXEL_PACK_BUFFER                             0x88EB
+#define GL_PIXEL_UNPACK_BUFFER                           0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING                     0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING                   0x88EF
+#define GL_FLOAT_MAT2x3                                  0x8B65
+#define GL_FLOAT_MAT2x4                                  0x8B66
+#define GL_FLOAT_MAT3x2                                  0x8B67
+#define GL_FLOAT_MAT3x4                                  0x8B68
+#define GL_FLOAT_MAT4x2                                  0x8B69
+#define GL_FLOAT_MAT4x3                                  0x8B6A
+#define GL_SRGB                                          0x8C40
+#define GL_SRGB8                                         0x8C41
+#define GL_SRGB8_ALPHA8                                  0x8C43
+#define GL_COMPARE_REF_TO_TEXTURE                        0x884E
+#define GL_MAJOR_VERSION                                 0x821B
+#define GL_MINOR_VERSION                                 0x821C
+#define GL_NUM_EXTENSIONS                                0x821D
+#define GL_RGBA32F                                       0x8814
+#define GL_RGB32F                                        0x8815
+#define GL_RGBA16F                                       0x881A
+#define GL_RGB16F                                        0x881B
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER                   0x88FD
+#define GL_MAX_ARRAY_TEXTURE_LAYERS                      0x88FF
+#define GL_MIN_PROGRAM_TEXEL_OFFSET                      0x8904
+#define GL_MAX_PROGRAM_TEXEL_OFFSET                      0x8905
+#define GL_MAX_VARYING_COMPONENTS                        0x8B4B
+#define GL_TEXTURE_2D_ARRAY                              0x8C1A
+#define GL_TEXTURE_BINDING_2D_ARRAY                      0x8C1D
+#define GL_R11F_G11F_B10F                                0x8C3A
+#define GL_UNSIGNED_INT_10F_11F_11F_REV                  0x8C3B
+#define GL_RGB9_E5                                       0x8C3D
+#define GL_UNSIGNED_INT_5_9_9_9_REV                      0x8C3E
+#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH         0x8C76
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE                0x8C7F
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS    0x8C80
+#define GL_TRANSFORM_FEEDBACK_VARYINGS                   0x8C83
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START               0x8C84
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE                0x8C85
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN         0x8C88
+#define GL_RASTERIZER_DISCARD                            0x8C89
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS       0x8C8B
+#define GL_INTERLEAVED_ATTRIBS                           0x8C8C
+#define GL_SEPARATE_ATTRIBS                              0x8C8D
+#define GL_TRANSFORM_FEEDBACK_BUFFER                     0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING             0x8C8F
+#define GL_RGBA32UI                                      0x8D70
+#define GL_RGB32UI                                       0x8D71
+#define GL_RGBA16UI                                      0x8D76
+#define GL_RGB16UI                                       0x8D77
+#define GL_RGBA8UI                                       0x8D7C
+#define GL_RGB8UI                                        0x8D7D
+#define GL_RGBA32I                                       0x8D82
+#define GL_RGB32I                                        0x8D83
+#define GL_RGBA16I                                       0x8D88
+#define GL_RGB16I                                        0x8D89
+#define GL_RGBA8I                                        0x8D8E
+#define GL_RGB8I                                         0x8D8F
+#define GL_RED_INTEGER                                   0x8D94
+#define GL_RGB_INTEGER                                   0x8D98
+#define GL_RGBA_INTEGER                                  0x8D99
+#define GL_SAMPLER_2D_ARRAY                              0x8DC1
+#define GL_SAMPLER_2D_ARRAY_SHADOW                       0x8DC4
+#define GL_SAMPLER_CUBE_SHADOW                           0x8DC5
+#define GL_UNSIGNED_INT_VEC2                             0x8DC6
+#define GL_UNSIGNED_INT_VEC3                             0x8DC7
+#define GL_UNSIGNED_INT_VEC4                             0x8DC8
+#define GL_INT_SAMPLER_2D                                0x8DCA
+#define GL_INT_SAMPLER_3D                                0x8DCB
+#define GL_INT_SAMPLER_CUBE                              0x8DCC
+#define GL_INT_SAMPLER_2D_ARRAY                          0x8DCF
+#define GL_UNSIGNED_INT_SAMPLER_2D                       0x8DD2
+#define GL_UNSIGNED_INT_SAMPLER_3D                       0x8DD3
+#define GL_UNSIGNED_INT_SAMPLER_CUBE                     0x8DD4
+#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY                 0x8DD7
+#define GL_BUFFER_ACCESS_FLAGS                           0x911F
+#define GL_BUFFER_MAP_LENGTH                             0x9120
+#define GL_BUFFER_MAP_OFFSET                             0x9121
+#define GL_DEPTH_COMPONENT32F                            0x8CAC
+#define GL_DEPTH32F_STENCIL8                             0x8CAD
+#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV                0x8DAD
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING         0x8210
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE         0x8211
+#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE               0x8212
+#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE             0x8213
+#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE              0x8214
+#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE             0x8215
+#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE             0x8216
+#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE           0x8217
+#define GL_FRAMEBUFFER_DEFAULT                           0x8218
+#define GL_FRAMEBUFFER_UNDEFINED                         0x8219
+#define GL_DEPTH_STENCIL_ATTACHMENT                      0x821A
+#define GL_DEPTH_STENCIL                                 0x84F9
+#define GL_UNSIGNED_INT_24_8                             0x84FA
+#define GL_DEPTH24_STENCIL8                              0x88F0
+#define GL_UNSIGNED_NORMALIZED                           0x8C17
+#define GL_DRAW_FRAMEBUFFER_BINDING                      GL_FRAMEBUFFER_BINDING
+#define GL_READ_FRAMEBUFFER                              0x8CA8
+#define GL_DRAW_FRAMEBUFFER                              0x8CA9
+#define GL_READ_FRAMEBUFFER_BINDING                      0x8CAA
+#define GL_RENDERBUFFER_SAMPLES                          0x8CAB
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER          0x8CD4
+#define GL_MAX_COLOR_ATTACHMENTS                         0x8CDF
+#define GL_COLOR_ATTACHMENT1                             0x8CE1
+#define GL_COLOR_ATTACHMENT2                             0x8CE2
+#define GL_COLOR_ATTACHMENT3                             0x8CE3
+#define GL_COLOR_ATTACHMENT4                             0x8CE4
+#define GL_COLOR_ATTACHMENT5                             0x8CE5
+#define GL_COLOR_ATTACHMENT6                             0x8CE6
+#define GL_COLOR_ATTACHMENT7                             0x8CE7
+#define GL_COLOR_ATTACHMENT8                             0x8CE8
+#define GL_COLOR_ATTACHMENT9                             0x8CE9
+#define GL_COLOR_ATTACHMENT10                            0x8CEA
+#define GL_COLOR_ATTACHMENT11                            0x8CEB
+#define GL_COLOR_ATTACHMENT12                            0x8CEC
+#define GL_COLOR_ATTACHMENT13                            0x8CED
+#define GL_COLOR_ATTACHMENT14                            0x8CEE
+#define GL_COLOR_ATTACHMENT15                            0x8CEF
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE            0x8D56
+#define GL_MAX_SAMPLES                                   0x8D57
+#define GL_HALF_FLOAT                                    0x140B
+#define GL_MAP_READ_BIT                                  0x0001
+#define GL_MAP_WRITE_BIT                                 0x0002
+#define GL_MAP_INVALIDATE_RANGE_BIT                      0x0004
+#define GL_MAP_INVALIDATE_BUFFER_BIT                     0x0008
+#define GL_MAP_FLUSH_EXPLICIT_BIT                        0x0010
+#define GL_MAP_UNSYNCHRONIZED_BIT                        0x0020
+#define GL_RG                                            0x8227
+#define GL_RG_INTEGER                                    0x8228
+#define GL_R8                                            0x8229
+#define GL_RG8                                           0x822B
+#define GL_R16F                                          0x822D
+#define GL_R32F                                          0x822E
+#define GL_RG16F                                         0x822F
+#define GL_RG32F                                         0x8230
+#define GL_R8I                                           0x8231
+#define GL_R8UI                                          0x8232
+#define GL_R16I                                          0x8233
+#define GL_R16UI                                         0x8234
+#define GL_R32I                                          0x8235
+#define GL_R32UI                                         0x8236
+#define GL_RG8I                                          0x8237
+#define GL_RG8UI                                         0x8238
+#define GL_RG16I                                         0x8239
+#define GL_RG16UI                                        0x823A
+#define GL_RG32I                                         0x823B
+#define GL_RG32UI                                        0x823C
+#define GL_VERTEX_ARRAY_BINDING                          0x85B5
+#define GL_R8_SNORM                                      0x8F94
+#define GL_RG8_SNORM                                     0x8F95
+#define GL_RGB8_SNORM                                    0x8F96
+#define GL_RGBA8_SNORM                                   0x8F97
+#define GL_SIGNED_NORMALIZED                             0x8F9C
+#define GL_PRIMITIVE_RESTART_FIXED_INDEX                 0x8D69
+#define GL_COPY_READ_BUFFER                              0x8F36
+#define GL_COPY_WRITE_BUFFER                             0x8F37
+#define GL_COPY_READ_BUFFER_BINDING                      GL_COPY_READ_BUFFER
+#define GL_COPY_WRITE_BUFFER_BINDING                     GL_COPY_WRITE_BUFFER
+#define GL_UNIFORM_BUFFER                                0x8A11
+#define GL_UNIFORM_BUFFER_BINDING                        0x8A28
+#define GL_UNIFORM_BUFFER_START                          0x8A29
+#define GL_UNIFORM_BUFFER_SIZE                           0x8A2A
+#define GL_MAX_VERTEX_UNIFORM_BLOCKS                     0x8A2B
+#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS                   0x8A2D
+#define GL_MAX_COMBINED_UNIFORM_BLOCKS                   0x8A2E
+#define GL_MAX_UNIFORM_BUFFER_BINDINGS                   0x8A2F
+#define GL_MAX_UNIFORM_BLOCK_SIZE                        0x8A30
+#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS        0x8A31
+#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS      0x8A33
+#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT               0x8A34
+#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH          0x8A35
+#define GL_ACTIVE_UNIFORM_BLOCKS                         0x8A36
+#define GL_UNIFORM_TYPE                                  0x8A37
+#define GL_UNIFORM_SIZE                                  0x8A38
+#define GL_UNIFORM_NAME_LENGTH                           0x8A39
+#define GL_UNIFORM_BLOCK_INDEX                           0x8A3A
+#define GL_UNIFORM_OFFSET                                0x8A3B
+#define GL_UNIFORM_ARRAY_STRIDE                          0x8A3C
+#define GL_UNIFORM_MATRIX_STRIDE                         0x8A3D
+#define GL_UNIFORM_IS_ROW_MAJOR                          0x8A3E
+#define GL_UNIFORM_BLOCK_BINDING                         0x8A3F
+#define GL_UNIFORM_BLOCK_DATA_SIZE                       0x8A40
+#define GL_UNIFORM_BLOCK_NAME_LENGTH                     0x8A41
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS                 0x8A42
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES          0x8A43
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER     0x8A44
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER   0x8A46
+#define GL_INVALID_INDEX                                 0xFFFFFFFFu
+#define GL_MAX_VERTEX_OUTPUT_COMPONENTS                  0x9122
+#define GL_MAX_FRAGMENT_INPUT_COMPONENTS                 0x9125
+#define GL_MAX_SERVER_WAIT_TIMEOUT                       0x9111
+#define GL_OBJECT_TYPE                                   0x9112
+#define GL_SYNC_CONDITION                                0x9113
+#define GL_SYNC_STATUS                                   0x9114
+#define GL_SYNC_FLAGS                                    0x9115
+#define GL_SYNC_FENCE                                    0x9116
+#define GL_SYNC_GPU_COMMANDS_COMPLETE                    0x9117
+#define GL_UNSIGNALED                                    0x9118
+#define GL_SIGNALED                                      0x9119
+#define GL_ALREADY_SIGNALED                              0x911A
+#define GL_TIMEOUT_EXPIRED                               0x911B
+#define GL_CONDITION_SATISFIED                           0x911C
+#define GL_WAIT_FAILED                                   0x911D
+#define GL_SYNC_FLUSH_COMMANDS_BIT                       0x00000001
+#define GL_TIMEOUT_IGNORED                               0xFFFFFFFFFFFFFFFFull
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR                   0x88FE
+#define GL_ANY_SAMPLES_PASSED                            0x8C2F
+#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE               0x8D6A
+#define GL_SAMPLER_BINDING                               0x8919
+#define GL_RGB10_A2UI                                    0x906F
+#define GL_TEXTURE_SWIZZLE_R                             0x8E42
+#define GL_TEXTURE_SWIZZLE_G                             0x8E43
+#define GL_TEXTURE_SWIZZLE_B                             0x8E44
+#define GL_TEXTURE_SWIZZLE_A                             0x8E45
+#define GL_GREEN                                         0x1904
+#define GL_BLUE                                          0x1905
+#define GL_INT_2_10_10_10_REV                            0x8D9F
+#define GL_TRANSFORM_FEEDBACK                            0x8E22
+#define GL_TRANSFORM_FEEDBACK_PAUSED                     0x8E23
+#define GL_TRANSFORM_FEEDBACK_ACTIVE                     0x8E24
+#define GL_TRANSFORM_FEEDBACK_BINDING                    0x8E25
+#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT               0x8257
+#define GL_PROGRAM_BINARY_LENGTH                         0x8741
+#define GL_NUM_PROGRAM_BINARY_FORMATS                    0x87FE
+#define GL_PROGRAM_BINARY_FORMATS                        0x87FF
+#define GL_COMPRESSED_R11_EAC                            0x9270
+#define GL_COMPRESSED_SIGNED_R11_EAC                     0x9271
+#define GL_COMPRESSED_RG11_EAC                           0x9272
+#define GL_COMPRESSED_SIGNED_RG11_EAC                    0x9273
+#define GL_COMPRESSED_RGB8_ETC2                          0x9274
+#define GL_COMPRESSED_SRGB8_ETC2                         0x9275
+#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2      0x9276
+#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2     0x9277
+#define GL_COMPRESSED_RGBA8_ETC2_EAC                     0x9278
+#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC              0x9279
+#define GL_TEXTURE_IMMUTABLE_FORMAT                      0x912F
+#define GL_MAX_ELEMENT_INDEX                             0x8D6B
+#define GL_NUM_SAMPLE_COUNTS                             0x9380
+#define GL_TEXTURE_IMMUTABLE_LEVELS                      0x82DF
+
+/*-------------------------------------------------------------------------
+ * Entrypoint definitions
+ *-----------------------------------------------------------------------*/
+
+/* OpenGL ES 2.0 */
+
+GL_APICALL void           GL_APIENTRY glActiveTexture (GLenum texture);
+GL_APICALL void           GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
+GL_APICALL void           GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar* name);
+GL_APICALL void           GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);
+GL_APICALL void           GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
+GL_APICALL void           GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
+GL_APICALL void           GL_APIENTRY glBindTexture (GLenum target, GLuint texture);
+GL_APICALL void           GL_APIENTRY glBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GL_APICALL void           GL_APIENTRY glBlendEquation (GLenum mode);
+GL_APICALL void           GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
+GL_APICALL void           GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
+GL_APICALL void           GL_APIENTRY glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+GL_APICALL void           GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
+GL_APICALL void           GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
+GL_APICALL GLenum         GL_APIENTRY glCheckFramebufferStatus (GLenum target);
+GL_APICALL void           GL_APIENTRY glClear (GLbitfield mask);
+GL_APICALL void           GL_APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GL_APICALL void           GL_APIENTRY glClearDepthf (GLfloat depth);
+GL_APICALL void           GL_APIENTRY glClearStencil (GLint s);
+GL_APICALL void           GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+GL_APICALL void           GL_APIENTRY glCompileShader (GLuint shader);
+GL_APICALL void           GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void           GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void           GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GL_APICALL void           GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL GLuint         GL_APIENTRY glCreateProgram (void);
+GL_APICALL GLuint         GL_APIENTRY glCreateShader (GLenum type);
+GL_APICALL void           GL_APIENTRY glCullFace (GLenum mode);
+GL_APICALL void           GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint* buffers);
+GL_APICALL void           GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers);
+GL_APICALL void           GL_APIENTRY glDeleteProgram (GLuint program);
+GL_APICALL void           GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint* renderbuffers);
+GL_APICALL void           GL_APIENTRY glDeleteShader (GLuint shader);
+GL_APICALL void           GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint* textures);
+GL_APICALL void           GL_APIENTRY glDepthFunc (GLenum func);
+GL_APICALL void           GL_APIENTRY glDepthMask (GLboolean flag);
+GL_APICALL void           GL_APIENTRY glDepthRangef (GLfloat n, GLfloat f);
+GL_APICALL void           GL_APIENTRY glDetachShader (GLuint program, GLuint shader);
+GL_APICALL void           GL_APIENTRY glDisable (GLenum cap);
+GL_APICALL void           GL_APIENTRY glDisableVertexAttribArray (GLuint index);
+GL_APICALL void           GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
+GL_APICALL void           GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices);
+GL_APICALL void           GL_APIENTRY glEnable (GLenum cap);
+GL_APICALL void           GL_APIENTRY glEnableVertexAttribArray (GLuint index);
+GL_APICALL void           GL_APIENTRY glFinish (void);
+GL_APICALL void           GL_APIENTRY glFlush (void);
+GL_APICALL void           GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GL_APICALL void           GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GL_APICALL void           GL_APIENTRY glFrontFace (GLenum mode);
+GL_APICALL void           GL_APIENTRY glGenBuffers (GLsizei n, GLuint* buffers);
+GL_APICALL void           GL_APIENTRY glGenerateMipmap (GLenum target);
+GL_APICALL void           GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint* framebuffers);
+GL_APICALL void           GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint* renderbuffers);
+GL_APICALL void           GL_APIENTRY glGenTextures (GLsizei n, GLuint* textures);
+GL_APICALL void           GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+GL_APICALL void           GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+GL_APICALL void           GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
+GL_APICALL GLint          GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar* name);
+GL_APICALL void           GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean* params);
+GL_APICALL void           GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL GLenum         GL_APIENTRY glGetError (void);
+GL_APICALL void           GL_APIENTRY glGetFloatv (GLenum pname, GLfloat* params);
+GL_APICALL void           GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params);
+GL_APICALL void           GL_APIENTRY glGetIntegerv (GLenum pname, GLint* params);
+GL_APICALL void           GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint* params);
+GL_APICALL void           GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog);
+GL_APICALL void           GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL void           GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint* params);
+GL_APICALL void           GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog);
+GL_APICALL void           GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
+GL_APICALL void           GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source);
+GL_APICALL const GLubyte* GL_APIENTRY glGetString (GLenum name);
+GL_APICALL void           GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat* params);
+GL_APICALL void           GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL void           GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat* params);
+GL_APICALL void           GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint* params);
+GL_APICALL GLint          GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar* name);
+GL_APICALL void           GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params);
+GL_APICALL void           GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint* params);
+GL_APICALL void           GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, GLvoid** pointer);
+GL_APICALL void           GL_APIENTRY glHint (GLenum target, GLenum mode);
+GL_APICALL GLboolean      GL_APIENTRY glIsBuffer (GLuint buffer);
+GL_APICALL GLboolean      GL_APIENTRY glIsEnabled (GLenum cap);
+GL_APICALL GLboolean      GL_APIENTRY glIsFramebuffer (GLuint framebuffer);
+GL_APICALL GLboolean      GL_APIENTRY glIsProgram (GLuint program);
+GL_APICALL GLboolean      GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer);
+GL_APICALL GLboolean      GL_APIENTRY glIsShader (GLuint shader);
+GL_APICALL GLboolean      GL_APIENTRY glIsTexture (GLuint texture);
+GL_APICALL void           GL_APIENTRY glLineWidth (GLfloat width);
+GL_APICALL void           GL_APIENTRY glLinkProgram (GLuint program);
+GL_APICALL void           GL_APIENTRY glPixelStorei (GLenum pname, GLint param);
+GL_APICALL void           GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
+GL_APICALL void           GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);
+GL_APICALL void           GL_APIENTRY glReleaseShaderCompiler (void);
+GL_APICALL void           GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void           GL_APIENTRY glSampleCoverage (GLfloat value, GLboolean invert);
+GL_APICALL void           GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void           GL_APIENTRY glShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length);
+GL_APICALL void           GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length);
+GL_APICALL void           GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
+GL_APICALL void           GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
+GL_APICALL void           GL_APIENTRY glStencilMask (GLuint mask);
+GL_APICALL void           GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
+GL_APICALL void           GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void           GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void           GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void           GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
+GL_APICALL void           GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat* params);
+GL_APICALL void           GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
+GL_APICALL void           GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint* params);
+GL_APICALL void           GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void           GL_APIENTRY glUniform1f (GLint location, GLfloat x);
+GL_APICALL void           GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void           GL_APIENTRY glUniform1i (GLint location, GLint x);
+GL_APICALL void           GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void           GL_APIENTRY glUniform2f (GLint location, GLfloat x, GLfloat y);
+GL_APICALL void           GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void           GL_APIENTRY glUniform2i (GLint location, GLint x, GLint y);
+GL_APICALL void           GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void           GL_APIENTRY glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void           GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void           GL_APIENTRY glUniform3i (GLint location, GLint x, GLint y, GLint z);
+GL_APICALL void           GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void           GL_APIENTRY glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void           GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void           GL_APIENTRY glUniform4i (GLint location, GLint x, GLint y, GLint z, GLint w);
+GL_APICALL void           GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void           GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void           GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void           GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void           GL_APIENTRY glUseProgram (GLuint program);
+GL_APICALL void           GL_APIENTRY glValidateProgram (GLuint program);
+GL_APICALL void           GL_APIENTRY glVertexAttrib1f (GLuint indx, GLfloat x);
+GL_APICALL void           GL_APIENTRY glVertexAttrib1fv (GLuint indx, const GLfloat* values);
+GL_APICALL void           GL_APIENTRY glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y);
+GL_APICALL void           GL_APIENTRY glVertexAttrib2fv (GLuint indx, const GLfloat* values);
+GL_APICALL void           GL_APIENTRY glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void           GL_APIENTRY glVertexAttrib3fv (GLuint indx, const GLfloat* values);
+GL_APICALL void           GL_APIENTRY glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void           GL_APIENTRY glVertexAttrib4fv (GLuint indx, const GLfloat* values);
+GL_APICALL void           GL_APIENTRY glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr);
+GL_APICALL void           GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+
+/* OpenGL ES 3.0 */
+
+GL_APICALL void           GL_APIENTRY glReadBuffer (GLenum mode);
+GL_APICALL void           GL_APIENTRY glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices);
+GL_APICALL void           GL_APIENTRY glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void           GL_APIENTRY glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void           GL_APIENTRY glCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void           GL_APIENTRY glCompressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void           GL_APIENTRY glCompressedTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void           GL_APIENTRY glGenQueries (GLsizei n, GLuint* ids);
+GL_APICALL void           GL_APIENTRY glDeleteQueries (GLsizei n, const GLuint* ids);
+GL_APICALL GLboolean      GL_APIENTRY glIsQuery (GLuint id);
+GL_APICALL void           GL_APIENTRY glBeginQuery (GLenum target, GLuint id);
+GL_APICALL void           GL_APIENTRY glEndQuery (GLenum target);
+GL_APICALL void           GL_APIENTRY glGetQueryiv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL void           GL_APIENTRY glGetQueryObjectuiv (GLuint id, GLenum pname, GLuint* params);
+GL_APICALL GLboolean      GL_APIENTRY glUnmapBuffer (GLenum target);
+GL_APICALL void           GL_APIENTRY glGetBufferPointerv (GLenum target, GLenum pname, GLvoid** params);
+GL_APICALL void           GL_APIENTRY glDrawBuffers (GLsizei n, const GLenum* bufs);
+GL_APICALL void           GL_APIENTRY glUniformMatrix2x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void           GL_APIENTRY glUniformMatrix3x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void           GL_APIENTRY glUniformMatrix2x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void           GL_APIENTRY glUniformMatrix4x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void           GL_APIENTRY glUniformMatrix3x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void           GL_APIENTRY glUniformMatrix4x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void           GL_APIENTRY glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+GL_APICALL void           GL_APIENTRY glRenderbufferStorageMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void           GL_APIENTRY glFramebufferTextureLayer (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+GL_APICALL GLvoid*        GL_APIENTRY glMapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+GL_APICALL void           GL_APIENTRY glFlushMappedBufferRange (GLenum target, GLintptr offset, GLsizeiptr length);
+GL_APICALL void           GL_APIENTRY glBindVertexArray (GLuint array);
+GL_APICALL void           GL_APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint* arrays);
+GL_APICALL void           GL_APIENTRY glGenVertexArrays (GLsizei n, GLuint* arrays);
+GL_APICALL GLboolean      GL_APIENTRY glIsVertexArray (GLuint array);
+GL_APICALL void           GL_APIENTRY glGetIntegeri_v (GLenum target, GLuint index, GLint* data);
+GL_APICALL void           GL_APIENTRY glBeginTransformFeedback (GLenum primitiveMode);
+GL_APICALL void           GL_APIENTRY glEndTransformFeedback (void);
+GL_APICALL void           GL_APIENTRY glBindBufferRange (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GL_APICALL void           GL_APIENTRY glBindBufferBase (GLenum target, GLuint index, GLuint buffer);
+GL_APICALL void           GL_APIENTRY glTransformFeedbackVaryings (GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode);
+GL_APICALL void           GL_APIENTRY glGetTransformFeedbackVarying (GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name);
+GL_APICALL void           GL_APIENTRY glVertexAttribIPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer);
+GL_APICALL void           GL_APIENTRY glGetVertexAttribIiv (GLuint index, GLenum pname, GLint* params);
+GL_APICALL void           GL_APIENTRY glGetVertexAttribIuiv (GLuint index, GLenum pname, GLuint* params);
+GL_APICALL void           GL_APIENTRY glVertexAttribI4i (GLuint index, GLint x, GLint y, GLint z, GLint w);
+GL_APICALL void           GL_APIENTRY glVertexAttribI4ui (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+GL_APICALL void           GL_APIENTRY glVertexAttribI4iv (GLuint index, const GLint* v);
+GL_APICALL void           GL_APIENTRY glVertexAttribI4uiv (GLuint index, const GLuint* v);
+GL_APICALL void           GL_APIENTRY glGetUniformuiv (GLuint program, GLint location, GLuint* params);
+GL_APICALL GLint          GL_APIENTRY glGetFragDataLocation (GLuint program, const GLchar *name);
+GL_APICALL void           GL_APIENTRY glUniform1ui (GLint location, GLuint v0);
+GL_APICALL void           GL_APIENTRY glUniform2ui (GLint location, GLuint v0, GLuint v1);
+GL_APICALL void           GL_APIENTRY glUniform3ui (GLint location, GLuint v0, GLuint v1, GLuint v2);
+GL_APICALL void           GL_APIENTRY glUniform4ui (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GL_APICALL void           GL_APIENTRY glUniform1uiv (GLint location, GLsizei count, const GLuint* value);
+GL_APICALL void           GL_APIENTRY glUniform2uiv (GLint location, GLsizei count, const GLuint* value);
+GL_APICALL void           GL_APIENTRY glUniform3uiv (GLint location, GLsizei count, const GLuint* value);
+GL_APICALL void           GL_APIENTRY glUniform4uiv (GLint location, GLsizei count, const GLuint* value);
+GL_APICALL void           GL_APIENTRY glClearBufferiv (GLenum buffer, GLint drawbuffer, const GLint* value);
+GL_APICALL void           GL_APIENTRY glClearBufferuiv (GLenum buffer, GLint drawbuffer, const GLuint* value);
+GL_APICALL void           GL_APIENTRY glClearBufferfv (GLenum buffer, GLint drawbuffer, const GLfloat* value);
+GL_APICALL void           GL_APIENTRY glClearBufferfi (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+GL_APICALL const GLubyte* GL_APIENTRY glGetStringi (GLenum name, GLuint index);
+GL_APICALL void           GL_APIENTRY glCopyBufferSubData (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+GL_APICALL void           GL_APIENTRY glGetUniformIndices (GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices);
+GL_APICALL void           GL_APIENTRY glGetActiveUniformsiv (GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params);
+GL_APICALL GLuint         GL_APIENTRY glGetUniformBlockIndex (GLuint program, const GLchar* uniformBlockName);
+GL_APICALL void           GL_APIENTRY glGetActiveUniformBlockiv (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params);
+GL_APICALL void           GL_APIENTRY glGetActiveUniformBlockName (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName);
+GL_APICALL void           GL_APIENTRY glUniformBlockBinding (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+GL_APICALL void           GL_APIENTRY glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count, GLsizei instanceCount);
+GL_APICALL void           GL_APIENTRY glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount);
+GL_APICALL GLsync         GL_APIENTRY glFenceSync (GLenum condition, GLbitfield flags);
+GL_APICALL GLboolean      GL_APIENTRY glIsSync (GLsync sync);
+GL_APICALL void           GL_APIENTRY glDeleteSync (GLsync sync);
+GL_APICALL GLenum         GL_APIENTRY glClientWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GL_APICALL void           GL_APIENTRY glWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GL_APICALL void           GL_APIENTRY glGetInteger64v (GLenum pname, GLint64* params);
+GL_APICALL void           GL_APIENTRY glGetSynciv (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values);
+GL_APICALL void           GL_APIENTRY glGetInteger64i_v (GLenum target, GLuint index, GLint64* data);
+GL_APICALL void           GL_APIENTRY glGetBufferParameteri64v (GLenum target, GLenum pname, GLint64* params);
+GL_APICALL void           GL_APIENTRY glGenSamplers (GLsizei count, GLuint* samplers);
+GL_APICALL void           GL_APIENTRY glDeleteSamplers (GLsizei count, const GLuint* samplers);
+GL_APICALL GLboolean      GL_APIENTRY glIsSampler (GLuint sampler);
+GL_APICALL void           GL_APIENTRY glBindSampler (GLuint unit, GLuint sampler);
+GL_APICALL void           GL_APIENTRY glSamplerParameteri (GLuint sampler, GLenum pname, GLint param);
+GL_APICALL void           GL_APIENTRY glSamplerParameteriv (GLuint sampler, GLenum pname, const GLint* param);
+GL_APICALL void           GL_APIENTRY glSamplerParameterf (GLuint sampler, GLenum pname, GLfloat param);
+GL_APICALL void           GL_APIENTRY glSamplerParameterfv (GLuint sampler, GLenum pname, const GLfloat* param);
+GL_APICALL void           GL_APIENTRY glGetSamplerParameteriv (GLuint sampler, GLenum pname, GLint* params);
+GL_APICALL void           GL_APIENTRY glGetSamplerParameterfv (GLuint sampler, GLenum pname, GLfloat* params);
+GL_APICALL void           GL_APIENTRY glVertexAttribDivisor (GLuint index, GLuint divisor);
+GL_APICALL void           GL_APIENTRY glBindTransformFeedback (GLenum target, GLuint id);
+GL_APICALL void           GL_APIENTRY glDeleteTransformFeedbacks (GLsizei n, const GLuint* ids);
+GL_APICALL void           GL_APIENTRY glGenTransformFeedbacks (GLsizei n, GLuint* ids);
+GL_APICALL GLboolean      GL_APIENTRY glIsTransformFeedback (GLuint id);
+GL_APICALL void           GL_APIENTRY glPauseTransformFeedback (void);
+GL_APICALL void           GL_APIENTRY glResumeTransformFeedback (void);
+GL_APICALL void           GL_APIENTRY glGetProgramBinary (GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary);
+GL_APICALL void           GL_APIENTRY glProgramBinary (GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length);
+GL_APICALL void           GL_APIENTRY glProgramParameteri (GLuint program, GLenum pname, GLint value);
+GL_APICALL void           GL_APIENTRY glInvalidateFramebuffer (GLenum target, GLsizei numAttachments, const GLenum* attachments);
+GL_APICALL void           GL_APIENTRY glInvalidateSubFramebuffer (GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void           GL_APIENTRY glTexStorage2D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void           GL_APIENTRY glTexStorage3D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+GL_APICALL void           GL_APIENTRY glGetInternalformativ (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ndk/platforms/android-18/include/GLES3/gl3ext.h b/ndk/platforms/android-18/include/GLES3/gl3ext.h
new file mode 100644
index 0000000..4d4ea96
--- /dev/null
+++ b/ndk/platforms/android-18/include/GLES3/gl3ext.h
@@ -0,0 +1,24 @@
+#ifndef __gl3ext_h_
+#define __gl3ext_h_
+
+/* $Revision: 17809 $ on $Date:: 2012-05-14 08:03:36 -0700 #$ */
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+/* OpenGL ES 3 Extensions
+ *
+ * After an OES extension's interactions with OpenGl ES 3.0 have been documented,
+ * its tokens and function definitions should be added to this file in a manner
+ * that does not conflict with gl2ext.h or gl3.h.
+ *
+ * Tokens and function definitions for extensions that have become standard
+ * features in OpenGL ES 3.0 will not be added to this file.
+ *
+ * Applications using OpenGL-ES-2-only extensions should include gl2ext.h
+ */
+
+#endif /* __gl3ext_h_ */
+
diff --git a/ndk/platforms/android-18/include/GLES3/gl3platform.h b/ndk/platforms/android-18/include/GLES3/gl3platform.h
new file mode 100644
index 0000000..1bd1a85
--- /dev/null
+++ b/ndk/platforms/android-18/include/GLES3/gl3platform.h
@@ -0,0 +1,30 @@
+#ifndef __gl3platform_h_
+#define __gl3platform_h_
+
+/* $Revision: 18437 $ on $Date:: 2012-07-08 23:31:39 -0700 #$ */
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+/* Platform-specific types and definitions for OpenGL ES 3.X  gl3.h
+ *
+ * Adopters may modify khrplatform.h and this file to suit their platform.
+ * You are encouraged to submit all modifications to the Khronos group so that
+ * they can be included in future versions of this file.  Please submit changes
+ * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla)
+ * by filing a bug against product "OpenGL-ES" component "Registry".
+ */
+
+#include <KHR/khrplatform.h>
+
+#ifndef GL_APICALL
+#define GL_APICALL  KHRONOS_APICALL
+#endif
+
+#ifndef GL_APIENTRY
+#define GL_APIENTRY KHRONOS_APIENTRY
+#endif
+
+#endif /* __gl3platform_h_ */
diff --git a/ndk/platforms/android-18/samples/gles3jni/AndroidManifest-11.xml b/ndk/platforms/android-18/samples/gles3jni/AndroidManifest-11.xml
new file mode 100644
index 0000000..9213c58
--- /dev/null
+++ b/ndk/platforms/android-18/samples/gles3jni/AndroidManifest-11.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.gles3jni">
+    <application
+            android:label="@string/gles3jni_activity">
+        <activity android:name="GLES3JNIActivity"
+                android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
+                android:launchMode="singleTask"
+                android:configChanges="orientation|keyboardHidden">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+    <uses-feature android:glEsVersion="0x00020000"/>
+    <uses-sdk android:minSdkVersion="11"/>
+</manifest>
diff --git a/ndk/platforms/android-18/samples/gles3jni/AndroidManifest-18.xml b/ndk/platforms/android-18/samples/gles3jni/AndroidManifest-18.xml
new file mode 100644
index 0000000..7eea32f
--- /dev/null
+++ b/ndk/platforms/android-18/samples/gles3jni/AndroidManifest-18.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.gles3jni">
+    <application
+            android:label="@string/gles3jni_activity">
+        <activity android:name="GLES3JNIActivity"
+                android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
+                android:launchMode="singleTask"
+                android:configChanges="orientation|keyboardHidden">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+    <uses-feature android:glEsVersion="0x00030000"/>
+    <uses-sdk android:minSdkVersion="18"/>
+</manifest>
diff --git a/ndk/platforms/android-18/samples/gles3jni/README b/ndk/platforms/android-18/samples/gles3jni/README
new file mode 100644
index 0000000..2250e21
--- /dev/null
+++ b/ndk/platforms/android-18/samples/gles3jni/README
@@ -0,0 +1,33 @@
+This sample demonstrates how to use OpenGL ES 3.0 from JNI/native code.
+
+The sample can be built two different ways:
+  * Compatible with API level 11 and later [*1]
+  * Require API level 18 or later.
+Both versions include an OpenGL ES 2.0 fallback path for devices that don't
+support OpenGL ES 3.0.
+
+To build and install the sample:
+$ ln -s AndroidManifest-$N.xml AndroidManifest.xml
+$ ln -s Android-$N.mk jni/Android.mk
+$ $ANDROID_SDK/tools/android update project --path . --target android-$N
+$ ../../ndk-build
+$ ant debug
+$ adb install bin/GLES3JNIActivity-debug.apk
+where $N is '11' or '18' and
+ANDROID_SDK is the root of your SDK installation.
+
+The OpenGL ES 3.0 rendering path uses a few new features compared to the
+OpenGL ES 2.0 path:
+
+* Instanced rendering and vertex attribute divisor to reduce the number of
+  draw calls and uniform changes.
+* Vertex array objects to reduce the number of calls required to set up
+  vertex attribute state on each frame.
+* Explicit assignment of attribute locations, eliminating the need to query
+  assignments.
+
+
+[*1] The only dependency on API level 11 is the call to
+     setEGLContextClientVersion in GLES3JNIView. With a custom
+     EGLConfigChooser and EGLContextFactory the sample would be compatible
+     with older API levels.
diff --git a/ndk/platforms/android-18/samples/gles3jni/jni/Android-11.mk b/ndk/platforms/android-18/samples/gles3jni/jni/Android-11.mk
new file mode 100644
index 0000000..baf17d2
--- /dev/null
+++ b/ndk/platforms/android-18/samples/gles3jni/jni/Android-11.mk
@@ -0,0 +1,27 @@
+# Copyright 2013 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE     := libgles3jni
+LOCAL_CFLAGS     := -Werror -DDYNAMIC_ES3
+LOCAL_SRC_FILES  := gles3jni.cpp \
+				   RendererES2.cpp \
+				   RendererES3.cpp \
+				   gl3stub.c
+LOCAL_LDLIBS     := -llog -lGLESv2 -lEGL
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/ndk/platforms/android-18/samples/gles3jni/jni/Android-18.mk b/ndk/platforms/android-18/samples/gles3jni/jni/Android-18.mk
new file mode 100644
index 0000000..5111de5
--- /dev/null
+++ b/ndk/platforms/android-18/samples/gles3jni/jni/Android-18.mk
@@ -0,0 +1,26 @@
+# Copyright 2013 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE    := libgles3jni
+LOCAL_CFLAGS    := -Werror
+LOCAL_SRC_FILES := gles3jni.cpp \
+				   RendererES2.cpp \
+				   RendererES3.cpp
+LOCAL_LDLIBS    := -llog -lGLESv3 -lEGL
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/ndk/platforms/android-18/samples/gles3jni/jni/RendererES2.cpp b/ndk/platforms/android-18/samples/gles3jni/jni/RendererES2.cpp
new file mode 100644
index 0000000..d5f8d48
--- /dev/null
+++ b/ndk/platforms/android-18/samples/gles3jni/jni/RendererES2.cpp
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2013 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.
+ */
+
+#include "gles3jni.h"
+#include <EGL/egl.h>
+
+static const char VERTEX_SHADER[] =
+    "#version 100\n"
+    "uniform mat2 scaleRot;\n"
+    "uniform vec2 offset;\n"
+    "attribute vec2 pos;\n"
+    "attribute vec4 color;\n"
+    "varying vec4 vColor;\n"
+    "void main() {\n"
+    "    gl_Position = vec4(scaleRot*pos + offset, 0.0, 1.0);\n"
+    "    vColor = color;\n"
+    "}\n";
+
+static const char FRAGMENT_SHADER[] =
+    "#version 100\n"
+    "precision mediump float;\n"
+    "varying vec4 vColor;\n"
+    "void main() {\n"
+    "    gl_FragColor = vColor;\n"
+    "}\n";
+
+class RendererES2: public Renderer {
+public:
+    RendererES2();
+    virtual ~RendererES2();
+    bool init();
+
+private:
+    virtual float* mapOffsetBuf();
+    virtual void unmapOffsetBuf();
+    virtual float* mapTransformBuf();
+    virtual void unmapTransformBuf();
+    virtual void draw(unsigned int numInstances);
+
+    const EGLContext mEglContext;
+    GLuint mProgram;
+    GLuint mVB;
+    GLint mPosAttrib;
+    GLint mColorAttrib;
+    GLint mScaleRotUniform;
+    GLint mOffsetUniform;
+
+    float mOffsets[2*MAX_INSTANCES];
+    float mScaleRot[4*MAX_INSTANCES];   // array of 2x2 column-major matrices
+};
+
+Renderer* createES2Renderer() {
+    RendererES2* renderer = new RendererES2;
+    if (!renderer->init()) {
+        delete renderer;
+        return NULL;
+    }
+    return renderer;
+}
+
+RendererES2::RendererES2()
+:   mEglContext(eglGetCurrentContext()),
+    mProgram(0),
+    mVB(0),
+    mPosAttrib(-1),
+    mColorAttrib(-1),
+    mScaleRotUniform(-1),
+    mOffsetUniform(-1)
+{}
+
+bool RendererES2::init() {
+    mProgram = createProgram(VERTEX_SHADER, FRAGMENT_SHADER);
+    if (!mProgram)
+        return false;
+    mPosAttrib = glGetAttribLocation(mProgram, "pos");
+    mColorAttrib = glGetAttribLocation(mProgram, "color");
+    mScaleRotUniform = glGetUniformLocation(mProgram, "scaleRot");
+    mOffsetUniform = glGetUniformLocation(mProgram, "offset");
+
+    glGenBuffers(1, &mVB);
+    glBindBuffer(GL_ARRAY_BUFFER, mVB);
+    glBufferData(GL_ARRAY_BUFFER, sizeof(QUAD), &QUAD[0], GL_STATIC_DRAW);
+
+    ALOGV("Using OpenGL ES 2.0 renderer");
+    return true;
+}
+
+RendererES2::~RendererES2() {
+    /* The destructor may be called after the context has already been
+     * destroyed, in which case our objects have already been destroyed.
+     *
+     * If the context exists, it must be current. This only happens when we're
+     * cleaning up after a failed init().
+     */
+    if (eglGetCurrentContext() != mEglContext)
+        return;
+    glDeleteBuffers(1, &mVB);
+    glDeleteProgram(mProgram);
+}
+
+float* RendererES2::mapOffsetBuf() {
+    return mOffsets;
+}
+
+void RendererES2::unmapOffsetBuf() {
+}
+
+float* RendererES2::mapTransformBuf() {
+    return mScaleRot;
+}
+
+void RendererES2::unmapTransformBuf() {
+}
+
+void RendererES2::draw(unsigned int numInstances) {
+    glUseProgram(mProgram);
+
+    glBindBuffer(GL_ARRAY_BUFFER, mVB);
+    glVertexAttribPointer(mPosAttrib, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)offsetof(Vertex, pos));
+    glVertexAttribPointer(mColorAttrib, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (const GLvoid*)offsetof(Vertex, rgba));
+    glEnableVertexAttribArray(mPosAttrib);
+    glEnableVertexAttribArray(mColorAttrib);
+
+    for (unsigned int i = 0; i < numInstances; i++) {
+        glUniformMatrix2fv(mScaleRotUniform, 1, GL_FALSE, mScaleRot + 4*i);
+        glUniform2fv(mOffsetUniform, 1, mOffsets + 2*i);
+        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+    }
+}
diff --git a/ndk/platforms/android-18/samples/gles3jni/jni/RendererES3.cpp b/ndk/platforms/android-18/samples/gles3jni/jni/RendererES3.cpp
new file mode 100644
index 0000000..a6e617b
--- /dev/null
+++ b/ndk/platforms/android-18/samples/gles3jni/jni/RendererES3.cpp
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2013 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.
+ */
+
+#include "gles3jni.h"
+#include <EGL/egl.h>
+
+#define STR(s) #s
+#define STRV(s) STR(s)
+
+#define POS_ATTRIB 0
+#define COLOR_ATTRIB 1
+#define SCALEROT_ATTRIB 2
+#define OFFSET_ATTRIB 3
+
+static const char VERTEX_SHADER[] =
+    "#version 300 es\n"
+    "layout(location = " STRV(POS_ATTRIB) ") in vec2 pos;\n"
+    "layout(location=" STRV(COLOR_ATTRIB) ") in vec4 color;\n"
+    "layout(location=" STRV(SCALEROT_ATTRIB) ") in vec4 scaleRot;\n"
+    "layout(location=" STRV(OFFSET_ATTRIB) ") in vec2 offset;\n"
+    "out vec4 vColor;\n"
+    "void main() {\n"
+    "    mat2 sr = mat2(scaleRot.xy, scaleRot.zw);\n"
+    "    gl_Position = vec4(sr*pos + offset, 0.0, 1.0);\n"
+    "    vColor = color;\n"
+    "}\n";
+
+static const char FRAGMENT_SHADER[] =
+    "#version 300 es\n"
+    "precision mediump float;\n"
+    "in vec4 vColor;\n"
+    "out vec4 outColor;\n"
+    "void main() {\n"
+    "    outColor = vColor;\n"
+    "}\n";
+
+class RendererES3: public Renderer {
+public:
+    RendererES3();
+    virtual ~RendererES3();
+    bool init();
+
+private:
+    enum {VB_INSTANCE, VB_SCALEROT, VB_OFFSET, VB_COUNT};
+
+    virtual float* mapOffsetBuf();
+    virtual void unmapOffsetBuf();
+    virtual float* mapTransformBuf();
+    virtual void unmapTransformBuf();
+    virtual void draw(unsigned int numInstances);
+
+    const EGLContext mEglContext;
+    GLuint mProgram;
+    GLuint mVB[VB_COUNT];
+    GLuint mVBState;
+};
+
+Renderer* createES3Renderer() {
+    RendererES3* renderer = new RendererES3;
+    if (!renderer->init()) {
+        delete renderer;
+        return NULL;
+    }
+    return renderer;
+}
+
+RendererES3::RendererES3()
+:   mEglContext(eglGetCurrentContext()),
+    mProgram(0),
+    mVBState(0)
+{
+    for (int i = 0; i < VB_COUNT; i++)
+        mVB[i] = 0;
+}
+
+bool RendererES3::init() {
+    mProgram = createProgram(VERTEX_SHADER, FRAGMENT_SHADER);
+    if (!mProgram)
+        return false;
+
+    glGenBuffers(VB_COUNT, mVB);
+    glBindBuffer(GL_ARRAY_BUFFER, mVB[VB_INSTANCE]);
+    glBufferData(GL_ARRAY_BUFFER, sizeof(QUAD), &QUAD[0], GL_STATIC_DRAW);
+    glBindBuffer(GL_ARRAY_BUFFER, mVB[VB_SCALEROT]);
+    glBufferData(GL_ARRAY_BUFFER, MAX_INSTANCES * 4*sizeof(float), NULL, GL_DYNAMIC_DRAW);
+    glBindBuffer(GL_ARRAY_BUFFER, mVB[VB_OFFSET]);
+    glBufferData(GL_ARRAY_BUFFER, MAX_INSTANCES * 2*sizeof(float), NULL, GL_STATIC_DRAW);
+
+    glGenVertexArrays(1, &mVBState);
+    glBindVertexArray(mVBState);
+
+    glBindBuffer(GL_ARRAY_BUFFER, mVB[VB_INSTANCE]);
+    glVertexAttribPointer(POS_ATTRIB, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)offsetof(Vertex, pos));
+    glVertexAttribPointer(COLOR_ATTRIB, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (const GLvoid*)offsetof(Vertex, rgba));
+    glEnableVertexAttribArray(POS_ATTRIB);
+    glEnableVertexAttribArray(COLOR_ATTRIB);
+
+    glBindBuffer(GL_ARRAY_BUFFER, mVB[VB_SCALEROT]);
+    glVertexAttribPointer(SCALEROT_ATTRIB, 4, GL_FLOAT, GL_FALSE, 4*sizeof(float), 0);
+    glEnableVertexAttribArray(SCALEROT_ATTRIB);
+    glVertexAttribDivisor(SCALEROT_ATTRIB, 1);
+
+    glBindBuffer(GL_ARRAY_BUFFER, mVB[VB_OFFSET]);
+    glVertexAttribPointer(OFFSET_ATTRIB, 2, GL_FLOAT, GL_FALSE, 2*sizeof(float), 0);
+    glEnableVertexAttribArray(OFFSET_ATTRIB);
+    glVertexAttribDivisor(OFFSET_ATTRIB, 1);
+
+    ALOGV("Using OpenGL ES 3.0 renderer");
+    return true;
+}
+
+RendererES3::~RendererES3() {
+    /* The destructor may be called after the context has already been
+     * destroyed, in which case our objects have already been destroyed.
+     *
+     * If the context exists, it must be current. This only happens when we're
+     * cleaning up after a failed init().
+     */
+    if (eglGetCurrentContext() != mEglContext)
+        return;
+    glDeleteVertexArrays(1, &mVBState);
+    glDeleteBuffers(VB_COUNT, mVB);
+    glDeleteProgram(mProgram);
+}
+
+float* RendererES3::mapOffsetBuf() {
+    glBindBuffer(GL_ARRAY_BUFFER, mVB[VB_OFFSET]);
+    return (float*)glMapBufferRange(GL_ARRAY_BUFFER,
+            0, MAX_INSTANCES * 2*sizeof(float),
+            GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
+}
+
+void RendererES3::unmapOffsetBuf() {
+    glUnmapBuffer(GL_ARRAY_BUFFER);
+}
+
+float* RendererES3::mapTransformBuf() {
+    glBindBuffer(GL_ARRAY_BUFFER, mVB[VB_SCALEROT]);
+    return (float*)glMapBufferRange(GL_ARRAY_BUFFER,
+            0, MAX_INSTANCES * 4*sizeof(float),
+            GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
+}
+
+void RendererES3::unmapTransformBuf() {
+    glUnmapBuffer(GL_ARRAY_BUFFER);
+}
+
+void RendererES3::draw(unsigned int numInstances) {
+    glUseProgram(mProgram);
+    glBindVertexArray(mVBState);
+    glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, numInstances);
+}
diff --git a/ndk/platforms/android-18/samples/gles3jni/jni/gl3stub.c b/ndk/platforms/android-18/samples/gles3jni/jni/gl3stub.c
new file mode 100644
index 0000000..67bf70c
--- /dev/null
+++ b/ndk/platforms/android-18/samples/gles3jni/jni/gl3stub.c
@@ -0,0 +1,343 @@
+/*
+ * Copyright 2013 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.
+ */
+
+#include <EGL/egl.h>
+#include "gl3stub.h"
+
+GLboolean gl3stubInit() {
+    #define FIND_PROC(s) s = (void*)eglGetProcAddress(#s)
+    FIND_PROC(glReadBuffer);
+    FIND_PROC(glDrawRangeElements);
+    FIND_PROC(glTexImage3D);
+    FIND_PROC(glTexSubImage3D);
+    FIND_PROC(glCopyTexSubImage3D);
+    FIND_PROC(glCompressedTexImage3D);
+    FIND_PROC(glCompressedTexSubImage3D);
+    FIND_PROC(glGenQueries);
+    FIND_PROC(glDeleteQueries);
+    FIND_PROC(glIsQuery);
+    FIND_PROC(glBeginQuery);
+    FIND_PROC(glEndQuery);
+    FIND_PROC(glGetQueryiv);
+    FIND_PROC(glGetQueryObjectuiv);
+    FIND_PROC(glUnmapBuffer);
+    FIND_PROC(glGetBufferPointerv);
+    FIND_PROC(glDrawBuffers);
+    FIND_PROC(glUniformMatrix2x3fv);
+    FIND_PROC(glUniformMatrix3x2fv);
+    FIND_PROC(glUniformMatrix2x4fv);
+    FIND_PROC(glUniformMatrix4x2fv);
+    FIND_PROC(glUniformMatrix3x4fv);
+    FIND_PROC(glUniformMatrix4x3fv);
+    FIND_PROC(glBlitFramebuffer);
+    FIND_PROC(glRenderbufferStorageMultisample);
+    FIND_PROC(glFramebufferTextureLayer);
+    FIND_PROC(glMapBufferRange);
+    FIND_PROC(glFlushMappedBufferRange);
+    FIND_PROC(glBindVertexArray);
+    FIND_PROC(glDeleteVertexArrays);
+    FIND_PROC(glGenVertexArrays);
+    FIND_PROC(glIsVertexArray);
+    FIND_PROC(glGetIntegeri_v);
+    FIND_PROC(glBeginTransformFeedback);
+    FIND_PROC(glEndTransformFeedback);
+    FIND_PROC(glBindBufferRange);
+    FIND_PROC(glBindBufferBase);
+    FIND_PROC(glTransformFeedbackVaryings);
+    FIND_PROC(glGetTransformFeedbackVarying);
+    FIND_PROC(glVertexAttribIPointer);
+    FIND_PROC(glGetVertexAttribIiv);
+    FIND_PROC(glGetVertexAttribIuiv);
+    FIND_PROC(glVertexAttribI4i);
+    FIND_PROC(glVertexAttribI4ui);
+    FIND_PROC(glVertexAttribI4iv);
+    FIND_PROC(glVertexAttribI4uiv);
+    FIND_PROC(glGetUniformuiv);
+    FIND_PROC(glGetFragDataLocation);
+    FIND_PROC(glUniform1ui);
+    FIND_PROC(glUniform2ui);
+    FIND_PROC(glUniform3ui);
+    FIND_PROC(glUniform4ui);
+    FIND_PROC(glUniform1uiv);
+    FIND_PROC(glUniform2uiv);
+    FIND_PROC(glUniform3uiv);
+    FIND_PROC(glUniform4uiv);
+    FIND_PROC(glClearBufferiv);
+    FIND_PROC(glClearBufferuiv);
+    FIND_PROC(glClearBufferfv);
+    FIND_PROC(glClearBufferfi);
+    FIND_PROC(glGetStringi);
+    FIND_PROC(glCopyBufferSubData);
+    FIND_PROC(glGetUniformIndices);
+    FIND_PROC(glGetActiveUniformsiv);
+    FIND_PROC(glGetUniformBlockIndex);
+    FIND_PROC(glGetActiveUniformBlockiv);
+    FIND_PROC(glGetActiveUniformBlockName);
+    FIND_PROC(glUniformBlockBinding);
+    FIND_PROC(glDrawArraysInstanced);
+    FIND_PROC(glDrawElementsInstanced);
+    FIND_PROC(glFenceSync);
+    FIND_PROC(glIsSync);
+    FIND_PROC(glDeleteSync);
+    FIND_PROC(glClientWaitSync);
+    FIND_PROC(glWaitSync);
+    FIND_PROC(glGetInteger64v);
+    FIND_PROC(glGetSynciv);
+    FIND_PROC(glGetInteger64i_v);
+    FIND_PROC(glGetBufferParameteri64v);
+    FIND_PROC(glGenSamplers);
+    FIND_PROC(glDeleteSamplers);
+    FIND_PROC(glIsSampler);
+    FIND_PROC(glBindSampler);
+    FIND_PROC(glSamplerParameteri);
+    FIND_PROC(glSamplerParameteriv);
+    FIND_PROC(glSamplerParameterf);
+    FIND_PROC(glSamplerParameterfv);
+    FIND_PROC(glGetSamplerParameteriv);
+    FIND_PROC(glGetSamplerParameterfv);
+    FIND_PROC(glVertexAttribDivisor);
+    FIND_PROC(glBindTransformFeedback);
+    FIND_PROC(glDeleteTransformFeedbacks);
+    FIND_PROC(glGenTransformFeedbacks);
+    FIND_PROC(glIsTransformFeedback);
+    FIND_PROC(glPauseTransformFeedback);
+    FIND_PROC(glResumeTransformFeedback);
+    FIND_PROC(glGetProgramBinary);
+    FIND_PROC(glProgramBinary);
+    FIND_PROC(glProgramParameteri);
+    FIND_PROC(glInvalidateFramebuffer);
+    FIND_PROC(glInvalidateSubFramebuffer);
+    FIND_PROC(glTexStorage2D);
+    FIND_PROC(glTexStorage3D);
+    FIND_PROC(glGetInternalformativ);
+    #undef FIND_PROC
+
+    if (!glReadBuffer ||
+        !glDrawRangeElements ||
+        !glTexImage3D ||
+        !glTexSubImage3D ||
+        !glCopyTexSubImage3D ||
+        !glCompressedTexImage3D ||
+        !glCompressedTexSubImage3D ||
+        !glGenQueries ||
+        !glDeleteQueries ||
+        !glIsQuery ||
+        !glBeginQuery ||
+        !glEndQuery ||
+        !glGetQueryiv ||
+        !glGetQueryObjectuiv ||
+        !glUnmapBuffer ||
+        !glGetBufferPointerv ||
+        !glDrawBuffers ||
+        !glUniformMatrix2x3fv ||
+        !glUniformMatrix3x2fv ||
+        !glUniformMatrix2x4fv ||
+        !glUniformMatrix4x2fv ||
+        !glUniformMatrix3x4fv ||
+        !glUniformMatrix4x3fv ||
+        !glBlitFramebuffer ||
+        !glRenderbufferStorageMultisample ||
+        !glFramebufferTextureLayer ||
+        !glMapBufferRange ||
+        !glFlushMappedBufferRange ||
+        !glBindVertexArray ||
+        !glDeleteVertexArrays ||
+        !glGenVertexArrays ||
+        !glIsVertexArray ||
+        !glGetIntegeri_v ||
+        !glBeginTransformFeedback ||
+        !glEndTransformFeedback ||
+        !glBindBufferRange ||
+        !glBindBufferBase ||
+        !glTransformFeedbackVaryings ||
+        !glGetTransformFeedbackVarying ||
+        !glVertexAttribIPointer ||
+        !glGetVertexAttribIiv ||
+        !glGetVertexAttribIuiv ||
+        !glVertexAttribI4i ||
+        !glVertexAttribI4ui ||
+        !glVertexAttribI4iv ||
+        !glVertexAttribI4uiv ||
+        !glGetUniformuiv ||
+        !glGetFragDataLocation ||
+        !glUniform1ui ||
+        !glUniform2ui ||
+        !glUniform3ui ||
+        !glUniform4ui ||
+        !glUniform1uiv ||
+        !glUniform2uiv ||
+        !glUniform3uiv ||
+        !glUniform4uiv ||
+        !glClearBufferiv ||
+        !glClearBufferuiv ||
+        !glClearBufferfv ||
+        !glClearBufferfi ||
+        !glGetStringi ||
+        !glCopyBufferSubData ||
+        !glGetUniformIndices ||
+        !glGetActiveUniformsiv ||
+        !glGetUniformBlockIndex ||
+        !glGetActiveUniformBlockiv ||
+        !glGetActiveUniformBlockName ||
+        !glUniformBlockBinding ||
+        !glDrawArraysInstanced ||
+        !glDrawElementsInstanced ||
+        !glFenceSync ||
+        !glIsSync ||
+        !glDeleteSync ||
+        !glClientWaitSync ||
+        !glWaitSync ||
+        !glGetInteger64v ||
+        !glGetSynciv ||
+        !glGetInteger64i_v ||
+        !glGetBufferParameteri64v ||
+        !glGenSamplers ||
+        !glDeleteSamplers ||
+        !glIsSampler ||
+        !glBindSampler ||
+        !glSamplerParameteri ||
+        !glSamplerParameteriv ||
+        !glSamplerParameterf ||
+        !glSamplerParameterfv ||
+        !glGetSamplerParameteriv ||
+        !glGetSamplerParameterfv ||
+        !glVertexAttribDivisor ||
+        !glBindTransformFeedback ||
+        !glDeleteTransformFeedbacks ||
+        !glGenTransformFeedbacks ||
+        !glIsTransformFeedback ||
+        !glPauseTransformFeedback ||
+        !glResumeTransformFeedback ||
+        !glGetProgramBinary ||
+        !glProgramBinary ||
+        !glProgramParameteri ||
+        !glInvalidateFramebuffer ||
+        !glInvalidateSubFramebuffer ||
+        !glTexStorage2D ||
+        !glTexStorage3D ||
+        !glGetInternalformativ)
+    {
+        return GL_FALSE;
+    }
+
+    return GL_TRUE;
+}
+
+/* Function pointer definitions */
+GL_APICALL void           (* GL_APIENTRY glReadBuffer) (GLenum mode);
+GL_APICALL void           (* GL_APIENTRY glDrawRangeElements) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices);
+GL_APICALL void           (* GL_APIENTRY glTexImage3D) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void           (* GL_APIENTRY glTexSubImage3D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void           (* GL_APIENTRY glCopyTexSubImage3D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void           (* GL_APIENTRY glCompressedTexImage3D) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void           (* GL_APIENTRY glCompressedTexSubImage3D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void           (* GL_APIENTRY glGenQueries) (GLsizei n, GLuint* ids);
+GL_APICALL void           (* GL_APIENTRY glDeleteQueries) (GLsizei n, const GLuint* ids);
+GL_APICALL GLboolean      (* GL_APIENTRY glIsQuery) (GLuint id);
+GL_APICALL void           (* GL_APIENTRY glBeginQuery) (GLenum target, GLuint id);
+GL_APICALL void           (* GL_APIENTRY glEndQuery) (GLenum target);
+GL_APICALL void           (* GL_APIENTRY glGetQueryiv) (GLenum target, GLenum pname, GLint* params);
+GL_APICALL void           (* GL_APIENTRY glGetQueryObjectuiv) (GLuint id, GLenum pname, GLuint* params);
+GL_APICALL GLboolean      (* GL_APIENTRY glUnmapBuffer) (GLenum target);
+GL_APICALL void           (* GL_APIENTRY glGetBufferPointerv) (GLenum target, GLenum pname, GLvoid** params);
+GL_APICALL void           (* GL_APIENTRY glDrawBuffers) (GLsizei n, const GLenum* bufs);
+GL_APICALL void           (* GL_APIENTRY glUniformMatrix2x3fv) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void           (* GL_APIENTRY glUniformMatrix3x2fv) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void           (* GL_APIENTRY glUniformMatrix2x4fv) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void           (* GL_APIENTRY glUniformMatrix4x2fv) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void           (* GL_APIENTRY glUniformMatrix3x4fv) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void           (* GL_APIENTRY glUniformMatrix4x3fv) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void           (* GL_APIENTRY glBlitFramebuffer) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+GL_APICALL void           (* GL_APIENTRY glRenderbufferStorageMultisample) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void           (* GL_APIENTRY glFramebufferTextureLayer) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+GL_APICALL GLvoid*        (* GL_APIENTRY glMapBufferRange) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+GL_APICALL void           (* GL_APIENTRY glFlushMappedBufferRange) (GLenum target, GLintptr offset, GLsizeiptr length);
+GL_APICALL void           (* GL_APIENTRY glBindVertexArray) (GLuint array);
+GL_APICALL void           (* GL_APIENTRY glDeleteVertexArrays) (GLsizei n, const GLuint* arrays);
+GL_APICALL void           (* GL_APIENTRY glGenVertexArrays) (GLsizei n, GLuint* arrays);
+GL_APICALL GLboolean      (* GL_APIENTRY glIsVertexArray) (GLuint array);
+GL_APICALL void           (* GL_APIENTRY glGetIntegeri_v) (GLenum target, GLuint index, GLint* data);
+GL_APICALL void           (* GL_APIENTRY glBeginTransformFeedback) (GLenum primitiveMode);
+GL_APICALL void           (* GL_APIENTRY glEndTransformFeedback) (void);
+GL_APICALL void           (* GL_APIENTRY glBindBufferRange) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GL_APICALL void           (* GL_APIENTRY glBindBufferBase) (GLenum target, GLuint index, GLuint buffer);
+GL_APICALL void           (* GL_APIENTRY glTransformFeedbackVaryings) (GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode);
+GL_APICALL void           (* GL_APIENTRY glGetTransformFeedbackVarying) (GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name);
+GL_APICALL void           (* GL_APIENTRY glVertexAttribIPointer) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer);
+GL_APICALL void           (* GL_APIENTRY glGetVertexAttribIiv) (GLuint index, GLenum pname, GLint* params);
+GL_APICALL void           (* GL_APIENTRY glGetVertexAttribIuiv) (GLuint index, GLenum pname, GLuint* params);
+GL_APICALL void           (* GL_APIENTRY glVertexAttribI4i) (GLuint index, GLint x, GLint y, GLint z, GLint w);
+GL_APICALL void           (* GL_APIENTRY glVertexAttribI4ui) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+GL_APICALL void           (* GL_APIENTRY glVertexAttribI4iv) (GLuint index, const GLint* v);
+GL_APICALL void           (* GL_APIENTRY glVertexAttribI4uiv) (GLuint index, const GLuint* v);
+GL_APICALL void           (* GL_APIENTRY glGetUniformuiv) (GLuint program, GLint location, GLuint* params);
+GL_APICALL GLint          (* GL_APIENTRY glGetFragDataLocation) (GLuint program, const GLchar *name);
+GL_APICALL void           (* GL_APIENTRY glUniform1ui) (GLint location, GLuint v0);
+GL_APICALL void           (* GL_APIENTRY glUniform2ui) (GLint location, GLuint v0, GLuint v1);
+GL_APICALL void           (* GL_APIENTRY glUniform3ui) (GLint location, GLuint v0, GLuint v1, GLuint v2);
+GL_APICALL void           (* GL_APIENTRY glUniform4ui) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GL_APICALL void           (* GL_APIENTRY glUniform1uiv) (GLint location, GLsizei count, const GLuint* value);
+GL_APICALL void           (* GL_APIENTRY glUniform2uiv) (GLint location, GLsizei count, const GLuint* value);
+GL_APICALL void           (* GL_APIENTRY glUniform3uiv) (GLint location, GLsizei count, const GLuint* value);
+GL_APICALL void           (* GL_APIENTRY glUniform4uiv) (GLint location, GLsizei count, const GLuint* value);
+GL_APICALL void           (* GL_APIENTRY glClearBufferiv) (GLenum buffer, GLint drawbuffer, const GLint* value);
+GL_APICALL void           (* GL_APIENTRY glClearBufferuiv) (GLenum buffer, GLint drawbuffer, const GLuint* value);
+GL_APICALL void           (* GL_APIENTRY glClearBufferfv) (GLenum buffer, GLint drawbuffer, const GLfloat* value);
+GL_APICALL void           (* GL_APIENTRY glClearBufferfi) (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+GL_APICALL const GLubyte* (* GL_APIENTRY glGetStringi) (GLenum name, GLuint index);
+GL_APICALL void           (* GL_APIENTRY glCopyBufferSubData) (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+GL_APICALL void           (* GL_APIENTRY glGetUniformIndices) (GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices);
+GL_APICALL void           (* GL_APIENTRY glGetActiveUniformsiv) (GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params);
+GL_APICALL GLuint         (* GL_APIENTRY glGetUniformBlockIndex) (GLuint program, const GLchar* uniformBlockName);
+GL_APICALL void           (* GL_APIENTRY glGetActiveUniformBlockiv) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params);
+GL_APICALL void           (* GL_APIENTRY glGetActiveUniformBlockName) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName);
+GL_APICALL void           (* GL_APIENTRY glUniformBlockBinding) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+GL_APICALL void           (* GL_APIENTRY glDrawArraysInstanced) (GLenum mode, GLint first, GLsizei count, GLsizei instanceCount);
+GL_APICALL void           (* GL_APIENTRY glDrawElementsInstanced) (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount);
+GL_APICALL GLsync         (* GL_APIENTRY glFenceSync) (GLenum condition, GLbitfield flags);
+GL_APICALL GLboolean      (* GL_APIENTRY glIsSync) (GLsync sync);
+GL_APICALL void           (* GL_APIENTRY glDeleteSync) (GLsync sync);
+GL_APICALL GLenum         (* GL_APIENTRY glClientWaitSync) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GL_APICALL void           (* GL_APIENTRY glWaitSync) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GL_APICALL void           (* GL_APIENTRY glGetInteger64v) (GLenum pname, GLint64* params);
+GL_APICALL void           (* GL_APIENTRY glGetSynciv) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values);
+GL_APICALL void           (* GL_APIENTRY glGetInteger64i_v) (GLenum target, GLuint index, GLint64* data);
+GL_APICALL void           (* GL_APIENTRY glGetBufferParameteri64v) (GLenum target, GLenum pname, GLint64* params);
+GL_APICALL void           (* GL_APIENTRY glGenSamplers) (GLsizei count, GLuint* samplers);
+GL_APICALL void           (* GL_APIENTRY glDeleteSamplers) (GLsizei count, const GLuint* samplers);
+GL_APICALL GLboolean      (* GL_APIENTRY glIsSampler) (GLuint sampler);
+GL_APICALL void           (* GL_APIENTRY glBindSampler) (GLuint unit, GLuint sampler);
+GL_APICALL void           (* GL_APIENTRY glSamplerParameteri) (GLuint sampler, GLenum pname, GLint param);
+GL_APICALL void           (* GL_APIENTRY glSamplerParameteriv) (GLuint sampler, GLenum pname, const GLint* param);
+GL_APICALL void           (* GL_APIENTRY glSamplerParameterf) (GLuint sampler, GLenum pname, GLfloat param);
+GL_APICALL void           (* GL_APIENTRY glSamplerParameterfv) (GLuint sampler, GLenum pname, const GLfloat* param);
+GL_APICALL void           (* GL_APIENTRY glGetSamplerParameteriv) (GLuint sampler, GLenum pname, GLint* params);
+GL_APICALL void           (* GL_APIENTRY glGetSamplerParameterfv) (GLuint sampler, GLenum pname, GLfloat* params);
+GL_APICALL void           (* GL_APIENTRY glVertexAttribDivisor) (GLuint index, GLuint divisor);
+GL_APICALL void           (* GL_APIENTRY glBindTransformFeedback) (GLenum target, GLuint id);
+GL_APICALL void           (* GL_APIENTRY glDeleteTransformFeedbacks) (GLsizei n, const GLuint* ids);
+GL_APICALL void           (* GL_APIENTRY glGenTransformFeedbacks) (GLsizei n, GLuint* ids);
+GL_APICALL GLboolean      (* GL_APIENTRY glIsTransformFeedback) (GLuint id);
+GL_APICALL void           (* GL_APIENTRY glPauseTransformFeedback) (void);
+GL_APICALL void           (* GL_APIENTRY glResumeTransformFeedback) (void);
+GL_APICALL void           (* GL_APIENTRY glGetProgramBinary) (GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary);
+GL_APICALL void           (* GL_APIENTRY glProgramBinary) (GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length);
+GL_APICALL void           (* GL_APIENTRY glProgramParameteri) (GLuint program, GLenum pname, GLint value);
+GL_APICALL void           (* GL_APIENTRY glInvalidateFramebuffer) (GLenum target, GLsizei numAttachments, const GLenum* attachments);
+GL_APICALL void           (* GL_APIENTRY glInvalidateSubFramebuffer) (GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void           (* GL_APIENTRY glTexStorage2D) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void           (* GL_APIENTRY glTexStorage3D) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+GL_APICALL void           (* GL_APIENTRY glGetInternalformativ) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params);
diff --git a/ndk/platforms/android-18/samples/gles3jni/jni/gl3stub.h b/ndk/platforms/android-18/samples/gles3jni/jni/gl3stub.h
new file mode 100644
index 0000000..7a02bf2
--- /dev/null
+++ b/ndk/platforms/android-18/samples/gles3jni/jni/gl3stub.h
@@ -0,0 +1,491 @@
+#ifndef __gl3_h_
+#define __gl3_h_
+
+/*
+ * stub gl3.h for dynamic loading, based on:
+ * gl3.h last updated on $Date: 2013-02-12 14:37:24 -0800 (Tue, 12 Feb 2013) $
+ *
+ * Changes:
+ * - Added #include <GLES2/gl2.h>
+ * - Removed duplicate OpenGL ES 2.0 declarations
+ * - Converted OpenGL ES 3.0 function prototypes to function pointer
+ *   declarations
+ * - Added gl3stubInit() declaration
+ */
+
+#include <GLES2/gl2.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright (c) 2007-2013 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+/* Call this function before calling any OpenGL ES 3.0 functions. It will
+ * return GL_TRUE if the OpenGL ES 3.0 was successfully initialized, GL_FALSE
+ * otherwise. */
+GLboolean gl3stubInit();
+
+/*-------------------------------------------------------------------------
+ * Data type definitions
+ *-----------------------------------------------------------------------*/
+
+/* OpenGL ES 3.0 */
+
+typedef unsigned short   GLhalf;
+typedef khronos_int64_t  GLint64;
+typedef khronos_uint64_t GLuint64;
+typedef struct __GLsync *GLsync;
+
+/*-------------------------------------------------------------------------
+ * Token definitions
+ *-----------------------------------------------------------------------*/
+
+/* OpenGL ES core versions */
+#define GL_ES_VERSION_3_0                                1
+
+/* OpenGL ES 3.0 */
+
+#define GL_READ_BUFFER                                   0x0C02
+#define GL_UNPACK_ROW_LENGTH                             0x0CF2
+#define GL_UNPACK_SKIP_ROWS                              0x0CF3
+#define GL_UNPACK_SKIP_PIXELS                            0x0CF4
+#define GL_PACK_ROW_LENGTH                               0x0D02
+#define GL_PACK_SKIP_ROWS                                0x0D03
+#define GL_PACK_SKIP_PIXELS                              0x0D04
+#define GL_COLOR                                         0x1800
+#define GL_DEPTH                                         0x1801
+#define GL_STENCIL                                       0x1802
+#define GL_RED                                           0x1903
+#define GL_RGB8                                          0x8051
+#define GL_RGBA8                                         0x8058
+#define GL_RGB10_A2                                      0x8059
+#define GL_TEXTURE_BINDING_3D                            0x806A
+#define GL_UNPACK_SKIP_IMAGES                            0x806D
+#define GL_UNPACK_IMAGE_HEIGHT                           0x806E
+#define GL_TEXTURE_3D                                    0x806F
+#define GL_TEXTURE_WRAP_R                                0x8072
+#define GL_MAX_3D_TEXTURE_SIZE                           0x8073
+#define GL_UNSIGNED_INT_2_10_10_10_REV                   0x8368
+#define GL_MAX_ELEMENTS_VERTICES                         0x80E8
+#define GL_MAX_ELEMENTS_INDICES                          0x80E9
+#define GL_TEXTURE_MIN_LOD                               0x813A
+#define GL_TEXTURE_MAX_LOD                               0x813B
+#define GL_TEXTURE_BASE_LEVEL                            0x813C
+#define GL_TEXTURE_MAX_LEVEL                             0x813D
+#define GL_MIN                                           0x8007
+#define GL_MAX                                           0x8008
+#define GL_DEPTH_COMPONENT24                             0x81A6
+#define GL_MAX_TEXTURE_LOD_BIAS                          0x84FD
+#define GL_TEXTURE_COMPARE_MODE                          0x884C
+#define GL_TEXTURE_COMPARE_FUNC                          0x884D
+#define GL_CURRENT_QUERY                                 0x8865
+#define GL_QUERY_RESULT                                  0x8866
+#define GL_QUERY_RESULT_AVAILABLE                        0x8867
+#define GL_BUFFER_MAPPED                                 0x88BC
+#define GL_BUFFER_MAP_POINTER                            0x88BD
+#define GL_STREAM_READ                                   0x88E1
+#define GL_STREAM_COPY                                   0x88E2
+#define GL_STATIC_READ                                   0x88E5
+#define GL_STATIC_COPY                                   0x88E6
+#define GL_DYNAMIC_READ                                  0x88E9
+#define GL_DYNAMIC_COPY                                  0x88EA
+#define GL_MAX_DRAW_BUFFERS                              0x8824
+#define GL_DRAW_BUFFER0                                  0x8825
+#define GL_DRAW_BUFFER1                                  0x8826
+#define GL_DRAW_BUFFER2                                  0x8827
+#define GL_DRAW_BUFFER3                                  0x8828
+#define GL_DRAW_BUFFER4                                  0x8829
+#define GL_DRAW_BUFFER5                                  0x882A
+#define GL_DRAW_BUFFER6                                  0x882B
+#define GL_DRAW_BUFFER7                                  0x882C
+#define GL_DRAW_BUFFER8                                  0x882D
+#define GL_DRAW_BUFFER9                                  0x882E
+#define GL_DRAW_BUFFER10                                 0x882F
+#define GL_DRAW_BUFFER11                                 0x8830
+#define GL_DRAW_BUFFER12                                 0x8831
+#define GL_DRAW_BUFFER13                                 0x8832
+#define GL_DRAW_BUFFER14                                 0x8833
+#define GL_DRAW_BUFFER15                                 0x8834
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS               0x8B49
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS                 0x8B4A
+#define GL_SAMPLER_3D                                    0x8B5F
+#define GL_SAMPLER_2D_SHADOW                             0x8B62
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT               0x8B8B
+#define GL_PIXEL_PACK_BUFFER                             0x88EB
+#define GL_PIXEL_UNPACK_BUFFER                           0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING                     0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING                   0x88EF
+#define GL_FLOAT_MAT2x3                                  0x8B65
+#define GL_FLOAT_MAT2x4                                  0x8B66
+#define GL_FLOAT_MAT3x2                                  0x8B67
+#define GL_FLOAT_MAT3x4                                  0x8B68
+#define GL_FLOAT_MAT4x2                                  0x8B69
+#define GL_FLOAT_MAT4x3                                  0x8B6A
+#define GL_SRGB                                          0x8C40
+#define GL_SRGB8                                         0x8C41
+#define GL_SRGB8_ALPHA8                                  0x8C43
+#define GL_COMPARE_REF_TO_TEXTURE                        0x884E
+#define GL_MAJOR_VERSION                                 0x821B
+#define GL_MINOR_VERSION                                 0x821C
+#define GL_NUM_EXTENSIONS                                0x821D
+#define GL_RGBA32F                                       0x8814
+#define GL_RGB32F                                        0x8815
+#define GL_RGBA16F                                       0x881A
+#define GL_RGB16F                                        0x881B
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER                   0x88FD
+#define GL_MAX_ARRAY_TEXTURE_LAYERS                      0x88FF
+#define GL_MIN_PROGRAM_TEXEL_OFFSET                      0x8904
+#define GL_MAX_PROGRAM_TEXEL_OFFSET                      0x8905
+#define GL_MAX_VARYING_COMPONENTS                        0x8B4B
+#define GL_TEXTURE_2D_ARRAY                              0x8C1A
+#define GL_TEXTURE_BINDING_2D_ARRAY                      0x8C1D
+#define GL_R11F_G11F_B10F                                0x8C3A
+#define GL_UNSIGNED_INT_10F_11F_11F_REV                  0x8C3B
+#define GL_RGB9_E5                                       0x8C3D
+#define GL_UNSIGNED_INT_5_9_9_9_REV                      0x8C3E
+#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH         0x8C76
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE                0x8C7F
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS    0x8C80
+#define GL_TRANSFORM_FEEDBACK_VARYINGS                   0x8C83
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START               0x8C84
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE                0x8C85
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN         0x8C88
+#define GL_RASTERIZER_DISCARD                            0x8C89
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS       0x8C8B
+#define GL_INTERLEAVED_ATTRIBS                           0x8C8C
+#define GL_SEPARATE_ATTRIBS                              0x8C8D
+#define GL_TRANSFORM_FEEDBACK_BUFFER                     0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING             0x8C8F
+#define GL_RGBA32UI                                      0x8D70
+#define GL_RGB32UI                                       0x8D71
+#define GL_RGBA16UI                                      0x8D76
+#define GL_RGB16UI                                       0x8D77
+#define GL_RGBA8UI                                       0x8D7C
+#define GL_RGB8UI                                        0x8D7D
+#define GL_RGBA32I                                       0x8D82
+#define GL_RGB32I                                        0x8D83
+#define GL_RGBA16I                                       0x8D88
+#define GL_RGB16I                                        0x8D89
+#define GL_RGBA8I                                        0x8D8E
+#define GL_RGB8I                                         0x8D8F
+#define GL_RED_INTEGER                                   0x8D94
+#define GL_RGB_INTEGER                                   0x8D98
+#define GL_RGBA_INTEGER                                  0x8D99
+#define GL_SAMPLER_2D_ARRAY                              0x8DC1
+#define GL_SAMPLER_2D_ARRAY_SHADOW                       0x8DC4
+#define GL_SAMPLER_CUBE_SHADOW                           0x8DC5
+#define GL_UNSIGNED_INT_VEC2                             0x8DC6
+#define GL_UNSIGNED_INT_VEC3                             0x8DC7
+#define GL_UNSIGNED_INT_VEC4                             0x8DC8
+#define GL_INT_SAMPLER_2D                                0x8DCA
+#define GL_INT_SAMPLER_3D                                0x8DCB
+#define GL_INT_SAMPLER_CUBE                              0x8DCC
+#define GL_INT_SAMPLER_2D_ARRAY                          0x8DCF
+#define GL_UNSIGNED_INT_SAMPLER_2D                       0x8DD2
+#define GL_UNSIGNED_INT_SAMPLER_3D                       0x8DD3
+#define GL_UNSIGNED_INT_SAMPLER_CUBE                     0x8DD4
+#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY                 0x8DD7
+#define GL_BUFFER_ACCESS_FLAGS                           0x911F
+#define GL_BUFFER_MAP_LENGTH                             0x9120
+#define GL_BUFFER_MAP_OFFSET                             0x9121
+#define GL_DEPTH_COMPONENT32F                            0x8CAC
+#define GL_DEPTH32F_STENCIL8                             0x8CAD
+#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV                0x8DAD
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING         0x8210
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE         0x8211
+#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE               0x8212
+#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE             0x8213
+#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE              0x8214
+#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE             0x8215
+#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE             0x8216
+#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE           0x8217
+#define GL_FRAMEBUFFER_DEFAULT                           0x8218
+#define GL_FRAMEBUFFER_UNDEFINED                         0x8219
+#define GL_DEPTH_STENCIL_ATTACHMENT                      0x821A
+#define GL_DEPTH_STENCIL                                 0x84F9
+#define GL_UNSIGNED_INT_24_8                             0x84FA
+#define GL_DEPTH24_STENCIL8                              0x88F0
+#define GL_UNSIGNED_NORMALIZED                           0x8C17
+#define GL_DRAW_FRAMEBUFFER_BINDING                      GL_FRAMEBUFFER_BINDING
+#define GL_READ_FRAMEBUFFER                              0x8CA8
+#define GL_DRAW_FRAMEBUFFER                              0x8CA9
+#define GL_READ_FRAMEBUFFER_BINDING                      0x8CAA
+#define GL_RENDERBUFFER_SAMPLES                          0x8CAB
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER          0x8CD4
+#define GL_MAX_COLOR_ATTACHMENTS                         0x8CDF
+#define GL_COLOR_ATTACHMENT1                             0x8CE1
+#define GL_COLOR_ATTACHMENT2                             0x8CE2
+#define GL_COLOR_ATTACHMENT3                             0x8CE3
+#define GL_COLOR_ATTACHMENT4                             0x8CE4
+#define GL_COLOR_ATTACHMENT5                             0x8CE5
+#define GL_COLOR_ATTACHMENT6                             0x8CE6
+#define GL_COLOR_ATTACHMENT7                             0x8CE7
+#define GL_COLOR_ATTACHMENT8                             0x8CE8
+#define GL_COLOR_ATTACHMENT9                             0x8CE9
+#define GL_COLOR_ATTACHMENT10                            0x8CEA
+#define GL_COLOR_ATTACHMENT11                            0x8CEB
+#define GL_COLOR_ATTACHMENT12                            0x8CEC
+#define GL_COLOR_ATTACHMENT13                            0x8CED
+#define GL_COLOR_ATTACHMENT14                            0x8CEE
+#define GL_COLOR_ATTACHMENT15                            0x8CEF
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE            0x8D56
+#define GL_MAX_SAMPLES                                   0x8D57
+#define GL_HALF_FLOAT                                    0x140B
+#define GL_MAP_READ_BIT                                  0x0001
+#define GL_MAP_WRITE_BIT                                 0x0002
+#define GL_MAP_INVALIDATE_RANGE_BIT                      0x0004
+#define GL_MAP_INVALIDATE_BUFFER_BIT                     0x0008
+#define GL_MAP_FLUSH_EXPLICIT_BIT                        0x0010
+#define GL_MAP_UNSYNCHRONIZED_BIT                        0x0020
+#define GL_RG                                            0x8227
+#define GL_RG_INTEGER                                    0x8228
+#define GL_R8                                            0x8229
+#define GL_RG8                                           0x822B
+#define GL_R16F                                          0x822D
+#define GL_R32F                                          0x822E
+#define GL_RG16F                                         0x822F
+#define GL_RG32F                                         0x8230
+#define GL_R8I                                           0x8231
+#define GL_R8UI                                          0x8232
+#define GL_R16I                                          0x8233
+#define GL_R16UI                                         0x8234
+#define GL_R32I                                          0x8235
+#define GL_R32UI                                         0x8236
+#define GL_RG8I                                          0x8237
+#define GL_RG8UI                                         0x8238
+#define GL_RG16I                                         0x8239
+#define GL_RG16UI                                        0x823A
+#define GL_RG32I                                         0x823B
+#define GL_RG32UI                                        0x823C
+#define GL_VERTEX_ARRAY_BINDING                          0x85B5
+#define GL_R8_SNORM                                      0x8F94
+#define GL_RG8_SNORM                                     0x8F95
+#define GL_RGB8_SNORM                                    0x8F96
+#define GL_RGBA8_SNORM                                   0x8F97
+#define GL_SIGNED_NORMALIZED                             0x8F9C
+#define GL_PRIMITIVE_RESTART_FIXED_INDEX                 0x8D69
+#define GL_COPY_READ_BUFFER                              0x8F36
+#define GL_COPY_WRITE_BUFFER                             0x8F37
+#define GL_COPY_READ_BUFFER_BINDING                      GL_COPY_READ_BUFFER
+#define GL_COPY_WRITE_BUFFER_BINDING                     GL_COPY_WRITE_BUFFER
+#define GL_UNIFORM_BUFFER                                0x8A11
+#define GL_UNIFORM_BUFFER_BINDING                        0x8A28
+#define GL_UNIFORM_BUFFER_START                          0x8A29
+#define GL_UNIFORM_BUFFER_SIZE                           0x8A2A
+#define GL_MAX_VERTEX_UNIFORM_BLOCKS                     0x8A2B
+#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS                   0x8A2D
+#define GL_MAX_COMBINED_UNIFORM_BLOCKS                   0x8A2E
+#define GL_MAX_UNIFORM_BUFFER_BINDINGS                   0x8A2F
+#define GL_MAX_UNIFORM_BLOCK_SIZE                        0x8A30
+#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS        0x8A31
+#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS      0x8A33
+#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT               0x8A34
+#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH          0x8A35
+#define GL_ACTIVE_UNIFORM_BLOCKS                         0x8A36
+#define GL_UNIFORM_TYPE                                  0x8A37
+#define GL_UNIFORM_SIZE                                  0x8A38
+#define GL_UNIFORM_NAME_LENGTH                           0x8A39
+#define GL_UNIFORM_BLOCK_INDEX                           0x8A3A
+#define GL_UNIFORM_OFFSET                                0x8A3B
+#define GL_UNIFORM_ARRAY_STRIDE                          0x8A3C
+#define GL_UNIFORM_MATRIX_STRIDE                         0x8A3D
+#define GL_UNIFORM_IS_ROW_MAJOR                          0x8A3E
+#define GL_UNIFORM_BLOCK_BINDING                         0x8A3F
+#define GL_UNIFORM_BLOCK_DATA_SIZE                       0x8A40
+#define GL_UNIFORM_BLOCK_NAME_LENGTH                     0x8A41
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS                 0x8A42
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES          0x8A43
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER     0x8A44
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER   0x8A46
+#define GL_INVALID_INDEX                                 0xFFFFFFFFu
+#define GL_MAX_VERTEX_OUTPUT_COMPONENTS                  0x9122
+#define GL_MAX_FRAGMENT_INPUT_COMPONENTS                 0x9125
+#define GL_MAX_SERVER_WAIT_TIMEOUT                       0x9111
+#define GL_OBJECT_TYPE                                   0x9112
+#define GL_SYNC_CONDITION                                0x9113
+#define GL_SYNC_STATUS                                   0x9114
+#define GL_SYNC_FLAGS                                    0x9115
+#define GL_SYNC_FENCE                                    0x9116
+#define GL_SYNC_GPU_COMMANDS_COMPLETE                    0x9117
+#define GL_UNSIGNALED                                    0x9118
+#define GL_SIGNALED                                      0x9119
+#define GL_ALREADY_SIGNALED                              0x911A
+#define GL_TIMEOUT_EXPIRED                               0x911B
+#define GL_CONDITION_SATISFIED                           0x911C
+#define GL_WAIT_FAILED                                   0x911D
+#define GL_SYNC_FLUSH_COMMANDS_BIT                       0x00000001
+#define GL_TIMEOUT_IGNORED                               0xFFFFFFFFFFFFFFFFull
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR                   0x88FE
+#define GL_ANY_SAMPLES_PASSED                            0x8C2F
+#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE               0x8D6A
+#define GL_SAMPLER_BINDING                               0x8919
+#define GL_RGB10_A2UI                                    0x906F
+#define GL_TEXTURE_SWIZZLE_R                             0x8E42
+#define GL_TEXTURE_SWIZZLE_G                             0x8E43
+#define GL_TEXTURE_SWIZZLE_B                             0x8E44
+#define GL_TEXTURE_SWIZZLE_A                             0x8E45
+#define GL_GREEN                                         0x1904
+#define GL_BLUE                                          0x1905
+#define GL_INT_2_10_10_10_REV                            0x8D9F
+#define GL_TRANSFORM_FEEDBACK                            0x8E22
+#define GL_TRANSFORM_FEEDBACK_PAUSED                     0x8E23
+#define GL_TRANSFORM_FEEDBACK_ACTIVE                     0x8E24
+#define GL_TRANSFORM_FEEDBACK_BINDING                    0x8E25
+#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT               0x8257
+#define GL_PROGRAM_BINARY_LENGTH                         0x8741
+#define GL_NUM_PROGRAM_BINARY_FORMATS                    0x87FE
+#define GL_PROGRAM_BINARY_FORMATS                        0x87FF
+#define GL_COMPRESSED_R11_EAC                            0x9270
+#define GL_COMPRESSED_SIGNED_R11_EAC                     0x9271
+#define GL_COMPRESSED_RG11_EAC                           0x9272
+#define GL_COMPRESSED_SIGNED_RG11_EAC                    0x9273
+#define GL_COMPRESSED_RGB8_ETC2                          0x9274
+#define GL_COMPRESSED_SRGB8_ETC2                         0x9275
+#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2      0x9276
+#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2     0x9277
+#define GL_COMPRESSED_RGBA8_ETC2_EAC                     0x9278
+#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC              0x9279
+#define GL_TEXTURE_IMMUTABLE_FORMAT                      0x912F
+#define GL_MAX_ELEMENT_INDEX                             0x8D6B
+#define GL_NUM_SAMPLE_COUNTS                             0x9380
+#define GL_TEXTURE_IMMUTABLE_LEVELS                      0x82DF
+
+/*-------------------------------------------------------------------------
+ * Entrypoint definitions
+ *-----------------------------------------------------------------------*/
+
+/* OpenGL ES 3.0 */
+
+extern GL_APICALL void           (* GL_APIENTRY glReadBuffer) (GLenum mode);
+extern GL_APICALL void           (* GL_APIENTRY glDrawRangeElements) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices);
+extern GL_APICALL void           (* GL_APIENTRY glTexImage3D) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+extern GL_APICALL void           (* GL_APIENTRY glTexSubImage3D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels);
+extern GL_APICALL void           (* GL_APIENTRY glCopyTexSubImage3D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+extern GL_APICALL void           (* GL_APIENTRY glCompressedTexImage3D) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data);
+extern GL_APICALL void           (* GL_APIENTRY glCompressedTexSubImage3D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data);
+extern GL_APICALL void           (* GL_APIENTRY glGenQueries) (GLsizei n, GLuint* ids);
+extern GL_APICALL void           (* GL_APIENTRY glDeleteQueries) (GLsizei n, const GLuint* ids);
+extern GL_APICALL GLboolean      (* GL_APIENTRY glIsQuery) (GLuint id);
+extern GL_APICALL void           (* GL_APIENTRY glBeginQuery) (GLenum target, GLuint id);
+extern GL_APICALL void           (* GL_APIENTRY glEndQuery) (GLenum target);
+extern GL_APICALL void           (* GL_APIENTRY glGetQueryiv) (GLenum target, GLenum pname, GLint* params);
+extern GL_APICALL void           (* GL_APIENTRY glGetQueryObjectuiv) (GLuint id, GLenum pname, GLuint* params);
+extern GL_APICALL GLboolean      (* GL_APIENTRY glUnmapBuffer) (GLenum target);
+extern GL_APICALL void           (* GL_APIENTRY glGetBufferPointerv) (GLenum target, GLenum pname, GLvoid** params);
+extern GL_APICALL void           (* GL_APIENTRY glDrawBuffers) (GLsizei n, const GLenum* bufs);
+extern GL_APICALL void           (* GL_APIENTRY glUniformMatrix2x3fv) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+extern GL_APICALL void           (* GL_APIENTRY glUniformMatrix3x2fv) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+extern GL_APICALL void           (* GL_APIENTRY glUniformMatrix2x4fv) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+extern GL_APICALL void           (* GL_APIENTRY glUniformMatrix4x2fv) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+extern GL_APICALL void           (* GL_APIENTRY glUniformMatrix3x4fv) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+extern GL_APICALL void           (* GL_APIENTRY glUniformMatrix4x3fv) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+extern GL_APICALL void           (* GL_APIENTRY glBlitFramebuffer) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+extern GL_APICALL void           (* GL_APIENTRY glRenderbufferStorageMultisample) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+extern GL_APICALL void           (* GL_APIENTRY glFramebufferTextureLayer) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+extern GL_APICALL GLvoid*        (* GL_APIENTRY glMapBufferRange) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+extern GL_APICALL void           (* GL_APIENTRY glFlushMappedBufferRange) (GLenum target, GLintptr offset, GLsizeiptr length);
+extern GL_APICALL void           (* GL_APIENTRY glBindVertexArray) (GLuint array);
+extern GL_APICALL void           (* GL_APIENTRY glDeleteVertexArrays) (GLsizei n, const GLuint* arrays);
+extern GL_APICALL void           (* GL_APIENTRY glGenVertexArrays) (GLsizei n, GLuint* arrays);
+extern GL_APICALL GLboolean      (* GL_APIENTRY glIsVertexArray) (GLuint array);
+extern GL_APICALL void           (* GL_APIENTRY glGetIntegeri_v) (GLenum target, GLuint index, GLint* data);
+extern GL_APICALL void           (* GL_APIENTRY glBeginTransformFeedback) (GLenum primitiveMode);
+extern GL_APICALL void           (* GL_APIENTRY glEndTransformFeedback) (void);
+extern GL_APICALL void           (* GL_APIENTRY glBindBufferRange) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+extern GL_APICALL void           (* GL_APIENTRY glBindBufferBase) (GLenum target, GLuint index, GLuint buffer);
+extern GL_APICALL void           (* GL_APIENTRY glTransformFeedbackVaryings) (GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode);
+extern GL_APICALL void           (* GL_APIENTRY glGetTransformFeedbackVarying) (GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name);
+extern GL_APICALL void           (* GL_APIENTRY glVertexAttribIPointer) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer);
+extern GL_APICALL void           (* GL_APIENTRY glGetVertexAttribIiv) (GLuint index, GLenum pname, GLint* params);
+extern GL_APICALL void           (* GL_APIENTRY glGetVertexAttribIuiv) (GLuint index, GLenum pname, GLuint* params);
+extern GL_APICALL void           (* GL_APIENTRY glVertexAttribI4i) (GLuint index, GLint x, GLint y, GLint z, GLint w);
+extern GL_APICALL void           (* GL_APIENTRY glVertexAttribI4ui) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+extern GL_APICALL void           (* GL_APIENTRY glVertexAttribI4iv) (GLuint index, const GLint* v);
+extern GL_APICALL void           (* GL_APIENTRY glVertexAttribI4uiv) (GLuint index, const GLuint* v);
+extern GL_APICALL void           (* GL_APIENTRY glGetUniformuiv) (GLuint program, GLint location, GLuint* params);
+extern GL_APICALL GLint          (* GL_APIENTRY glGetFragDataLocation) (GLuint program, const GLchar *name);
+extern GL_APICALL void           (* GL_APIENTRY glUniform1ui) (GLint location, GLuint v0);
+extern GL_APICALL void           (* GL_APIENTRY glUniform2ui) (GLint location, GLuint v0, GLuint v1);
+extern GL_APICALL void           (* GL_APIENTRY glUniform3ui) (GLint location, GLuint v0, GLuint v1, GLuint v2);
+extern GL_APICALL void           (* GL_APIENTRY glUniform4ui) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+extern GL_APICALL void           (* GL_APIENTRY glUniform1uiv) (GLint location, GLsizei count, const GLuint* value);
+extern GL_APICALL void           (* GL_APIENTRY glUniform2uiv) (GLint location, GLsizei count, const GLuint* value);
+extern GL_APICALL void           (* GL_APIENTRY glUniform3uiv) (GLint location, GLsizei count, const GLuint* value);
+extern GL_APICALL void           (* GL_APIENTRY glUniform4uiv) (GLint location, GLsizei count, const GLuint* value);
+extern GL_APICALL void           (* GL_APIENTRY glClearBufferiv) (GLenum buffer, GLint drawbuffer, const GLint* value);
+extern GL_APICALL void           (* GL_APIENTRY glClearBufferuiv) (GLenum buffer, GLint drawbuffer, const GLuint* value);
+extern GL_APICALL void           (* GL_APIENTRY glClearBufferfv) (GLenum buffer, GLint drawbuffer, const GLfloat* value);
+extern GL_APICALL void           (* GL_APIENTRY glClearBufferfi) (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+extern GL_APICALL const GLubyte* (* GL_APIENTRY glGetStringi) (GLenum name, GLuint index);
+extern GL_APICALL void           (* GL_APIENTRY glCopyBufferSubData) (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+extern GL_APICALL void           (* GL_APIENTRY glGetUniformIndices) (GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices);
+extern GL_APICALL void           (* GL_APIENTRY glGetActiveUniformsiv) (GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params);
+extern GL_APICALL GLuint         (* GL_APIENTRY glGetUniformBlockIndex) (GLuint program, const GLchar* uniformBlockName);
+extern GL_APICALL void           (* GL_APIENTRY glGetActiveUniformBlockiv) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params);
+extern GL_APICALL void           (* GL_APIENTRY glGetActiveUniformBlockName) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName);
+extern GL_APICALL void           (* GL_APIENTRY glUniformBlockBinding) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+extern GL_APICALL void           (* GL_APIENTRY glDrawArraysInstanced) (GLenum mode, GLint first, GLsizei count, GLsizei instanceCount);
+extern GL_APICALL void           (* GL_APIENTRY glDrawElementsInstanced) (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount);
+extern GL_APICALL GLsync         (* GL_APIENTRY glFenceSync) (GLenum condition, GLbitfield flags);
+extern GL_APICALL GLboolean      (* GL_APIENTRY glIsSync) (GLsync sync);
+extern GL_APICALL void           (* GL_APIENTRY glDeleteSync) (GLsync sync);
+extern GL_APICALL GLenum         (* GL_APIENTRY glClientWaitSync) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+extern GL_APICALL void           (* GL_APIENTRY glWaitSync) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+extern GL_APICALL void           (* GL_APIENTRY glGetInteger64v) (GLenum pname, GLint64* params);
+extern GL_APICALL void           (* GL_APIENTRY glGetSynciv) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values);
+extern GL_APICALL void           (* GL_APIENTRY glGetInteger64i_v) (GLenum target, GLuint index, GLint64* data);
+extern GL_APICALL void           (* GL_APIENTRY glGetBufferParameteri64v) (GLenum target, GLenum pname, GLint64* params);
+extern GL_APICALL void           (* GL_APIENTRY glGenSamplers) (GLsizei count, GLuint* samplers);
+extern GL_APICALL void           (* GL_APIENTRY glDeleteSamplers) (GLsizei count, const GLuint* samplers);
+extern GL_APICALL GLboolean      (* GL_APIENTRY glIsSampler) (GLuint sampler);
+extern GL_APICALL void           (* GL_APIENTRY glBindSampler) (GLuint unit, GLuint sampler);
+extern GL_APICALL void           (* GL_APIENTRY glSamplerParameteri) (GLuint sampler, GLenum pname, GLint param);
+extern GL_APICALL void           (* GL_APIENTRY glSamplerParameteriv) (GLuint sampler, GLenum pname, const GLint* param);
+extern GL_APICALL void           (* GL_APIENTRY glSamplerParameterf) (GLuint sampler, GLenum pname, GLfloat param);
+extern GL_APICALL void           (* GL_APIENTRY glSamplerParameterfv) (GLuint sampler, GLenum pname, const GLfloat* param);
+extern GL_APICALL void           (* GL_APIENTRY glGetSamplerParameteriv) (GLuint sampler, GLenum pname, GLint* params);
+extern GL_APICALL void           (* GL_APIENTRY glGetSamplerParameterfv) (GLuint sampler, GLenum pname, GLfloat* params);
+extern GL_APICALL void           (* GL_APIENTRY glVertexAttribDivisor) (GLuint index, GLuint divisor);
+extern GL_APICALL void           (* GL_APIENTRY glBindTransformFeedback) (GLenum target, GLuint id);
+extern GL_APICALL void           (* GL_APIENTRY glDeleteTransformFeedbacks) (GLsizei n, const GLuint* ids);
+extern GL_APICALL void           (* GL_APIENTRY glGenTransformFeedbacks) (GLsizei n, GLuint* ids);
+extern GL_APICALL GLboolean      (* GL_APIENTRY glIsTransformFeedback) (GLuint id);
+extern GL_APICALL void           (* GL_APIENTRY glPauseTransformFeedback) (void);
+extern GL_APICALL void           (* GL_APIENTRY glResumeTransformFeedback) (void);
+extern GL_APICALL void           (* GL_APIENTRY glGetProgramBinary) (GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary);
+extern GL_APICALL void           (* GL_APIENTRY glProgramBinary) (GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length);
+extern GL_APICALL void           (* GL_APIENTRY glProgramParameteri) (GLuint program, GLenum pname, GLint value);
+extern GL_APICALL void           (* GL_APIENTRY glInvalidateFramebuffer) (GLenum target, GLsizei numAttachments, const GLenum* attachments);
+extern GL_APICALL void           (* GL_APIENTRY glInvalidateSubFramebuffer) (GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+extern GL_APICALL void           (* GL_APIENTRY glTexStorage2D) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+extern GL_APICALL void           (* GL_APIENTRY glTexStorage3D) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+extern GL_APICALL void           (* GL_APIENTRY glGetInternalformativ) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ndk/platforms/android-18/samples/gles3jni/jni/gles3jni.cpp b/ndk/platforms/android-18/samples/gles3jni/jni/gles3jni.cpp
new file mode 100644
index 0000000..23f2b05
--- /dev/null
+++ b/ndk/platforms/android-18/samples/gles3jni/jni/gles3jni.cpp
@@ -0,0 +1,284 @@
+/*
+ * Copyright 2013 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.
+ */
+
+#include <jni.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "gles3jni.h"
+
+const Vertex QUAD[4] = {
+    // Square with diagonal < 2 so that it fits in a [-1 .. 1]^2 square
+    // regardless of rotation.
+    {{-0.7f, -0.7f}, {0x00, 0xFF, 0x00}},
+    {{ 0.7f, -0.7f}, {0x00, 0x00, 0xFF}},
+    {{-0.7f,  0.7f}, {0xFF, 0x00, 0x00}},
+    {{ 0.7f,  0.7f}, {0xFF, 0xFF, 0xFF}},
+};
+
+bool checkGlError(const char* funcName) {
+    GLint err = glGetError();
+    if (err != GL_NO_ERROR) {
+        ALOGE("GL error after %s(): 0x%08x\n", funcName, err);
+        return true;
+    }
+    return false;
+}
+
+GLuint createShader(GLenum shaderType, const char* src) {
+    GLuint shader = glCreateShader(shaderType);
+    if (!shader) {
+        checkGlError("glCreateShader");
+        return 0;
+    }
+    glShaderSource(shader, 1, &src, NULL);
+
+    GLint compiled = GL_FALSE;
+    glCompileShader(shader);
+    glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
+    if (!compiled) {
+        GLint infoLogLen = 0;
+        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLen);
+        if (infoLogLen > 0) {
+            GLchar* infoLog = (GLchar*)malloc(infoLogLen);
+            if (infoLog) {
+                glGetShaderInfoLog(shader, infoLogLen, NULL, infoLog);
+                ALOGE("Could not compile %s shader:\n%s\n",
+                        shaderType == GL_VERTEX_SHADER ? "vertex" : "fragment",
+                        infoLog);
+                free(infoLog);
+            }
+        }
+        glDeleteShader(shader);
+        return 0;
+    }
+
+    return shader;
+}
+
+GLuint createProgram(const char* vtxSrc, const char* fragSrc) {
+    GLuint vtxShader = 0;
+    GLuint fragShader = 0;
+    GLuint program = 0;
+    GLint linked = GL_FALSE;
+
+    vtxShader = createShader(GL_VERTEX_SHADER, vtxSrc);
+    if (!vtxShader)
+        goto exit;
+
+    fragShader = createShader(GL_FRAGMENT_SHADER, fragSrc);
+    if (!fragShader)
+        goto exit;
+
+    program = glCreateProgram();
+    if (!program) {
+        checkGlError("glCreateProgram");
+        goto exit;
+    }
+    glAttachShader(program, vtxShader);
+    glAttachShader(program, fragShader);
+
+    glLinkProgram(program);
+    glGetProgramiv(program, GL_LINK_STATUS, &linked);
+    if (!linked) {
+        ALOGE("Could not link program");
+        GLint infoLogLen = 0;
+        glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLen);
+        if (infoLogLen) {
+            GLchar* infoLog = (GLchar*)malloc(infoLogLen);
+            if (infoLog) {
+                glGetProgramInfoLog(program, infoLogLen, NULL, infoLog);
+                ALOGE("Could not link program:\n%s\n", infoLog);
+                free(infoLog);
+            }
+        }
+        glDeleteProgram(program);
+        program = 0;
+    }
+
+exit:
+    glDeleteShader(vtxShader);
+    glDeleteShader(fragShader);
+    return program;
+}
+
+static void printGlString(const char* name, GLenum s) {
+    const char* v = (const char*)glGetString(s);
+    ALOGV("GL %s: %s\n", name, v);
+}
+
+// ----------------------------------------------------------------------------
+
+Renderer::Renderer()
+:   mNumInstances(0),
+    mLastFrameNs(0)
+{
+    memset(mScale, 0, sizeof(mScale));
+    memset(mAngularVelocity, 0, sizeof(mAngularVelocity));
+    memset(mAngles, 0, sizeof(mAngles));
+}
+
+Renderer::~Renderer() {
+}
+
+void Renderer::resize(int w, int h) {
+    float* offsets = mapOffsetBuf();
+    calcSceneParams(w, h, offsets);
+    unmapOffsetBuf();
+
+    for (unsigned int i = 0; i < mNumInstances; i++) {
+        mAngles[i] = drand48() * TWO_PI;
+        mAngularVelocity[i] = MAX_ROT_SPEED * (2.0*drand48() - 1.0);
+    }
+
+    mLastFrameNs = 0;
+
+    glViewport(0, 0, w, h);
+}
+
+void Renderer::calcSceneParams(unsigned int w, unsigned int h,
+        float* offsets) {
+    // number of cells along the larger screen dimension
+    const float NCELLS_MAJOR = MAX_INSTANCES_PER_SIDE;
+    // cell size in scene space
+    const float CELL_SIZE = 2.0f / NCELLS_MAJOR;
+
+    // Calculations are done in "landscape", i.e. assuming dim[0] >= dim[1].
+    // Only at the end are values put in the opposite order if h > w.
+    const float dim[2] = {fmaxf(w,h), fminf(w,h)};
+    const float aspect[2] = {dim[0] / dim[1], dim[1] / dim[0]};
+    const float scene2clip[2] = {1.0f, aspect[0]};
+    const int ncells[2] = {
+            NCELLS_MAJOR,
+            (int)floorf(NCELLS_MAJOR * aspect[1])
+    };
+
+    float centers[2][MAX_INSTANCES_PER_SIDE];
+    for (int d = 0; d < 2; d++) {
+        float offset = -ncells[d] / NCELLS_MAJOR; // -1.0 for d=0
+        for (int i = 0; i < ncells[d]; i++) {
+            centers[d][i] = scene2clip[d] * (CELL_SIZE*(i + 0.5f) + offset);
+        }
+    }
+
+    int major = w >= h ? 0 : 1;
+    int minor = w >= h ? 1 : 0;
+    // outer product of centers[0] and centers[1]
+    for (int i = 0; i < ncells[0]; i++) {
+        for (int j = 0; j < ncells[1]; j++) {
+            int idx = i*ncells[1] + j;
+            offsets[2*idx + major] = centers[0][i];
+            offsets[2*idx + minor] = centers[1][j];
+        }
+    }
+
+    mNumInstances = ncells[0] * ncells[1];
+    mScale[major] = 0.5f * CELL_SIZE * scene2clip[0];
+    mScale[minor] = 0.5f * CELL_SIZE * scene2clip[1];
+}
+
+void Renderer::step() {
+    timespec now;
+    clock_gettime(CLOCK_MONOTONIC, &now);
+    uint64_t nowNs = now.tv_sec*1000000000ull + now.tv_nsec;
+
+    if (mLastFrameNs > 0) {
+        float dt = float(nowNs - mLastFrameNs) * 0.000000001f;
+
+        for (unsigned int i = 0; i < mNumInstances; i++) {
+            mAngles[i] += mAngularVelocity[i] * dt;
+            if (mAngles[i] >= TWO_PI) {
+                mAngles[i] -= TWO_PI;
+            } else if (mAngles[i] <= -TWO_PI) {
+                mAngles[i] += TWO_PI;
+            }
+        }
+
+        float* transforms = mapTransformBuf();
+        for (unsigned int i = 0; i < mNumInstances; i++) {
+            float s = sinf(mAngles[i]);
+            float c = cosf(mAngles[i]);
+            transforms[4*i + 0] =  c * mScale[0];
+            transforms[4*i + 1] =  s * mScale[1];
+            transforms[4*i + 2] = -s * mScale[0];
+            transforms[4*i + 3] =  c * mScale[1];
+        }
+        unmapTransformBuf();
+    }
+
+    mLastFrameNs = nowNs;
+}
+
+void Renderer::render() {
+    step();
+
+    glClearColor(0.2f, 0.2f, 0.3f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+    draw(mNumInstances);
+    checkGlError("Renderer::render");
+}
+
+// ----------------------------------------------------------------------------
+
+static Renderer* g_renderer = NULL;
+
+extern "C" {
+    JNIEXPORT void JNICALL Java_com_android_gles3jni_GLES3JNILib_init(JNIEnv* env, jobject obj);
+    JNIEXPORT void JNICALL Java_com_android_gles3jni_GLES3JNILib_resize(JNIEnv* env, jobject obj, jint width, jint height);
+    JNIEXPORT void JNICALL Java_com_android_gles3jni_GLES3JNILib_step(JNIEnv* env, jobject obj);
+};
+
+#if !defined(DYNAMIC_ES3)
+static GLboolean gl3stubInit() {
+    return GL_TRUE;
+}
+#endif
+
+JNIEXPORT void JNICALL
+Java_com_android_gles3jni_GLES3JNILib_init(JNIEnv* env, jobject obj) {
+    if (g_renderer) {
+        delete g_renderer;
+        g_renderer = NULL;
+    }
+
+    printGlString("Version", GL_VERSION);
+    printGlString("Vendor", GL_VENDOR);
+    printGlString("Renderer", GL_RENDERER);
+    printGlString("Extensions", GL_EXTENSIONS);
+
+    const char* versionStr = (const char*)glGetString(GL_VERSION);
+    if (strstr(versionStr, "OpenGL ES 3.") && gl3stubInit()) {
+        g_renderer = createES3Renderer();
+    } else if (strstr(versionStr, "OpenGL ES 2.")) {
+        g_renderer = createES2Renderer();
+    } else {
+        ALOGE("Unsupported OpenGL ES version");
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_com_android_gles3jni_GLES3JNILib_resize(JNIEnv* env, jobject obj, jint width, jint height) {
+    if (g_renderer) {
+        g_renderer->resize(width, height);
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_com_android_gles3jni_GLES3JNILib_step(JNIEnv* env, jobject obj) {
+    if (g_renderer) {
+        g_renderer->render();
+    }
+}
diff --git a/ndk/platforms/android-18/samples/gles3jni/jni/gles3jni.h b/ndk/platforms/android-18/samples/gles3jni/jni/gles3jni.h
new file mode 100644
index 0000000..dde779c
--- /dev/null
+++ b/ndk/platforms/android-18/samples/gles3jni/jni/gles3jni.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2013 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.
+ */
+
+#ifndef GLES3JNI_H
+#define GLES3JNI_H 1
+
+#include <android/log.h>
+#include <math.h>
+
+#if DYNAMIC_ES3
+#include "gl3stub.h"
+#else
+#include <GLES3/gl3.h>
+#endif
+
+#define DEBUG 1
+
+#define LOG_TAG "GLES3JNI"
+#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
+#if DEBUG
+#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
+#else
+#define ALOGV(...)
+#endif
+
+// ----------------------------------------------------------------------------
+// Types, functions, and data used by both ES2 and ES3 renderers.
+// Defined in gles3jni.cpp.
+
+#define MAX_INSTANCES_PER_SIDE 16
+#define MAX_INSTANCES   (MAX_INSTANCES_PER_SIDE * MAX_INSTANCES_PER_SIDE)
+#define TWO_PI          (2.0 * M_PI)
+#define MAX_ROT_SPEED   (0.3 * TWO_PI)
+
+// This demo uses three coordinate spaces:
+// - The model (a quad) is in a [-1 .. 1]^2 space
+// - Scene space is either
+//    landscape: [-1 .. 1] x [-1/(2*w/h) .. 1/(2*w/h)]
+//    portrait:  [-1/(2*h/w) .. 1/(2*h/w)] x [-1 .. 1]
+// - Clip space in OpenGL is [-1 .. 1]^2
+//
+// Conceptually, the quads are rotated in model space, then scaled (uniformly)
+// and translated to place them in scene space. Scene space is then
+// non-uniformly scaled to clip space. In practice the transforms are combined
+// so vertices go directly from model to clip space.
+
+struct Vertex {
+    GLfloat pos[2];
+    GLubyte rgba[4];
+};
+extern const Vertex QUAD[4];
+
+// returns true if a GL error occurred
+extern bool checkGlError(const char* funcName);
+extern GLuint createShader(GLenum shaderType, const char* src);
+extern GLuint createProgram(const char* vtxSrc, const char* fragSrc);
+
+// ----------------------------------------------------------------------------
+// Interface to the ES2 and ES3 renderers, used by JNI code.
+
+class Renderer {
+public:
+    virtual ~Renderer();
+    void resize(int w, int h);
+    void render();
+
+protected:
+    Renderer();
+
+    // return a pointer to a buffer of MAX_INSTANCES * sizeof(vec2).
+    // the buffer is filled with per-instance offsets, then unmapped.
+    virtual float* mapOffsetBuf() = 0;
+    virtual void unmapOffsetBuf() = 0;
+    // return a pointer to a buffer of MAX_INSTANCES * sizeof(vec4).
+    // the buffer is filled with per-instance scale and rotation transforms.
+    virtual float* mapTransformBuf() = 0;
+    virtual void unmapTransformBuf() = 0;
+
+    virtual void draw(unsigned int numInstances) = 0;
+
+private:
+    void calcSceneParams(unsigned int w, unsigned int h, float* offsets);
+    void step();
+
+    unsigned int mNumInstances;
+    float mScale[2];
+    float mAngularVelocity[MAX_INSTANCES];
+    uint64_t mLastFrameNs;
+    float mAngles[MAX_INSTANCES];
+};
+
+extern Renderer* createES2Renderer();
+extern Renderer* createES3Renderer();
+
+#endif // GLES3JNI_H
diff --git a/ndk/platforms/android-18/samples/gles3jni/res/values/strings.xml b/ndk/platforms/android-18/samples/gles3jni/res/values/strings.xml
new file mode 100644
index 0000000..375efc6
--- /dev/null
+++ b/ndk/platforms/android-18/samples/gles3jni/res/values/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 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.
+-->
+
+<!-- This file contains resource definitions for displayed strings, allowing
+     them to be changed based on the locale and options. -->
+
+<resources>
+    <!-- Simple strings. -->
+    <string name="gles3jni_activity">GLES3JNI</string>
+
+</resources>
diff --git a/ndk/platforms/android-18/samples/gles3jni/src/com/android/gles3jni/GLES3JNIActivity.java b/ndk/platforms/android-18/samples/gles3jni/src/com/android/gles3jni/GLES3JNIActivity.java
new file mode 100644
index 0000000..5427418
--- /dev/null
+++ b/ndk/platforms/android-18/samples/gles3jni/src/com/android/gles3jni/GLES3JNIActivity.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2013 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.gles3jni;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.WindowManager;
+
+import java.io.File;
+
+public class GLES3JNIActivity extends Activity {
+
+    GLES3JNIView mView;
+
+    @Override protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        mView = new GLES3JNIView(getApplication());
+        setContentView(mView);
+    }
+
+    @Override protected void onPause() {
+        super.onPause();
+        mView.onPause();
+    }
+
+    @Override protected void onResume() {
+        super.onResume();
+        mView.onResume();
+    }
+}
diff --git a/ndk/platforms/android-18/samples/gles3jni/src/com/android/gles3jni/GLES3JNILib.java b/ndk/platforms/android-18/samples/gles3jni/src/com/android/gles3jni/GLES3JNILib.java
new file mode 100644
index 0000000..811658f
--- /dev/null
+++ b/ndk/platforms/android-18/samples/gles3jni/src/com/android/gles3jni/GLES3JNILib.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2013 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.gles3jni;
+
+// Wrapper for native library
+
+public class GLES3JNILib {
+
+     static {
+         System.loadLibrary("gles3jni");
+     }
+
+     public static native void init();
+     public static native void resize(int width, int height);
+     public static native void step();
+}
diff --git a/ndk/platforms/android-18/samples/gles3jni/src/com/android/gles3jni/GLES3JNIView.java b/ndk/platforms/android-18/samples/gles3jni/src/com/android/gles3jni/GLES3JNIView.java
new file mode 100644
index 0000000..12624fd
--- /dev/null
+++ b/ndk/platforms/android-18/samples/gles3jni/src/com/android/gles3jni/GLES3JNIView.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2013 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.gles3jni;
+
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.opengl.GLSurfaceView;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.egl.EGLContext;
+import javax.microedition.khronos.egl.EGLDisplay;
+import javax.microedition.khronos.opengles.GL10;
+
+class GLES3JNIView extends GLSurfaceView {
+    private static final String TAG = "GLES3JNI";
+    private static final boolean DEBUG = true;
+
+    public GLES3JNIView(Context context) {
+        super(context);
+        // Pick an EGLConfig with RGB8 color, 16-bit depth, no stencil,
+        // supporting OpenGL ES 2.0 or later backwards-compatible versions.
+        setEGLConfigChooser(8, 8, 8, 0, 16, 0);
+        setEGLContextClientVersion(2);
+        setRenderer(new Renderer());
+    }
+
+    private static class Renderer implements GLSurfaceView.Renderer {
+        public void onDrawFrame(GL10 gl) {
+            GLES3JNILib.step();
+        }
+
+        public void onSurfaceChanged(GL10 gl, int width, int height) {
+            GLES3JNILib.resize(width, height);
+        }
+
+        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+            GLES3JNILib.init();
+        }
+    }
+}
diff --git a/ndk/platforms/android-3/include/inttypes.h b/ndk/platforms/android-3/include/inttypes.h
index 81d2315..73b22db 100644
--- a/ndk/platforms/android-3/include/inttypes.h
+++ b/ndk/platforms/android-3/include/inttypes.h
@@ -56,7 +56,7 @@
 #define	PRIdFAST64		"lld"		/* int_fast64_t */
 
 #define	PRIdMAX			"jd"		/* intmax_t */
-#define	PRIdPTR			"ld"		/* intptr_t */
+#define	PRIdPTR			"d"		/* intptr_t */
 
 #define	PRIi8			"i"		/* int8_t */
 #define	PRIi16			"i"		/* int16_t */
@@ -74,7 +74,7 @@
 #define	PRIiFAST64		"lli"		/* int_fast64_t */
 
 #define	PRIiMAX			"ji"		/* intmax_t */
-#define	PRIiPTR			"li"		/* intptr_t */
+#define	PRIiPTR			"i"		/* intptr_t */
 
 /* fprintf macros for unsigned integers */
 #define	PRIo8			"o"		/* int8_t */
@@ -93,7 +93,7 @@
 #define	PRIoFAST64		"llo"		/* int_fast64_t */
 
 #define	PRIoMAX			"jo"		/* intmax_t */
-#define	PRIoPTR			"lo"		/* intptr_t */
+#define	PRIoPTR			"o"		/* intptr_t */
 
 #define	PRIu8			"u"		/* uint8_t */
 #define	PRIu16			"u"		/* uint16_t */
@@ -111,7 +111,7 @@
 #define	PRIuFAST64		"llu"		/* uint_fast64_t */
 
 #define	PRIuMAX			"ju"		/* uintmax_t */
-#define	PRIuPTR			"lu"		/* uintptr_t */
+#define	PRIuPTR			"u"		/* uintptr_t */
 
 #define	PRIx8			"x"		/* uint8_t */
 #define	PRIx16			"x"		/* uint16_t */
@@ -129,7 +129,7 @@
 #define	PRIxFAST64		"llx"		/* uint_fast64_t */
 
 #define	PRIxMAX			"jx"		/* uintmax_t */
-#define	PRIxPTR			"lx"		/* uintptr_t */
+#define	PRIxPTR			"x"		/* uintptr_t */
 
 #define	PRIX8			"X"		/* uint8_t */
 #define	PRIX16			"X"		/* uint16_t */
@@ -147,7 +147,7 @@
 #define	PRIXFAST64		"llX"		/* uint_fast64_t */
 
 #define	PRIXMAX			"jX"		/* uintmax_t */
-#define	PRIXPTR			"lX"		/* uintptr_t */
+#define	PRIXPTR			"X"		/* uintptr_t */
 
 /* fscanf macros for signed integers */
 #define	SCNd8			"hhd"		/* int8_t */
@@ -166,7 +166,7 @@
 #define	SCNdFAST64		"lld"		/* int_fast64_t */
 
 #define	SCNdMAX			"jd"		/* intmax_t */
-#define	SCNdPTR			"ld"		/* intptr_t */
+#define	SCNdPTR			"d"		/* intptr_t */
 
 #define	SCNi8			"hhi"		/* int8_t */
 #define	SCNi16			"hi"		/* int16_t */
@@ -184,7 +184,7 @@
 #define	SCNiFAST64		"lli"		/* int_fast64_t */
 
 #define	SCNiMAX			"ji"		/* intmax_t */
-#define	SCNiPTR			"li"		/* intptr_t */
+#define	SCNiPTR			"i"		/* intptr_t */
 
 /* fscanf macros for unsigned integers */
 #define	SCNo8			"hho"		/* uint8_t */
@@ -203,7 +203,7 @@
 #define	SCNoFAST64		"llo"		/* uint_fast64_t */
 
 #define	SCNoMAX			"jo"		/* uintmax_t */
-#define	SCNoPTR			"lo"		/* uintptr_t */
+#define	SCNoPTR			"o"		/* uintptr_t */
 
 #define	SCNu8			"hhu"		/* uint8_t */
 #define	SCNu16			"hu"		/* uint16_t */
@@ -221,7 +221,7 @@
 #define	SCNuFAST64		"llu"		/* uint_fast64_t */
 
 #define	SCNuMAX			"ju"		/* uintmax_t */
-#define	SCNuPTR			"lu"		/* uintptr_t */
+#define	SCNuPTR			"u"		/* uintptr_t */
 
 #define	SCNx8			"hhx"		/* uint8_t */
 #define	SCNx16			"hx"		/* uint16_t */
@@ -239,7 +239,7 @@
 #define	SCNxFAST64		"llx"		/* uint_fast64_t */
 
 #define	SCNxMAX			"jx"		/* uintmax_t */
-#define	SCNxPTR			"lx"		/* uintptr_t */
+#define	SCNxPTR			"x"		/* uintptr_t */
 
 #endif /* __cplusplus || __STDC_FORMAT_MACROS */
 
diff --git a/ndk/platforms/android-3/include/malloc.h b/ndk/platforms/android-3/include/malloc.h
index ec21926..49a10e6 100644
--- a/ndk/platforms/android-3/include/malloc.h
+++ b/ndk/platforms/android-3/include/malloc.h
@@ -33,7 +33,7 @@
 extern void   free(void *);
 
 extern void*  memalign(size_t  alignment, size_t  bytesize);
-extern size_t malloc_usable_size(void*);
+extern size_t malloc_usable_size(const void*);
 
 extern void*  valloc(size_t  bytesize);
 extern void*  pvalloc(size_t bytesize);
diff --git a/ndk/platforms/android-3/include/netinet/tcp.h b/ndk/platforms/android-3/include/netinet/tcp.h
index 9adf904..bc52249 100644
--- a/ndk/platforms/android-3/include/netinet/tcp.h
+++ b/ndk/platforms/android-3/include/netinet/tcp.h
@@ -31,4 +31,22 @@
 #include <endian.h>		/* Include *before* linux/tcp.h */
 #include <linux/tcp.h>
 
+__BEGIN_DECLS
+
+enum {
+  TCP_ESTABLISHED = 1,
+  TCP_SYN_SENT,
+  TCP_SYN_RECV,
+  TCP_FIN_WAIT1,
+  TCP_FIN_WAIT2,
+  TCP_TIME_WAIT,
+  TCP_CLOSE,
+  TCP_CLOSE_WAIT,
+  TCP_LAST_ACK,
+  TCP_LISTEN,
+  TCP_CLOSING
+};
+
+__END_DECLS
+
 #endif /* _NETINET_TCP_H */
diff --git a/ndk/platforms/android-3/include/stdint.h b/ndk/platforms/android-3/include/stdint.h
index c3e29dd..44613d5 100644
--- a/ndk/platforms/android-3/include/stdint.h
+++ b/ndk/platforms/android-3/include/stdint.h
@@ -66,7 +66,7 @@
 #  define INT_FAST8_MIN    INT8_MIN
 #  define INT_FAST8_MAX    INT8_MAX
 
-#  define UINT8_MAX           (255U)
+#  define UINT8_MAX           (255)
 #  define UINT_LEAST8_MAX     UINT8_MAX
 #  define UINT_FAST8_MAX      UINT8_MAX
 #endif
@@ -76,7 +76,7 @@
 #  define INT_LEAST8_C(c)	 INT8_C(c)
 #  define INT_FAST8_C(c)	INT8_C(c)
 
-#  define UINT8_C(c)	c ## U
+#  define UINT8_C(c)	c
 #  define UINT_LEAST8_C(c)  UINT8_C(c)
 #  define UINT_FAST8_C(c)  UINT8_C(c)
 #endif
@@ -99,7 +99,7 @@
 #  define INT_FAST16_MIN	INT32_MIN
 #  define INT_FAST16_MAX	INT32_MAX
 
-#  define UINT16_MAX	(65535U)
+#  define UINT16_MAX	(65535)
 #  define UINT_LEAST16_MAX UINT16_MAX
 #  define UINT_FAST16_MAX UINT32_MAX
 #endif
@@ -109,7 +109,7 @@
 #  define INT_LEAST16_C(c) INT16_C(c)
 #  define INT_FAST16_C(c)	 INT32_C(c)
 
-#  define UINT16_C(c)	c ## U
+#  define UINT16_C(c)	c
 #  define UINT_LEAST16_C(c) UINT16_C(c)
 #  define UINT_FAST16_C(c) UINT32_C(c)
 #endif
@@ -226,6 +226,29 @@
 #  define UINTMAX_C(c)	UINT64_C(c)
 #endif
 
+/* Limits of sig_atomic_t. */
+#ifdef __STDINT_LIMITS
+#  define SIG_ATOMIC_MIN  INT32_MIN
+#  define SIG_ATOMIC_MAX  INT32_MAX
+#endif
+
+/* Limits of wchar_t. */
+#ifdef __STDINT_LIMITS
+#include <sys/_wchar_limits.h>
+#endif
+
+/* Limits of wint_t. */
+#ifdef __STDINT_LIMITS
+#  define WINT_MIN        INT32_MIN
+#  define WINT_MAX        INT32_MAX
+#endif
+
+/* size_t is defined by the GCC-specific <stddef.h> */
+#ifndef _SSIZE_T_DEFINED_
+#define _SSIZE_T_DEFINED_
+typedef long int  ssize_t;
+#endif
+
 #define _BITSIZE 32
 
 /* Keep the kernel from trying to define these types... */
diff --git a/ndk/platforms/android-3/include/sys/_wchar_limits.h b/ndk/platforms/android-3/include/sys/_wchar_limits.h
new file mode 100644
index 0000000..644792f
--- /dev/null
+++ b/ndk/platforms/android-3/include/sys/_wchar_limits.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef _SYS__WCHAR_LIMITS_H
+#define _SYS__WCHAR_LIMITS_H
+
+#include <android/api-level.h>
+
+/* WCHAR_MIN / WCHAR_MAX can be defined by <stdint.h> or <wchar.h>.
+ * Due to historical reasons, their definition is a bit complex.
+ *
+ * - In NDK r8e and older, all definitions of WCHAR_MIN and WCHAR_MAX
+ *   where 32-bit signed values (with one exception described below),
+ *   despite the fact that wchar_t is 'unsigned' on ARM.
+ *   See http://b.android.com/57749
+ *
+ *   This is no longer the case, unless you define _WCHAR_IS_ALWAYS_SIGNED
+ *   at compile time to restore the old (broken) behaviour. This doesn't
+ *   affect other CPU ABIs.
+ *
+ * - Before API level 9, on ARM, wchar_t was typedef to 'char' when
+ *   compiling C (not C++). Also, the definitions of WCHAR_MIN and
+ *   WCHAR_MAX differed between <stdint.h> and <wchar.h>:
+ *
+ *     <stdint.h> conditionally defined them to INT32_MIN / INT32_MAX.
+ *     <wchar.h> conditionally defined them to 0 and 255 instead.
+ *
+ *   <stdint.h> would only define WCHAR_MIN and WCHAR_MAX when:
+ *    - Compiling C sources.
+ *    - Compiling C++ sources with __STDC_LIMIT_MACROS being defined.
+ *
+ *   <wchar.h> always ends up including <stdint.h> indirectly. This
+ *   means that:
+ *
+ *     - When compiling C sources, WCHAR_MIN / WCHAR_MAX were always
+ *       defined as INT32_MIN / INT32_MAX.
+ *
+ *     - When compiling C++ sources with __STDC_LIMIT_MACROS defined,
+ *       they were always defined to INT32_MIN / INT32_MAX
+ *
+ *     - When compiling C++ sources without __STDC_LIMIT_MACROS defined,
+ *       they were defined by <wchar.h> as 0 and 255, respectively.
+ *
+ *    Keep in mind that this was ARM-specific, only for API level < 9.
+ *
+ *    If _WCHAR_IS_8BIT is defined, the same broken behaviour will
+ *    be restored. See http://b.android.com/57267
+ */ 
+#if !defined(WCHAR_MIN)
+
+#  if defined(_WCHAR_IS_8BIT) && defined(__arm__) && __ANDROID_API__ < 9
+#    if defined(__cplusplus) && !defined(__STDC_LIMIT_MACROS)
+#      define WCHAR_MIN  0
+#      define WCHAR_MAX  255
+#    else
+#      define WCHAR_MIN   (-2147483647 - 1)
+#      define WCHAR_MAX   (2147483647)
+#    endif
+#  elif defined(_WCHAR_IS_ALWAYS_SIGNED)
+#    define WCHAR_MIN   (-2147483647 - 1)
+#    define WCHAR_MAX   (2147483647)
+#  else
+  /* Otherwise, the value is derived from the toolchain configuration.
+   * to avoid putting explicit CPU checks in this header. */
+#    ifndef __WCHAR_MAX__
+#      error "__WCHAR_MAX__ is not defined. Check your toolchain!"
+#    endif
+  /* Clang does define __WCHAR_MAX__, but not __WCHAR_MIN__ */
+#    ifndef __WCHAR_MIN__
+#      if __WCHAR_MAX__ == 4294967295
+#        define __WCHAR_MIN__  (0U)
+#      elif __WCHAR_MAX__ == 2147483647
+#        define __WCHAR_MIN__  (-2147483647 - 1)
+#      else
+#        error "Invalid __WCHAR_MAX__ value. Check your toolchain!"
+#      endif
+#    endif /* !__WCHAR_MIN__ */
+#    define WCHAR_MIN    __WCHAR_MIN__
+#    define WCHAR_MAX    __WCHAR_MAX__
+#  endif /* !_WCHAR_IS_ALWAYS_SIGNED */
+
+#endif /* !WCHAR_MIN */
+
+#endif  /* _SYS__WCHAR_LIMITS_H */
diff --git a/ndk/platforms/android-3/include/sys/cdefs.h b/ndk/platforms/android-3/include/sys/cdefs.h
index 27c575c..88ce720 100644
--- a/ndk/platforms/android-3/include/sys/cdefs.h
+++ b/ndk/platforms/android-3/include/sys/cdefs.h
@@ -37,11 +37,36 @@
 #ifndef	_SYS_CDEFS_H_
 #define	_SYS_CDEFS_H_
 
-
-/* our implementation of wchar_t is only 8-bit - die die non-portable code */
+/* In previous NDK releases, wchar_t was defined as 'unsigned char'
+ * when targetting API level < 9 (i.e. Froyo or older).
+ *
+ * This is no longer the case, but you can define _WCHAR_IS_8BIT
+ * at compile time to restore the old behaviour.
+ *
+ * The reason for this redefine is purely historical. Until Android 2.3,
+ * i.e. API level 9, there was absolutely no official support for wchar_t
+ * in the C library, but compiling GCC and the GNU libstdc++ required a
+ * working <wchar.h>.
+ *
+ * To allow this while keeping the C library small, wchar_t was redefined
+ * explicitely as an 8-bit unsigned integer (which is perfectly allowed
+ * by the standard) and a very small set of wcs-xxx functions provided
+ * as wrappers around the corresponding str-xxx ones.
+ *
+ * Starting with API level 9, wchar_t is properly defined as a 32-bit
+ * type (as mandated by the compiler itself), and the lines below
+ * were removed (see $NDK/platforms/android-9/include/sys/cdefs.h).
+ *
+ * Note that this only affects C source compilation. For C++, wchar_t
+ * is a compiler keyboard that cannot be redefined and is always 32-bit.
+ *
+ * On the other hand, _WCHAR_IS_8BIT also affects the definition of
+ * WCHAR_MIN, WCHAR_MAX and WEOF (see <wchar.h> comments).
+ */
+#ifdef _WCHAR_IS_8BIT
 #undef  __WCHAR_TYPE__
 #define __WCHAR_TYPE__  unsigned char
-
+#endif
 
 /*
  * Macro to test if we're using a GNU C compiler of a specific vintage
diff --git a/ndk/platforms/android-3/include/wchar.h b/ndk/platforms/android-3/include/wchar.h
index 9a6ce1d..575da4d 100644
--- a/ndk/platforms/android-3/include/wchar.h
+++ b/ndk/platforms/android-3/include/wchar.h
@@ -40,6 +40,7 @@
 #include <malloc.h>
 
 #include <stddef.h>
+#include <sys/_wchar_limits.h>
 
 /* IMPORTANT: Any code that relies on wide character support is essentially
  *            non-portable and/or broken. the only reason this header exist
@@ -70,9 +71,15 @@
     WC_TYPE_MAX
 } wctype_t;
 
-#define  WCHAR_MAX   255
-#define  WCHAR_MIN   0
+/* WEOF used to be defined as simply -1, which is
+ * invalid (the standard mandates that the expression must have wint_t
+ * type). Revert to the old broken behaviour is _WCHAR_IS_8BIT is defined.
+ * See http://b.android.com/57267 */
+#ifdef _WCHAR_IS_8BIT
 #define  WEOF        (-1)
+#else
+#define  WEOF        ((wint_t)-1)
+#endif
 
 extern wint_t            btowc(int);
 extern int               fwprintf(FILE *, const wchar_t *, ...);
diff --git a/ndk/platforms/android-8/include/wchar.h b/ndk/platforms/android-8/include/wchar.h
index b9c7b0b..453b6d5 100644
--- a/ndk/platforms/android-8/include/wchar.h
+++ b/ndk/platforms/android-8/include/wchar.h
@@ -40,6 +40,7 @@
 #include <malloc.h>
 
 #include <stddef.h>
+#include <sys/_wchar_limits.h>
 
 /* IMPORTANT: Any code that relies on wide character support is essentially
  *            non-portable and/or broken. the only reason this header exist
@@ -70,9 +71,20 @@
     WC_TYPE_MAX
 } wctype_t;
 
-#define  WCHAR_MAX   255
-#define  WCHAR_MIN   0
+/* WEOF used to be defined as simply -1, which is
+ * invalid (the standard mandates that the expression must have wint_t
+ * type). Revert to the old broken behaviour is _WCHAR_IS_8BIT is defined.
+ * See http://b.android.com/57267 */
+#ifdef _WCHAR_IS_8BIT
 #define  WEOF        (-1)
+#else
+#define  WEOF        ((wint_t)-1)
+#endif
+#ifdef _WCHAR_IS_8BIT
+#define  WEOF        (-1)
+#else
+#define  WEOF        ((wint_t)-1)
+#endif
 
 extern wint_t            btowc(int);
 extern int               fwprintf(FILE *, const wchar_t *, ...);
diff --git a/ndk/platforms/android-9/arch-x86/lib/libc.a b/ndk/platforms/android-9/arch-x86/lib/libc.a
index 29b1726..788b92e 100644
--- a/ndk/platforms/android-9/arch-x86/lib/libc.a
+++ b/ndk/platforms/android-9/arch-x86/lib/libc.a
Binary files differ
diff --git a/ndk/platforms/android-9/arch-x86/src/__stack_chk_fail_local.h b/ndk/platforms/android-9/arch-x86/src/__stack_chk_fail_local.h
new file mode 100644
index 0000000..4f3699a
--- /dev/null
+++ b/ndk/platforms/android-9/arch-x86/src/__stack_chk_fail_local.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+/*
+   __stack_chk_fail routine is runtime part of stack protector compiler
+   feature. It's implemented in libc and represents die routine when stack
+   corruption is detected.
+
+   Calls are generated by compiler and injected into user functions when
+   -fstack-protector* options are used.
+
+   __stack_chk_fail_local is wrapper for __stack_chk_fail. Compiler generates
+   wrapper calls instead for PIC code only and only on IA32 for optimization
+   purpose (see gcc/config/i386/i386.c). Wrapper body is always included into
+   executable or library. This is the idea of optimization.
+
+   Glibc is doing this via libc_nonshared.a which is linked automatically
+   everytime with libc.so. In bionic we have to bring it within crtfiles
+   because libc.so is real library and not a link script like libc.so at glibc.
+
+   For x86_64 or non-PIC code compiler always generates __stack_chk_fail calls.
+*/
+
+#ifdef __i386__
+#ifdef __PIC__
+extern void __stack_chk_fail();
+
+__attribute__ ((visibility ("hidden")))
+void __stack_chk_fail_local()
+{
+  __stack_chk_fail();
+}
+#endif
+#endif
diff --git a/ndk/platforms/android-9/arch-x86/src/atexit.S b/ndk/platforms/android-9/arch-x86/src/atexit.S
deleted file mode 100644
index b28f40b..0000000
--- a/ndk/platforms/android-9/arch-x86/src/atexit.S
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-	.text
-	.p2align 4,,15
-	.globl	atexit
-	.hidden	atexit
-	.type	atexit, @function
-atexit:
-	pushl	%ebp
-	movl	%esp, %ebp
-	pushl	%ebx
-	call	__x86.get_pc_thunk.bx
-	addl	$_GLOBAL_OFFSET_TABLE_, %ebx
-	subl	$20, %esp
-	movl	$0, 4(%esp)
-	movl	__dso_handle@GOTOFF(%ebx), %eax
-	movl	%eax, 8(%esp)
-	movl	8(%ebp), %eax
-	movl	%eax, (%esp)
-	call	__cxa_atexit@PLT
-	addl	$20, %esp
-	popl	%ebx
-	popl	%ebp
-	ret
-	.size	atexit, .-atexit
-
-	.section	.text.__x86.get_pc_thunk.bx,"axG",@progbits,__x86.get_pc_thunk.bx,comdat
-	.globl	__x86.get_pc_thunk.bx
-	.hidden	__x86.get_pc_thunk.bx
-	.type	__x86.get_pc_thunk.bx, @function
-__x86.get_pc_thunk.bx:
-	nop
-	nop
-	nop
-	nop
-	nop
-	nop
-	nop
-	nop
-	movl	(%esp), %ebx
-	ret
diff --git a/ndk/platforms/android-9/arch-x86/src/__stack_chk_fail_local.S b/ndk/platforms/android-9/arch-x86/src/atexit.h
similarity index 73%
rename from ndk/platforms/android-9/arch-x86/src/__stack_chk_fail_local.S
rename to ndk/platforms/android-9/arch-x86/src/atexit.h
index 59fe86e..bc776a8 100644
--- a/ndk/platforms/android-9/arch-x86/src/__stack_chk_fail_local.S
+++ b/ndk/platforms/android-9/arch-x86/src/atexit.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2012 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -25,24 +25,11 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-/*
- * Contributed by: Intel Corporation
- */
 
-	.text
-	.p2align 4,,15
-	.globl	__stack_chk_fail_local
-	.hidden	__stack_chk_fail_local
-	.type	__stack_chk_fail_local, @function
+extern void *__dso_handle;
 
-__stack_chk_fail_local:
-#ifdef __PIC__
-	pushl	%ebx
-	call	__x86.get_pc_thunk.bx
-	addl	$_GLOBAL_OFFSET_TABLE_, %ebx
-	call	__stack_chk_fail@PLT
-#else /* PIC */
-	jmp   __stack_chk_fail
-#endif /* not PIC */
-
-	.size	__stack_chk_fail_local, .-__stack_chk_fail_local
+__attribute__ ((visibility ("hidden")))
+int atexit(void (*func)(void))
+{
+  return (__cxa_atexit((void (*)(void *))func, (void *)0, &__dso_handle));
+}
diff --git a/ndk/platforms/android-9/arch-x86/src/__stack_chk_fail_local.S b/ndk/platforms/android-9/arch-x86/src/crtbegin.c
similarity index 60%
copy from ndk/platforms/android-9/arch-x86/src/__stack_chk_fail_local.S
copy to ndk/platforms/android-9/arch-x86/src/crtbegin.c
index 59fe86e..43e9306 100644
--- a/ndk/platforms/android-9/arch-x86/src/__stack_chk_fail_local.S
+++ b/ndk/platforms/android-9/arch-x86/src/crtbegin.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2012 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -25,24 +25,32 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-/*
- * Contributed by: Intel Corporation
- */
 
-	.text
-	.p2align 4,,15
-	.globl	__stack_chk_fail_local
-	.hidden	__stack_chk_fail_local
-	.type	__stack_chk_fail_local, @function
+#include "../../bionic/libc_init_common.h"
+#include <stddef.h>
+#include <stdint.h>
 
-__stack_chk_fail_local:
-#ifdef __PIC__
-	pushl	%ebx
-	call	__x86.get_pc_thunk.bx
-	addl	$_GLOBAL_OFFSET_TABLE_, %ebx
-	call	__stack_chk_fail@PLT
-#else /* PIC */
-	jmp   __stack_chk_fail
-#endif /* not PIC */
+__attribute__ ((section (".preinit_array")))
+void (*__PREINIT_ARRAY__)(void) = (void (*)(void)) -1;
 
-	.size	__stack_chk_fail_local, .-__stack_chk_fail_local
+__attribute__ ((section (".init_array")))
+void (*__INIT_ARRAY__)(void) = (void (*)(void)) -1;
+
+__attribute__ ((section (".fini_array")))
+void (*__FINI_ARRAY__)(void) = (void (*)(void)) -1;
+
+__LIBC_HIDDEN__
+__attribute__((force_align_arg_pointer))
+void _start() {
+  structors_array_t array;
+  array.preinit_array = &__PREINIT_ARRAY__;
+  array.init_array = &__INIT_ARRAY__;
+  array.fini_array = &__FINI_ARRAY__;
+
+  void* raw_args = (void*) ((uintptr_t) __builtin_frame_address(0) + sizeof(void*));
+  __libc_init(raw_args, NULL, &main, &array);
+}
+
+#include "__dso_handle.h"
+#include "atexit.h"
+#include "__stack_chk_fail_local.h"
diff --git a/ndk/platforms/android-9/arch-x86/src/crtbegin_dynamic.S b/ndk/platforms/android-9/arch-x86/src/crtbegin_dynamic.S
deleted file mode 100644
index 0ccad70..0000000
--- a/ndk/platforms/android-9/arch-x86/src/crtbegin_dynamic.S
+++ /dev/null
@@ -1,138 +0,0 @@
-# bionic/arch-x86/bionic/crtbegin_dynamic.S
-#
-# Copyright 2006, The Android Open Source Project
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#     * Redistributions of source code must retain the above copyright
-#       notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above copyright
-#       notice, this list of conditions and the following disclaimer in the
-#       documentation and/or other materials provided with the distribution.
-#     * Neither the name of Google Inc. nor the names of its contributors may
-#       be used to endorse or promote products derived from this software
-#       without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR 
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 
-# EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
-# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
-# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
-# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-	.text
-	.align 4
-	.type _start, @function
-	.globl _start
-
-# this is the small startup code that is first run when
-# any executable that is dynamically-linked with Bionic
-# runs.
-#
-# it's purpose is to call __libc_init with appropriate
-# arguments, which are:
-#
-#    - the address of the raw data block setup by the Linux
-#      kernel ELF loader
-#
-#    - address of an "onexit" function, not used on any
-#      platform supported by Bionic
-#
-#    - address of the "main" function of the program. We
-#      can't hard-code it in the adr pseudo instruction
-#      so we use a tiny trampoline that will get relocated
-#      by the dynamic linker before this code runs
-#
-#    - address of the constructor list
-#
-_start:	
-        mov     %esp, %eax
-        # before push arguments, align the stack to a 16 byte boundary
-        andl    $~15, %esp
-        mov     $1f, %edx
-        pushl   %edx
-        mov     $0f, %edx
-        pushl   %edx
-        mov     $0, %edx
-        pushl   %edx
-        pushl   %eax
-        call    __libc_init
-
-0:  jmp   main
-
-1:  .long   __PREINIT_ARRAY__
-    .long   __INIT_ARRAY__
-    .long   __FINI_ARRAY__
-
-	.section .preinit_array, "aw"
-	.globl __PREINIT_ARRAY__
-__PREINIT_ARRAY__:
-	.long -1
-
-	.section .init_array, "aw"
-	.globl __INIT_ARRAY__
-__INIT_ARRAY__:
-	.long -1
-	.long	frame_dummy
-
-	.section .fini_array, "aw"
-	.globl __FINI_ARRAY__
-__FINI_ARRAY__:
-	.long -1
-	.long	__do_global_dtors_aux
-
-	.section	.eh_frame,"a",@progbits
-	.align 4
-	.type	__EH_FRAME_BEGIN__, @object
-__EH_FRAME_BEGIN__:
-	.text
-	.p2align 4,,15
-	.type	__do_global_dtors_aux, @function
-__do_global_dtors_aux:
-	pushl	%ebp
-	movl	%esp, %ebp
-	subl	$24, %esp
-	cmpb	$0, completed.4454
-	jne	.L4
-	movl	$__deregister_frame_info_bases, %eax
-	testl	%eax, %eax
-	je	.L3
-	movl	$__EH_FRAME_BEGIN__, (%esp)
-	call	__deregister_frame_info_bases
-.L3:
-	movb	$1, completed.4454
-.L4:
-	leave
-	ret
-	.text
-	.p2align 4,,15
-	.type	frame_dummy, @function
-frame_dummy:
-	pushl	%ebp
-	movl	$__register_frame_info_bases, %eax
-	movl	%esp, %ebp
-	subl	$24, %esp
-	testl	%eax, %eax
-	je	.L7
-	movl	%ebx, 12(%esp)
-	movl	$0, 8(%esp)
-	movl	$object.4466, 4(%esp)
-	movl	$__EH_FRAME_BEGIN__, (%esp)
-	call	__register_frame_info_bases
-.L7:
-	leave
-	ret
-	.local	completed.4454
-	.comm	completed.4454,1,1
-	.local	object.4466
-	.comm	object.4466,24,4
-	.weak	__register_frame_info_bases
-	.weak	__deregister_frame_info_bases
-
-#include "__dso_handle.S"
-#include "atexit.S"
-#include "__stack_chk_fail_local.S"
diff --git a/ndk/platforms/android-9/arch-x86/src/crtbegin_so.S b/ndk/platforms/android-9/arch-x86/src/crtbegin_so.S
deleted file mode 100644
index 99662fe..0000000
--- a/ndk/platforms/android-9/arch-x86/src/crtbegin_so.S
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-.section .init_array, "aw"
-.align 4
-.type __INIT_ARRAY__, @object
-.globl __INIT_ARRAY__
-__INIT_ARRAY__:
-    .long -1
-    .long frame_dummy
-
-.section .fini_array, "aw"
-.align 4
-.type __FINI_ARRAY__, @object
-.globl __FINI_ARRAY__
-__FINI_ARRAY__:
-    .long -1
-    .long __do_global_dtors_aux
-
-	.section	.eh_frame,"a",@progbits
-	.align 4
-	.type	__EH_FRAME_BEGIN__, @object
-__EH_FRAME_BEGIN__:
-	.text
-	.p2align 4,,15
-	.type	__do_global_dtors_aux, @function
-__do_global_dtors_aux:
-	pushl	%ebp
-	movl	%esp, %ebp
-	pushl	%ebx
-	call	__x86.get_pc_thunk.bx
-	addl	$_GLOBAL_OFFSET_TABLE_, %ebx
-	subl	$20, %esp
-	cmpb	$0, completed.4454@GOTOFF(%ebx)
-	jne	.L5
-	movl	__dso_handle@GOTOFF(%ebx), %eax
-	movl	%eax, (%esp)
-	call	__cxa_finalize@PLT
-	movl	__deregister_frame_info_bases@GOT(%ebx), %eax
-	testl	%eax, %eax
-	je	.L4
-	leal	__EH_FRAME_BEGIN__@GOTOFF(%ebx), %eax
-	movl	%eax, (%esp)
-	call	__deregister_frame_info_bases@PLT
-.L4:
-	movb	$1, completed.4454@GOTOFF(%ebx)
-.L5:
-	addl	$20, %esp
-	popl	%ebx
-	popl	%ebp
-	ret
-	.text
-	.p2align 4,,15
-	.type	frame_dummy, @function
-frame_dummy:
-	pushl	%ebp
-	movl	%esp, %ebp
-	pushl	%ebx
-	call	__x86.get_pc_thunk.bx
-	addl	$_GLOBAL_OFFSET_TABLE_, %ebx
-	subl	$20, %esp
-	movl	__register_frame_info_bases@GOT(%ebx), %eax
-	testl	%eax, %eax
-	je	.L8
-	leal	object.4469@GOTOFF(%ebx), %eax
-	movl	%eax, 4(%esp)
-	leal	__EH_FRAME_BEGIN__@GOTOFF(%ebx), %eax
-	movl	%ebx, 12(%esp)
-	movl	$0, 8(%esp)
-	movl	%eax, (%esp)
-	call	__register_frame_info_bases@PLT
-.L8:
-	addl	$20, %esp
-	popl	%ebx
-	popl	%ebp
-	ret
-	.local	completed.4454
-	.comm	completed.4454,1,1
-	.local	object.4469
-	.comm	object.4469,24,4
-	.weak	__register_frame_info_bases
-	.weak	__deregister_frame_info_bases
-
-#include "__dso_handle_so.S"
-#include "atexit.S"
-#include "__stack_chk_fail_local.S"
diff --git a/ndk/platforms/android-9/arch-x86/src/crtbegin_so.c b/ndk/platforms/android-9/arch-x86/src/crtbegin_so.c
new file mode 100644
index 0000000..30de6af
--- /dev/null
+++ b/ndk/platforms/android-9/arch-x86/src/crtbegin_so.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+extern void __cxa_finalize(void *);
+extern void *__dso_handle;
+
+__attribute__((visibility("hidden"),destructor))
+void __on_dlclose() {
+  __cxa_finalize(&__dso_handle);
+}
+
+/* CRT_LEGACY_WORKAROUND should only be defined when building
+ * this file as part of the platform's C library.
+ *
+ * The C library already defines a function named 'atexit()'
+ * for backwards compatibility with older NDK-generated binaries.
+ *
+ * For newer ones, 'atexit' is actually embedded in the C
+ * runtime objects that are linked into the final ELF
+ * binary (shared library or executable), and will call
+ * __cxa_atexit() in order to un-register any atexit()
+ * handler when a library is unloaded.
+ *
+ * This function must be global *and* hidden. Only the
+ * code inside the same ELF binary should be able to access it.
+ */
+
+#ifdef CRT_LEGACY_WORKAROUND
+#include "__dso_handle.h"
+#else
+#include "__dso_handle_so.h"
+#include "atexit.h"
+#include "__stack_chk_fail_local.h"
+#endif
diff --git a/ndk/platforms/android-9/arch-x86/src/crtbegin_static.S b/ndk/platforms/android-9/arch-x86/src/crtbegin_static.S
deleted file mode 100644
index 4fffecd..0000000
--- a/ndk/platforms/android-9/arch-x86/src/crtbegin_static.S
+++ /dev/null
@@ -1,138 +0,0 @@
-# bionic/arch-x86/bionic/crtbegin_static.S
-#
-# Copyright 2006, The Android Open Source Project
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#     * Redistributions of source code must retain the above copyright
-#       notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above copyright
-#       notice, this list of conditions and the following disclaimer in the
-#       documentation and/or other materials provided with the distribution.
-#     * Neither the name of Google Inc. nor the names of its contributors may
-#       be used to endorse or promote products derived from this software
-#       without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR 
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 
-# EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
-# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
-# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
-# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-	.text
-	.align 4
-	.type _start, @function
-	.globl _start
-
-# this is the small startup code that is first run when
-# any executable that is statically-linked with Bionic
-# runs.
-#
-# it's purpose is to call __libc_init with appropriate
-# arguments, which are:
-#
-#    - the address of the raw data block setup by the Linux
-#      kernel ELF loader
-#
-#    - address of an "onexit" function, not used on any
-#      platform supported by Bionic
-#
-#    - address of the "main" function of the program. We
-#      can't hard-code it in the adr pseudo instruction
-#      so we use a tiny trampoline that will get relocated
-#      by the dynamic linker before this code runs
-#
-#    - address of the constructor list
-#
-_start:	
-        mov     %esp, %eax
-        # before push arguments, align the stack to a 16 byte boundary
-        andl    $~15, %esp
-        mov     $1f, %edx
-        pushl   %edx
-        mov     $0f, %edx
-        pushl   %edx
-        mov     $0, %edx
-        pushl   %edx
-        pushl   %eax
-        call    __libc_init
-
-0:  jmp   main
-
-1:  .long   __PREINIT_ARRAY__
-    .long   __INIT_ARRAY__
-    .long   __FINI_ARRAY__
-
-	.section .preinit_array, "aw"
-	.globl __PREINIT_ARRAY__
-__PREINIT_ARRAY__:
-	.long -1
-
-	.section .init_array, "aw"
-	.globl __INIT_ARRAY__
-__INIT_ARRAY__:
-	.long -1
-	.long	frame_dummy
-
-	.section .fini_array, "aw"
-	.globl __FINI_ARRAY__
-__FINI_ARRAY__:
-	.long -1
-	.long	__do_global_dtors_aux
-
-	.section	.eh_frame,"a",@progbits
-	.align 4
-	.type	__EH_FRAME_BEGIN__, @object
-__EH_FRAME_BEGIN__:
-	.text
-	.p2align 4,,15
-	.type	__do_global_dtors_aux, @function
-__do_global_dtors_aux:
-	pushl	%ebp
-	movl	%esp, %ebp
-	subl	$24, %esp
-	cmpb	$0, completed.4454
-	jne	.L4
-	movl	$__deregister_frame_info_bases, %eax
-	testl	%eax, %eax
-	je	.L3
-	movl	$__EH_FRAME_BEGIN__, (%esp)
-	call	__deregister_frame_info_bases
-.L3:
-	movb	$1, completed.4454
-.L4:
-	leave
-	ret
-	.text
-	.p2align 4,,15
-	.type	frame_dummy, @function
-frame_dummy:
-	pushl	%ebp
-	movl	$__register_frame_info_bases, %eax
-	movl	%esp, %ebp
-	subl	$24, %esp
-	testl	%eax, %eax
-	je	.L7
-	movl	%ebx, 12(%esp)
-	movl	$0, 8(%esp)
-	movl	$object.4466, 4(%esp)
-	movl	$__EH_FRAME_BEGIN__, (%esp)
-	call	__register_frame_info_bases
-.L7:
-	leave
-	ret
-	.local	completed.4454
-	.comm	completed.4454,1,1
-	.local	object.4466
-	.comm	object.4466,24,4
-	.weak	__register_frame_info_bases
-	.weak	__deregister_frame_info_bases
-
-#include "__dso_handle.S"
-#include "atexit.S"
-#include "__stack_chk_fail_local.S"
diff --git a/ndk/platforms/android-9/arch-x86/symbols/libc.so.functions.txt b/ndk/platforms/android-9/arch-x86/symbols/libc.so.functions.txt
index 2c7a608..2a77c44 100644
--- a/ndk/platforms/android-9/arch-x86/symbols/libc.so.functions.txt
+++ b/ndk/platforms/android-9/arch-x86/symbols/libc.so.functions.txt
@@ -264,6 +264,7 @@
 clock_gettime
 clock_nanosleep
 clock_settime
+clone
 close
 closedir
 closelog
diff --git a/ndk/platforms/android-9/arch-x86_64 b/ndk/platforms/android-9/arch-x86_64
new file mode 120000
index 0000000..fb7033c
--- /dev/null
+++ b/ndk/platforms/android-9/arch-x86_64
@@ -0,0 +1 @@
+arch-x86
\ No newline at end of file
diff --git a/ndk/platforms/android-9/include/wchar.h b/ndk/platforms/android-9/include/wchar.h
index fea648c..806e3d1 100644
--- a/ndk/platforms/android-9/include/wchar.h
+++ b/ndk/platforms/android-9/include/wchar.h
@@ -41,13 +41,7 @@
 #include <malloc.h>
 
 #include <stddef.h>
-
-/* IMPORTANT: Any code that relies on wide character support is essentially
- *            non-portable and/or broken. the only reason this header exist
- *            is because I'm really a nice guy. However, I'm not nice enough
- *            to provide you with a real implementation. instead wchar_t == char
- *            and all wc functions are stubs to their "normal" equivalent...
- */
+#include <sys/_wchar_limits.h>
 
 __BEGIN_DECLS
 
@@ -71,8 +65,6 @@
     WC_TYPE_MAX
 } wctype_t;
 
-#define  WCHAR_MAX   INT_MAX
-#define  WCHAR_MIN   INT_MIN
 #define  WEOF        ((wint_t)(-1))
 
 extern wint_t            btowc(int);
diff --git a/ndk/sources/android/libportable/arch-mips/pthread.c b/ndk/sources/android/libportable/arch-mips/pthread.c
index 41d9478..5b75623 100644
--- a/ndk/sources/android/libportable/arch-mips/pthread.c
+++ b/ndk/sources/android/libportable/arch-mips/pthread.c
@@ -288,13 +288,14 @@
 int WRAP(pthread_sigmask)(int portable_how, const sigset_portable_t *portable_sigset,
                              sigset_portable_t *portable_oldset)
 {
+    extern int REAL(pthread_sigmask)(int how, const sigset_t *set, sigset_t *oset);
     int portable_ret, ret;
 
     ALOGV(" ");
     ALOGV("%s(portable_how:%d portable_sigset:%p, portable_oldset:%p)", __func__,
               portable_how,   portable_sigset,    portable_oldset);
 
-    ret = do_sigmask(portable_how, portable_sigset, portable_oldset, pthread_sigmask, NULL);
+    ret = do_sigmask(portable_how, portable_sigset, portable_oldset, REAL(pthread_sigmask), NULL);
 
     portable_ret = errno_ntop(ret);
 
diff --git a/ndk/sources/android/libportable/arch-mips/signal.c b/ndk/sources/android/libportable/arch-mips/signal.c
index c1befd6..a06eff7 100644
--- a/ndk/sources/android/libportable/arch-mips/signal.c
+++ b/ndk/sources/android/libportable/arch-mips/signal.c
@@ -745,6 +745,7 @@
  */
 sighandler_portable_t WRAP(signal)(int portable_signum, sighandler_portable_t handler)
 {
+    extern __sighandler_t REAL(bsd_signal)(int, __sighandler_t);
     sighandler_portable_t rv;
 
     ALOGV(" ");
@@ -752,7 +753,7 @@
               portable_signum,    handler);
 
     /* bsd does a SA_RESTART */
-    rv = do_signal_portable(portable_signum, handler, bsd_signal);
+    rv = do_signal_portable(portable_signum, handler, REAL(bsd_signal));
 
     ALOGV("%s: return(ret:%p); }", __func__, rv);
     return rv;
@@ -761,6 +762,7 @@
 
 sighandler_portable_t WRAP(sysv_signal)(int portable_signum, sighandler_portable_t handler)
 {
+    extern __sighandler_t REAL(sysv_signal)(int, __sighandler_t);
     sighandler_portable_t rv;
 
     ALOGV(" ");
@@ -768,7 +770,7 @@
               portable_signum,    handler);
 
     /* sysv does a SA_RESETHAND */
-    rv = do_signal_portable(portable_signum, handler, sysv_signal);
+    rv = do_signal_portable(portable_signum, handler, REAL(sysv_signal));
 
     ALOGV("%s: return(ret:%p); }", __func__, rv);
     return rv;
@@ -785,6 +787,7 @@
 
 sighandler_portable_t WRAP(bsd_signal)(int portable_signum, sighandler_portable_t handler)
 {
+    extern __sighandler_t REAL(bsd_signal)(int, __sighandler_t);
     sighandler_portable_t rv;
 
     ALOGV(" ");
@@ -792,7 +795,7 @@
               portable_signum,    handler);
 
     /* bsd does a SA_RESTART */
-    rv = do_signal_portable(portable_signum, handler, bsd_signal);
+    rv = do_signal_portable(portable_signum, handler, REAL(bsd_signal));
 
     ALOGV("%s: return(ret:%p); }", __func__, rv);
     return rv;
diff --git a/ndk/sources/android/libportable/arch-mips/waitpid.c b/ndk/sources/android/libportable/arch-mips/waitpid.c
index bbf0a8a..f1d2bcf 100644
--- a/ndk/sources/android/libportable/arch-mips/waitpid.c
+++ b/ndk/sources/android/libportable/arch-mips/waitpid.c
@@ -104,6 +104,11 @@
     return rv;
 }
 
+// FIXME: WORKAROUND after Android wait4 has been implemented
+pid_t REAL(wait4)(pid_t p, int *s, int o, struct rusage *r) {
+  extern pid_t  __wait4(pid_t, int *, int, struct rusage *);
+  return __wait4(p,s,o,r);
+}
 
 pid_t WRAP(wait4)(pid_t pid, int *status, int options, struct rusage *rusage)
 {
diff --git a/ndk/tools/headers-diff-bionic-vs-ndk.py b/ndk/tools/headers-diff-bionic-vs-ndk.py
new file mode 100755
index 0000000..1f8a9e3
--- /dev/null
+++ b/ndk/tools/headers-diff-bionic-vs-ndk.py
@@ -0,0 +1,248 @@
+#!/usr/bin/python
+#
+# This tool is used to compare headers between Bionic and NDK
+# script should be in development/ndk/tools for correct roots autodetection
+#
+
+import sys, os, os.path
+import subprocess
+import argparse, textwrap
+
+class FileCollector:
+    """Collect headers from Bionic and sysroot
+
+    sysincludes data format:
+    sysincludes                     -- dict with arch as key
+    sysincludes[arch]               -- dict with includes root as key
+    sysincludes[arch][root]         -- dict with header name as key
+    sysincludes[arch][root][header] -- list [last_platform, ..., first_platform]
+    """
+
+    def __init__(self, platforms_root, archs):
+        """Init platform roots and structures before collecting"""
+        self.platforms = []
+        self.archs = archs
+        self.sysincludes = {}
+        for arch in self.archs:
+            self.sysincludes[arch] = {}
+
+        ## scaning available platforms ##
+        for dirname in os.listdir(platforms_root):
+            path = os.path.join(platforms_root, dirname)
+            if os.path.isdir(path) and ('android' in dirname):
+                self.platforms.append(dirname)
+        try:
+            self.platforms.sort(key = lambda s: int(s.split('-')[1]))
+            self.root = platforms_root
+        except Exception:
+            print 'Wrong platforms list \n{0}'.format(str(self.platforms))
+
+    def scan_dir(self, root):
+        """Non-recursive file scan in directory"""
+        files = []
+        for filename in os.listdir(root):
+            if os.path.isfile(os.path.join(root, filename)):
+                files.append(filename)
+        return files
+
+    def scan_includes(self, root):
+        """Recursive includes scan in given root"""
+        includes = []
+        includes_root = os.path.join(root, 'include')
+        if not os.path.isdir(includes_root):
+            return includes
+
+        ## recursive scanning ##
+        includes.append(('', self.scan_dir(includes_root)))
+        for dirname, dirnames, filenames in os.walk(includes_root):
+            for subdirname in dirnames:
+                path = os.path.join(dirname, subdirname)
+                relpath = os.path.relpath(path, includes_root)
+                includes.append((relpath, self.scan_dir(path)))
+
+        return includes
+
+    def scan_archs_includes(self, root):
+        """Scan includes for all defined archs in given root"""
+        includes = {}
+        includes['common'] = self.scan_includes(root)
+
+        for arch in [a for a in self.archs if a != 'common']:
+            arch_root = os.path.join(root, arch)
+            includes[arch] = self.scan_includes(arch_root)
+
+        return includes
+
+    def scan_platform_includes(self, platform):
+        """Scan all platform includes of one layer"""
+        platform_root = os.path.join(self.root, platform)
+        return self.scan_archs_includes(platform_root)
+
+    def scan_bionic_includes(self, bionic_root):
+        """Scan Bionic's libc includes"""
+        self.bionic_root = bionic_root
+        self.bionic_includes = self.scan_archs_includes(bionic_root)
+
+    def append_sysincludes(self, arch, root, headers, platform):
+        """Merge new platform includes layer with current sysincludes"""
+        if not (root in self.sysincludes[arch]):
+            self.sysincludes[arch][root] = {}
+
+        for include in headers:
+            if include in self.sysincludes[arch][root]:
+                last_platform = self.sysincludes[arch][root][include][0]
+                if platform != last_platform:
+                    self.sysincludes[arch][root][include].insert(0, platform)
+            else:
+                self.sysincludes[arch][root][include] = [platform]
+
+    def update_to_platform(self, platform):
+        """Update sysincludes state by applying new platform layer"""
+        new_includes = self.scan_platform_includes(platform)
+        for arch in self.archs:
+            for pack in new_includes[arch]:
+                self.append_sysincludes(arch, pack[0], pack[1], platform)
+
+    def scan_sysincludes(self, target_platform):
+        """Fully automated sysincludes collector upto specified platform"""
+        version = int(target_platform.split('-')[1])
+        layers = filter(lambda s: int(s.split('-')[1]) <= version, self.platforms)
+        for platform in layers:
+            self.update_to_platform(platform)
+
+
+class BionicSysincludes:
+    def set_roots(self):
+        """Automated roots initialization (AOSP oriented)"""
+        script_root = os.path.dirname(os.path.realpath(__file__))
+        self.aosp_root      = os.path.normpath(os.path.join(script_root, '../../..'))
+        self.platforms_root = os.path.join(self.aosp_root, 'development/ndk/platforms')
+        self.bionic_root    = os.path.join(self.aosp_root, 'bionic/libc')
+
+    def scan_includes(self):
+        """Scan all required includes"""
+        self.collector = FileCollector(self.platforms_root, self.archs)
+        ## detecting latest platform ##
+        self.platforms = self.collector.platforms
+        latest_platform = self.platforms[-1:][0]
+        ## scanning both includes repositories ##
+        self.collector.scan_sysincludes(latest_platform)
+        self.collector.scan_bionic_includes(self.bionic_root)
+        ## scan results ##
+        self.sysincludes     = self.collector.sysincludes
+        self.bionic_includes = self.collector.bionic_includes
+
+    def git_diff(self, file_origin, file_probe):
+        """Difference routine based on git diff"""
+        try:
+            subprocess.check_output(['git', 'diff', '--no-index', file_origin, file_probe])
+        except subprocess.CalledProcessError as error:
+            return error.output
+        return None
+
+    def match_with_bionic_includes(self):
+        """Compare headers between Bionic and sysroot"""
+        self.diffs = {}
+        ## for every arch ##
+        for arch in self.archs:
+            arch_root = (lambda s: s if s != 'common' else '')(arch)
+            ## for every includes directory ##
+            for pack in self.bionic_includes[arch]:
+                root = pack[0]
+                path_bionic = os.path.join(self.bionic_root, arch_root, 'include', root)
+                ## for every header that both in Bionic and sysroot ##
+                for include in pack[1]:
+                    if include in self.sysincludes[arch][root]:
+                        ## completing paths ##
+                        platform = self.sysincludes[arch][root][include][0]
+                        file_origin = os.path.join(path_bionic, include)
+                        file_probe  = os.path.join(self.platforms_root, platform, arch_root, 'include', root, include)
+                        ## comparison by git diff ##
+                        output = self.git_diff(file_origin, file_probe)
+                        if output is not None:
+                            if arch not in self.diffs:
+                                self.diffs[arch] = {}
+                            if root not in self.diffs[arch]:
+                                self.diffs[arch][root] = {}
+                            ## storing git diff ##
+                            self.diffs[arch][root][include] = output
+
+    def print_history(self, arch, root, header):
+        """Print human-readable list header updates across platforms"""
+        history = self.sysincludes[arch][root][header]
+        for platform in self.platforms:
+            entry = (lambda s: s.split('-')[1] if s in history else '-')(platform)
+            print '{0:3}'.format(entry),
+        print ''
+
+    def show_and_store_results(self):
+        """Print summary list of headers and write diff-report to file"""
+        try:
+            diff_fd = open(self.diff_file, 'w')
+            for arch in self.archs:
+                if arch not in self.diffs:
+                    continue
+                print '{0}/'.format(arch)
+                roots = self.diffs[arch].keys()
+                roots.sort()
+                for root in roots:
+                    print '    {0}/'.format((lambda s: s if s != '' else '../include')(root))
+                    includes = self.diffs[arch][root].keys()
+                    includes.sort()
+                    for include in includes:
+                        print '        {0:32}'.format(include),
+                        self.print_history(arch, root, include)
+                        diff = self.diffs[arch][root][include]
+                        diff_fd.write(diff)
+                        diff_fd.write('\n\n')
+                    print ''
+                print ''
+
+        finally:
+            diff_fd.close()
+
+    def main(self):
+        self.set_roots()
+        self.scan_includes()
+        self.match_with_bionic_includes()
+        self.show_and_store_results()
+
+if __name__ == '__main__':
+    ## configuring command line parser ##
+    parser = argparse.ArgumentParser(formatter_class = argparse.RawTextHelpFormatter,
+                                     description = 'Headers comparison tool between bionic and NDK platforms')
+    parser.epilog = textwrap.dedent('''
+    output format:
+    {architecture}/
+        {directory}/
+            {header name}.h  {platforms history}
+
+    platforms history format:
+        number X means header has been changed in android-X
+        `-\' means it is the same
+
+    diff-report format:
+        git diff output for all headers
+        use --diff option to specify filename
+    ''')
+
+    parser.add_argument('--archs', metavar = 'A', nargs = '+',
+                        default = ['common', 'arm', 'x86', 'mips'],
+                        help = 'list of architectures\n(default: common arm x86 mips)')
+    parser.add_argument('--diff', metavar = 'FILE', nargs = 1,
+                        default = ['headers-diff-bionic-vs-ndk.diff'],
+                        help = 'diff-report filename\n(default: `bionic-vs-sysincludes_report.diff\')')
+
+    ## parsing arguments ##
+    args = parser.parse_args()
+
+    ## doing work ##
+    app = BionicSysincludes()
+    app.archs = map((lambda s: 'arch-{0}'.format(s) if s != 'common' else s), args.archs)
+    app.diff_file = args.diff[0]
+    app.main()
+
+    print 'Headers listed above are DIFFERENT in Bionic and NDK platforms'
+    print 'See `{0}\' for details'.format(app.diff_file)
+    print 'See --help for format description.'
+    print ''
diff --git a/samples/ApiDemos/AndroidManifest.xml b/samples/ApiDemos/AndroidManifest.xml
index 12abc14..608220a 100644
--- a/samples/ApiDemos/AndroidManifest.xml
+++ b/samples/ApiDemos/AndroidManifest.xml
@@ -1005,6 +1005,13 @@
         </receiver>
 <!-- END_INCLUDE(app_update_declaration) -->
 
+        <receiver android:name=".app.AppUpdateSspReceiver">
+            <intent-filter>
+                <action android:name="android.intent.action.PACKAGE_REPLACED" />
+                <data android:scheme="package" android:ssp="com.example.android.apis" />
+            </intent-filter>
+        </receiver>
+
         <!-- ************************************* -->
         <!--       PREFERENCE PACKAGE SAMPLES      -->
         <!-- ************************************* -->
diff --git a/samples/ApiDemos/res/layout/date_widgets_example_1.xml b/samples/ApiDemos/res/layout/date_widgets_example_1.xml
index b9db6a0..9313cdf 100644
--- a/samples/ApiDemos/res/layout/date_widgets_example_1.xml
+++ b/samples/ApiDemos/res/layout/date_widgets_example_1.xml
@@ -32,9 +32,14 @@
             android:layout_height="wrap_content"
             android:text="@string/date_widgets_example_pickDate_text"/>
 
-    <Button android:id="@+id/pickTime"
+    <Button android:id="@+id/pickTime12"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:text="@string/date_widgets_example_pickTime_text"/>
+            android:text="@string/date_widgets_example_pickTime12_text"/>
+
+    <Button android:id="@+id/pickTime24"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/date_widgets_example_pickTime24_text"/>
 
 </LinearLayout>
diff --git a/samples/ApiDemos/res/layout/intents.xml b/samples/ApiDemos/res/layout/intents.xml
index aed709d..e301b0b 100644
--- a/samples/ApiDemos/res/layout/intents.xml
+++ b/samples/ApiDemos/res/layout/intents.xml
@@ -17,7 +17,8 @@
 <!-- Demonstrates launching various intents.
      See corresponding Java code com.example.android.apis.app.Intents.java. -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="4dip"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical" android:padding="4dip"
     android:gravity="center_horizontal"
     android:layout_width="match_parent" android:layout_height="match_parent">
 
@@ -29,9 +30,22 @@
 
     <Button android:id="@+id/get_music"
         android:layout_width="wrap_content" android:layout_height="wrap_content" 
-        android:text="@string/get_music">
+        android:text="@string/get_music"
+        android:onClick="onGetMusic">
         <requestFocus />
     </Button>
 
+    <Button android:id="@+id/get_image"
+        android:layout_width="wrap_content" android:layout_height="wrap_content"
+        android:text="@string/get_image"
+        android:onClick="onGetImage">
+    </Button>
+
+    <Button android:id="@+id/get_stream"
+        android:layout_width="wrap_content" android:layout_height="wrap_content"
+        android:text="@string/get_stream"
+        android:onClick="onGetStream">
+    </Button>
+
 </LinearLayout>
 
diff --git a/samples/ApiDemos/res/values/strings.xml b/samples/ApiDemos/res/values/strings.xml
index dad21bf..d81f769 100644
--- a/samples/ApiDemos/res/values/strings.xml
+++ b/samples/ApiDemos/res/values/strings.xml
@@ -467,6 +467,8 @@
     <string name="activity_intents">App/Activity/Intents</string>
     <string name="intents">Example of launching various Intents.</string>
     <string name="get_music">Get Music</string>
+    <string name="get_image">Get Image</string>
+    <string name="get_stream">Get Stream</string>
 
     <!-- ============================== -->
     <!--  app/intents activity flags examples strings     -->
@@ -1348,7 +1350,8 @@
     <string name="text_switcher_1_next_text">Next</string>
 
     <string name="date_widgets_example_dateDisplay_text"></string>
-    <string name="date_widgets_example_pickTime_text">change the time</string>
+    <string name="date_widgets_example_pickTime12_text">change the time (12 hour)</string>
+    <string name="date_widgets_example_pickTime24_text">change the time (24 hour)</string>
     <string name="date_widgets_example_pickDate_text">change the date</string>
 
     <string name="buttons_1_normal">Normal</string>
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/AppUpdateSspReceiver.java b/samples/ApiDemos/src/com/example/android/apis/app/AppUpdateSspReceiver.java
new file mode 100644
index 0000000..dfa265c
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/AppUpdateSspReceiver.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2013 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.app;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.widget.Toast;
+
+/**
+ * Executed when a new version of the application is is installed.
+ */
+public class AppUpdateSspReceiver extends BroadcastReceiver {
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        String msg = "Ssp update received: " + intent.getData();
+        Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
+    }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/Intents.java b/samples/ApiDemos/src/com/example/android/apis/app/Intents.java
index 8f02b83..6207dd8 100644
--- a/samples/ApiDemos/src/com/example/android/apis/app/Intents.java
+++ b/samples/ApiDemos/src/com/example/android/apis/app/Intents.java
@@ -31,17 +31,23 @@
         super.onCreate(savedInstanceState);
 
         setContentView(R.layout.intents);
-
-        // Watch for button clicks.
-        Button button = (Button)findViewById(R.id.get_music);
-        button.setOnClickListener(mGetMusicListener);
     }
 
-    private OnClickListener mGetMusicListener = new OnClickListener() {
-        public void onClick(View v) {
-            Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
-            intent.setType("audio/*");
-            startActivity(Intent.createChooser(intent, "Select music"));
-        }
-    };
+    public void onGetMusic(View view) {
+        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
+        intent.setType("audio/*");
+        startActivity(Intent.createChooser(intent, "Select music"));
+    }
+
+    public void onGetImage(View view) {
+        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
+        intent.setType("image/*");
+        startActivity(Intent.createChooser(intent, "Select image"));
+    }
+
+    public void onGetStream(View view) {
+        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
+        intent.setType("*/*");
+        startActivity(Intent.createChooser(intent, "Select stream"));
+    }
 }
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/DateWidgets1.java b/samples/ApiDemos/src/com/example/android/apis/view/DateWidgets1.java
index f0b1d22..537bda8 100644
--- a/samples/ApiDemos/src/com/example/android/apis/view/DateWidgets1.java
+++ b/samples/ApiDemos/src/com/example/android/apis/view/DateWidgets1.java
@@ -51,8 +51,9 @@
     private int mHour;
     private int mMinute;
 
-    static final int TIME_DIALOG_ID = 0;
-    static final int DATE_DIALOG_ID = 1;
+    static final int TIME_12_DIALOG_ID = 0;
+    static final int TIME_24_DIALOG_ID = 1;
+    static final int DATE_DIALOG_ID = 2;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -62,21 +63,9 @@
 
         mDateDisplay = (TextView) findViewById(R.id.dateDisplay);
 
-        Button pickDate = (Button) findViewById(R.id.pickDate);
-        pickDate.setOnClickListener(new View.OnClickListener() {
-
-            public void onClick(View v) {
-                showDialog(DATE_DIALOG_ID);
-            }
-        });
-
-        Button pickTime = (Button) findViewById(R.id.pickTime);
-        pickTime.setOnClickListener(new View.OnClickListener() {
-
-            public void onClick(View v) {
-                showDialog(TIME_DIALOG_ID);
-            }
-        });
+        setDialogOnClickListener(R.id.pickDate, DATE_DIALOG_ID);
+        setDialogOnClickListener(R.id.pickTime12, TIME_12_DIALOG_ID);
+        setDialogOnClickListener(R.id.pickTime24, TIME_24_DIALOG_ID);
 
         final Calendar c = Calendar.getInstance();
         mYear = c.get(Calendar.YEAR);
@@ -88,12 +77,22 @@
         updateDisplay();
     }
 
+    private void setDialogOnClickListener(int buttonId, final int dialogId) {
+        Button b = (Button) findViewById(buttonId);
+        b.setOnClickListener(new View.OnClickListener() {
+            public void onClick(View v) {
+                showDialog(dialogId);
+            }
+        });
+    }
+
     @Override
     protected Dialog onCreateDialog(int id) {
         switch (id) {
-            case TIME_DIALOG_ID:
+            case TIME_12_DIALOG_ID:
+            case TIME_24_DIALOG_ID:
                 return new TimePickerDialog(this,
-                        mTimeSetListener, mHour, mMinute, false);
+                        mTimeSetListener, mHour, mMinute, id == TIME_24_DIALOG_ID);
             case DATE_DIALOG_ID:
                 return new DatePickerDialog(this,
                             mDateSetListener,
@@ -105,7 +104,8 @@
     @Override
     protected void onPrepareDialog(int id, Dialog dialog) {
         switch (id) {
-            case TIME_DIALOG_ID:
+            case TIME_12_DIALOG_ID:
+            case TIME_24_DIALOG_ID:
                 ((TimePickerDialog) dialog).updateTime(mHour, mMinute);
                 break;
             case DATE_DIALOG_ID:
diff --git a/samples/AppLimits/Android.mk b/samples/AppLimits/Android.mk
deleted file mode 100644
index 2725276..0000000
--- a/samples/AppLimits/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := samples tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := AppLimits
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
-
-LOCAL_PROGUARD_FLAG_FILES := proguard.flags
-
-# Use the following include to make our test apk.
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/samples/AppLimits/AndroidManifest.xml b/samples/AppLimits/AndroidManifest.xml
deleted file mode 100644
index 8133fe9..0000000
--- a/samples/AppLimits/AndroidManifest.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 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.
--->
-
-<manifest android:versionCode="1"
-        android:versionName="1"
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        package="com.example.android.applimits">
-
-    <application android:label="@string/app_name"
-        android:requiredForAllUsers="true">
-
-        <activity android:name="CustomRestrictionsActivity"
-                android:exported="true"
-                android:label="@string/restrictions_activity_label">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity>
-
-        <receiver android:name="GetRestrictionsReceiver"
-                android:exported="true">
-            <intent-filter>
-                <action android:name="android.intent.action.GET_RESTRICTION_ENTRIES" />
-            </intent-filter>
-        </receiver>
-
-    </application>
-</manifest>
diff --git a/samples/AppLimits/res/values/strings.xml b/samples/AppLimits/res/values/strings.xml
deleted file mode 100644
index d5b7721..0000000
--- a/samples/AppLimits/res/values/strings.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 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.
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name">AppLimits Demo</string>
-    <string name="restrictions_activity_label">Custom app restrictions</string>
-    <string name="app_limits_main_label">App Limits</string>
-    <string name="custom_or_not_title">Test Custom Restrictions</string>
-    <string name="choice_entry_title">Test choice type</string>
-    <string name="multi_entry_title">Test multi-select type</string>
-
-    <string-array name="multi_entry_entries">
-        <item>Ice Cream</item>
-        <item>Jelly Bean</item>
-        <item>More Jelly Bean</item>
-    </string-array>
-
-    <string-array name="multi_entry_values" translateable="false">
-        <item>1</item>
-        <item>2</item>
-        <item>3</item>
-    </string-array>
-
-    <string-array name="choice_entry_entries">
-        <item>Ice Cream</item>
-        <item>Jelly Bean</item>
-        <item>More Jelly Bean</item>
-    </string-array>
-
-    <string-array name="choice_entry_values" translateable="false">
-        <item>1</item>
-        <item>2</item>
-        <item>3</item>
-    </string-array>
-
-</resources>
\ No newline at end of file
diff --git a/samples/AppLimits/res/xml/custom_prefs.xml b/samples/AppLimits/res/xml/custom_prefs.xml
deleted file mode 100644
index 2b45125..0000000
--- a/samples/AppLimits/res/xml/custom_prefs.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 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.
--->
-
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
-        android:title="@string/restrictions_activity_label">
-
-    <CheckBoxPreference android:key="custom"
-        android:title="@string/custom_or_not_title" />
-
-    <ListPreference android:key="choice"
-        android:title="@string/choice_entry_title"
-        android:entries="@array/choice_entry_entries"
-        android:entryValues="@array/choice_entry_values" />
-
-    <MultiSelectListPreference android:key="multi"
-        android:title="@string/multi_entry_title"
-        android:entries="@array/multi_entry_entries"
-        android:entryValues="@array/multi_entry_values" />
-
-</PreferenceScreen>
diff --git a/samples/AppLimits/src/com/example/android/applimits/CustomRestrictionsActivity.java b/samples/AppLimits/src/com/example/android/applimits/CustomRestrictionsActivity.java
deleted file mode 100644
index 963aa21..0000000
--- a/samples/AppLimits/src/com/example/android/applimits/CustomRestrictionsActivity.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2013 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.applimits;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.RestrictionEntry;
-import android.os.Bundle;
-import android.os.UserManager;
-import android.preference.CheckBoxPreference;
-import android.preference.ListPreference;
-import android.preference.MultiSelectListPreference;
-import android.preference.Preference;
-import android.preference.Preference.OnPreferenceChangeListener;
-import android.preference.PreferenceActivity;
-
-import com.example.android.applimits.GetRestrictionsReceiver;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-public class CustomRestrictionsActivity extends PreferenceActivity
-        implements OnPreferenceChangeListener {
-
-    private static final String KEY_CUSTOM_PREF = "custom";
-    private static final String KEY_CHOICE_PREF = "choice";
-    private static final String KEY_MULTI_PREF = "multi";
-
-    List<RestrictionEntry> mRestrictions;
-    private Bundle mRestrictionsBundle;
-
-    CheckBoxPreference mCustomPref;
-    ListPreference mChoicePref;
-    MultiSelectListPreference mMultiPref;
-
-    RestrictionEntry mCustomEntry;
-    RestrictionEntry mChoiceEntry;
-    RestrictionEntry mMultiEntry;
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        mRestrictionsBundle = getIntent().getBundleExtra(Intent.EXTRA_RESTRICTIONS_BUNDLE);
-        if (mRestrictionsBundle == null) {
-            mRestrictionsBundle =
-                ((UserManager) getSystemService(Context.USER_SERVICE))
-                .getApplicationRestrictions(getPackageName());
-        }
-        if (mRestrictionsBundle == null) {
-            mRestrictionsBundle = new Bundle();
-        }
-
-        if (savedInstanceState != null
-                && savedInstanceState.containsKey(Intent.EXTRA_RESTRICTIONS_LIST)) {
-            mRestrictions = savedInstanceState.getParcelableArrayList(
-                    Intent.EXTRA_RESTRICTIONS_LIST);
-        }
-
-        this.addPreferencesFromResource(R.xml.custom_prefs);
-        mCustomPref = (CheckBoxPreference) findPreference(KEY_CUSTOM_PREF);
-        mChoicePref = (ListPreference) findPreference(KEY_CHOICE_PREF);
-        mMultiPref = (MultiSelectListPreference) findPreference(KEY_MULTI_PREF);
-
-        // Transfer the saved values into the preference hierarchy
-        if (mRestrictions != null) {
-            for (RestrictionEntry entry : mRestrictions) {
-                if (entry.getKey().equals(GetRestrictionsReceiver.KEY_CUSTOM)) {
-                    mCustomPref.setChecked(entry.getSelectedState());
-                    mCustomEntry = entry;
-                } else if (entry.getKey().equals(GetRestrictionsReceiver.KEY_CHOICE)) {
-                    mChoicePref.setValue(entry.getSelectedString());
-                    mChoiceEntry = entry;
-                } else if (entry.getKey().equals(GetRestrictionsReceiver.KEY_MULTI_SELECT)) {
-                    HashSet<String> set = new HashSet<String>();
-                    for (String value : entry.getAllSelectedStrings()) {
-                        set.add(value);
-                    }
-                    mMultiPref.setValues(set);
-                    mMultiEntry = entry;
-                }
-            }
-        } else {
-            mRestrictions = new ArrayList<RestrictionEntry>();
-            mCustomEntry = new RestrictionEntry(GetRestrictionsReceiver.KEY_CUSTOM,
-                    mRestrictionsBundle.getBoolean(GetRestrictionsReceiver.KEY_CUSTOM, false));
-            mCustomEntry.setType(RestrictionEntry.TYPE_BOOLEAN);
-            mCustomPref.setChecked(mCustomEntry.getSelectedState());
-            mChoiceEntry = new RestrictionEntry(GetRestrictionsReceiver.KEY_CHOICE,
-                    mRestrictionsBundle.getString(GetRestrictionsReceiver.KEY_CHOICE));
-            mChoiceEntry.setType(RestrictionEntry.TYPE_CHOICE);
-            mChoicePref.setValue(mChoiceEntry.getSelectedString());
-            mMultiEntry = new RestrictionEntry(GetRestrictionsReceiver.KEY_MULTI_SELECT,
-                    mRestrictionsBundle.getStringArray(GetRestrictionsReceiver.KEY_MULTI_SELECT));
-            mMultiEntry.setType(RestrictionEntry.TYPE_MULTI_SELECT);
-            if (mMultiEntry.getAllSelectedStrings() != null) {
-                HashSet<String> set = new HashSet<String>();
-                for (String value : mRestrictionsBundle.getStringArray(
-                        GetRestrictionsReceiver.KEY_MULTI_SELECT)) {
-                    set.add(value);
-                }
-                mMultiPref.setValues(set);
-            }
-            mRestrictions.add(mCustomEntry);
-            mRestrictions.add(mChoiceEntry);
-            mRestrictions.add(mMultiEntry);
-        }
-        mCustomPref.setOnPreferenceChangeListener(this);
-        mChoicePref.setOnPreferenceChangeListener(this);
-        mMultiPref.setOnPreferenceChangeListener(this);
-        Intent intent = new Intent(getIntent());
-        intent.putParcelableArrayListExtra(Intent.EXTRA_RESTRICTIONS_LIST,
-                new ArrayList<RestrictionEntry>(mRestrictions));
-        setResult(RESULT_OK, intent);
-    }
-
-    public void onSaveInstanceState(Bundle outState) {
-        super.onSaveInstanceState(outState);
-        outState.putParcelableArrayList(Intent.EXTRA_RESTRICTIONS_LIST,
-                new ArrayList<RestrictionEntry>(mRestrictions));
-    }
-
-    @Override
-    public boolean onPreferenceChange(Preference preference, Object newValue) {
-        if (preference == mCustomPref) {
-            mCustomEntry.setSelectedState((Boolean) newValue);
-        } else if (preference == mChoicePref) {
-            mChoiceEntry.setSelectedString((String) newValue);
-        } else if (preference == mMultiPref) {
-            String[] selectedStrings = new String[((Set<String>)newValue).size()];
-            int i = 0;
-            for (String value : (Set<String>) newValue) {
-                selectedStrings[i++] = value;
-            }
-            mMultiEntry.setAllSelectedStrings(selectedStrings);
-        }
-        Intent intent = new Intent(getIntent());
-        intent.putParcelableArrayListExtra(Intent.EXTRA_RESTRICTIONS_LIST,
-                new ArrayList<RestrictionEntry>(mRestrictions));
-        setResult(RESULT_OK, intent);
-        return true;
-    }
-}
diff --git a/samples/AppLimits/src/com/example/android/applimits/GetRestrictionsReceiver.java b/samples/AppLimits/src/com/example/android/applimits/GetRestrictionsReceiver.java
deleted file mode 100644
index 0249911..0000000
--- a/samples/AppLimits/src/com/example/android/applimits/GetRestrictionsReceiver.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2013 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.applimits;
-
-import android.app.Activity;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.RestrictionEntry;
-import android.content.BroadcastReceiver.PendingResult;
-import android.content.res.Resources;
-import android.os.Bundle;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class GetRestrictionsReceiver extends BroadcastReceiver {
-    private static final String TAG = "AppLimits$GetRestrictionsReceiver";
-
-    static final String KEY_CUSTOM = "custom_or_not";
-    static final String KEY_CHOICE = "choice";
-    static final String KEY_MULTI_SELECT = "multi";
-
-    @Override
-    public void onReceive(final Context context, Intent intent) {
-        final PendingResult result = goAsync();
-        final Bundle oldRestrictions =
-                intent.getBundleExtra(Intent.EXTRA_RESTRICTIONS_BUNDLE);
-        Log.i(TAG, "oldRestrictions = " + oldRestrictions);
-        new Thread() {
-            public void run() {
-                createRestrictions(context, result, oldRestrictions);
-            }
-        }.start();
-    }
-
-    public static void populateCustomEntry(Resources res, RestrictionEntry entry) {
-        entry.setType(RestrictionEntry.TYPE_BOOLEAN);
-        entry.setTitle(res.getString(R.string.custom_or_not_title));
-    }
-
-    public static void populateChoiceEntry(Resources res, RestrictionEntry reSingleChoice) {
-        String[] choiceEntries = res.getStringArray(R.array.choice_entry_entries);
-        String[] choiceValues = res.getStringArray(R.array.choice_entry_values);
-        if (reSingleChoice.getSelectedString() == null) {
-            reSingleChoice.setSelectedString(choiceValues[0]);
-        }
-        reSingleChoice.setTitle(res.getString(R.string.choice_entry_title));
-        reSingleChoice.setChoiceEntries(choiceEntries);
-        reSingleChoice.setChoiceValues(choiceValues);
-        reSingleChoice.setType(RestrictionEntry.TYPE_CHOICE);
-    }
-
-    public static void populateMultiEntry(Resources res, RestrictionEntry reMultiSelect) {
-        String[] multiEntries = res.getStringArray(R.array.multi_entry_entries);
-        String[] multiValues = res.getStringArray(R.array.multi_entry_values);
-        if (reMultiSelect.getAllSelectedStrings() == null) {
-            reMultiSelect.setAllSelectedStrings(new String[0]);
-        }
-        reMultiSelect.setTitle(res.getString(R.string.multi_entry_title));
-        reMultiSelect.setChoiceEntries(multiEntries);
-        reMultiSelect.setChoiceValues(multiValues);
-        reMultiSelect.setType(RestrictionEntry.TYPE_MULTI_SELECT);
-    }
-
-    private ArrayList<RestrictionEntry> initRestrictions(Context context) {
-        ArrayList<RestrictionEntry> newRestrictions = new ArrayList<RestrictionEntry>();
-        Resources res = context.getResources();
-
-        RestrictionEntry reCustomOrNot = new RestrictionEntry(KEY_CUSTOM, false);
-        populateCustomEntry(res, reCustomOrNot);
-        newRestrictions.add(reCustomOrNot);
-
-        RestrictionEntry reSingleChoice = new RestrictionEntry(KEY_CHOICE, (String) null);
-        populateChoiceEntry(res, reSingleChoice);
-        newRestrictions.add(reSingleChoice);
-
-        RestrictionEntry reMultiSelect = new RestrictionEntry(KEY_MULTI_SELECT, (String[]) null);
-        populateMultiEntry(res, reMultiSelect);
-        newRestrictions.add(reMultiSelect);
-
-        return newRestrictions;
-    }
-
-    private void createRestrictions(Context context, PendingResult result, Bundle old) {
-        Resources res = context.getResources();
-
-        ArrayList<RestrictionEntry> newEntries = initRestrictions(context);
-        // If this is the first time, create the default restrictions entries and return them.
-        if (old == null) {
-            Bundle extras = new Bundle();
-            extras.putParcelableArrayList(Intent.EXTRA_RESTRICTIONS_LIST, newEntries);
-            result.setResult(Activity.RESULT_OK, null, extras);
-            result.finish();
-            return;
-        }
-
-        boolean custom = old.getBoolean(KEY_CUSTOM, false);
-        for (RestrictionEntry entry : newEntries) {
-            final String key = entry.getKey();
-            if (KEY_CUSTOM.equals(key)) {
-                entry.setSelectedState(custom);
-            } else if (KEY_CHOICE.equals(key)) {
-                if (old.containsKey(KEY_CHOICE)) {
-                    entry.setSelectedString(old.getString(KEY_CHOICE));
-                }
-            } else if (KEY_MULTI_SELECT.equals(key)) {
-                if (old.containsKey(KEY_MULTI_SELECT)) {
-                    entry.setAllSelectedStrings(old.getStringArray(key));
-                }
-            }
-        }
-
-        Bundle extras = new Bundle();
-        if (custom) {
-            Intent customIntent = new Intent();
-            customIntent.setClass(context, CustomRestrictionsActivity.class);
-            extras.putParcelable(Intent.EXTRA_RESTRICTIONS_INTENT, customIntent);
-        }
-        extras.putParcelableArrayList(Intent.EXTRA_RESTRICTIONS_LIST, newEntries);
-        result.setResult(Activity.RESULT_OK, null, extras);
-        result.finish();
-    }
-}
diff --git a/samples/Support7Demos/AndroidManifest.xml b/samples/Support7Demos/AndroidManifest.xml
index 1edf3e6..273af1e 100644
--- a/samples/Support7Demos/AndroidManifest.xml
+++ b/samples/Support7Demos/AndroidManifest.xml
@@ -21,6 +21,12 @@
      to come from a domain that you own or have control over. -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.example.android.supportv7">
+    <!-- Permission for INTERNET is required for streaming video content
+         from the web, it's not required otherwise. -->
+    <uses-permission android:name="android.permission.INTERNET" />
+    <!-- Permission for SYSTEM_ALERT_WINDOW is only required for emulating
+         remote display using system alert window. -->
+    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
 
     <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="17" />
 
diff --git a/samples/Support7Demos/res/drawable-hdpi/ic_media_pause.png b/samples/Support7Demos/res/drawable-hdpi/ic_media_pause.png
new file mode 100644
index 0000000..1d465a4
--- /dev/null
+++ b/samples/Support7Demos/res/drawable-hdpi/ic_media_pause.png
Binary files differ
diff --git a/samples/Support7Demos/res/drawable-hdpi/ic_media_play.png b/samples/Support7Demos/res/drawable-hdpi/ic_media_play.png
new file mode 100644
index 0000000..2746d17
--- /dev/null
+++ b/samples/Support7Demos/res/drawable-hdpi/ic_media_play.png
Binary files differ
diff --git a/samples/Support7Demos/res/drawable-hdpi/ic_media_stop.png b/samples/Support7Demos/res/drawable-hdpi/ic_media_stop.png
new file mode 100644
index 0000000..a0ff136
--- /dev/null
+++ b/samples/Support7Demos/res/drawable-hdpi/ic_media_stop.png
Binary files differ
diff --git a/samples/Support7Demos/res/drawable-hdpi/ic_menu_add.png b/samples/Support7Demos/res/drawable-hdpi/ic_menu_add.png
new file mode 100644
index 0000000..444e8a5
--- /dev/null
+++ b/samples/Support7Demos/res/drawable-hdpi/ic_menu_add.png
Binary files differ
diff --git a/samples/Support7Demos/res/drawable-hdpi/ic_menu_delete.png b/samples/Support7Demos/res/drawable-hdpi/ic_menu_delete.png
new file mode 100644
index 0000000..24d8f6a
--- /dev/null
+++ b/samples/Support7Demos/res/drawable-hdpi/ic_menu_delete.png
Binary files differ
diff --git a/samples/Support7Demos/res/drawable-mdpi/ic_media_pause.png b/samples/Support7Demos/res/drawable-mdpi/ic_media_pause.png
new file mode 100644
index 0000000..3e6b2a1
--- /dev/null
+++ b/samples/Support7Demos/res/drawable-mdpi/ic_media_pause.png
Binary files differ
diff --git a/samples/Support7Demos/res/drawable-mdpi/ic_media_play.png b/samples/Support7Demos/res/drawable-mdpi/ic_media_play.png
new file mode 100644
index 0000000..7966bbc
--- /dev/null
+++ b/samples/Support7Demos/res/drawable-mdpi/ic_media_play.png
Binary files differ
diff --git a/samples/Support7Demos/res/drawable-mdpi/ic_media_stop.png b/samples/Support7Demos/res/drawable-mdpi/ic_media_stop.png
new file mode 100644
index 0000000..8ea7efe
--- /dev/null
+++ b/samples/Support7Demos/res/drawable-mdpi/ic_media_stop.png
Binary files differ
diff --git a/samples/Support7Demos/res/drawable-mdpi/ic_menu_add.png b/samples/Support7Demos/res/drawable-mdpi/ic_menu_add.png
new file mode 100644
index 0000000..361c7c4
--- /dev/null
+++ b/samples/Support7Demos/res/drawable-mdpi/ic_menu_add.png
Binary files differ
diff --git a/samples/Support7Demos/res/drawable-mdpi/ic_menu_delete.png b/samples/Support7Demos/res/drawable-mdpi/ic_menu_delete.png
new file mode 100644
index 0000000..e2c8700
--- /dev/null
+++ b/samples/Support7Demos/res/drawable-mdpi/ic_menu_delete.png
Binary files differ
diff --git a/samples/Support7Demos/res/layout/media_item.xml b/samples/Support7Demos/res/layout/media_item.xml
new file mode 100644
index 0000000..e5d6d02
--- /dev/null
+++ b/samples/Support7Demos/res/layout/media_item.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.
+-->
+
+<!-- Layout for list item in Library or Playlist view. Displays ImageButton
+     instead of radio button to the right of the item. -->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="horizontal"
+        android:gravity="center_vertical">
+
+    <ImageButton android:id="@+id/item_action"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:minWidth="48dp"
+        android:minHeight="48dp"
+        android:layout_alignParentRight="true"
+        android:layout_centerVertical="true"
+        android:background="@null"/>
+
+    <TextView android:id="@+id/item_text"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:textAppearance="?android:attr/textAppearanceSmall"
+        android:layout_centerVertical="true"
+        android:layout_toLeftOf="@id/item_action"
+        android:layout_gravity="left"
+        android:gravity="left"/>
+</RelativeLayout>
diff --git a/samples/Support7Demos/res/layout/overlay_display_window.xml b/samples/Support7Demos/res/layout/overlay_display_window.xml
new file mode 100644
index 0000000..36b4a0d
--- /dev/null
+++ b/samples/Support7Demos/res/layout/overlay_display_window.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+      android:layout_width="match_parent"
+      android:layout_height="match_parent"
+      android:background="#000000">
+    <TextureView android:id="@+id/overlay_display_window_texture"
+               android:layout_width="0px"
+               android:layout_height="0px" />
+    <TextView android:id="@+id/overlay_display_window_title"
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:layout_gravity="top|center_horizontal" />
+</FrameLayout>
diff --git a/samples/Support7Demos/res/layout/sample_media_router.xml b/samples/Support7Demos/res/layout/sample_media_router.xml
index a8b08b1..e2f7008 100644
--- a/samples/Support7Demos/res/layout/sample_media_router.xml
+++ b/samples/Support7Demos/res/layout/sample_media_router.xml
@@ -20,45 +20,118 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:orientation="vertical">
-
-    <!-- Message to show to use. -->
-    <TextView android:id="@+id/text"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_weight="0"
-        android:gravity="center_vertical|center_horizontal"
-        android:textAppearance="?android:attr/textAppearanceMedium"
-        android:text="@string/sample_media_router_text"/>
-
-    <!-- Some information about what's going on. -->
-    <TextView android:id="@+id/info"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_weight="0"
-        android:gravity="center_vertical|center_horizontal"
-        android:textAppearance="?android:attr/textAppearanceMedium"/>
-
-    <!-- Some media to play. -->
-    <ListView android:id="@+id/media"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_weight="1"/>
-
-    <!-- Control buttons for the currently selected route. -->
     <LinearLayout
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_weight="0">
-        <Button android:id="@+id/play_button"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_weight="0"
-            android:text="@string/play_button_text" />
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        android:orientation="vertical">
+        <!-- Tabs for media library, playlist and statistics -->
+        <TabHost android:id="@+id/tabHost"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:layout_weight="1">
+            <LinearLayout
+                android:orientation="vertical"
+                android:layout_width="fill_parent"
+                android:layout_height="fill_parent">
+                <TabWidget android:id="@android:id/tabs"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content" />
 
-        <Button android:id="@+id/statistics_button"
+                <FrameLayout android:id="@android:id/tabcontent"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content">
+                    <LinearLayout android:id="@+id/tab1"
+                        android:layout_width="fill_parent"
+                        android:layout_height="wrap_content"
+                        android:orientation="vertical">
+                        <ListView android:id="@+id/media"
+                            android:layout_width="match_parent"
+                            android:layout_height="wrap_content"
+                            android:layout_weight="1" />
+                    </LinearLayout>
+
+                    <LinearLayout android:id="@+id/tab2"
+                        android:layout_width="fill_parent"
+                        android:layout_height="fill_parent"
+                        android:orientation="vertical">
+                        <ListView android:id="@+id/playlist"
+                            android:layout_width="match_parent"
+                            android:layout_height="wrap_content"
+                            android:layout_weight="1"/>
+                    </LinearLayout>
+
+                    <LinearLayout android:id="@+id/tab3"
+                        android:layout_width="fill_parent"
+                        android:layout_height="fill_parent"
+                        android:orientation="vertical">
+                        <TextView android:id="@+id/info"
+                            android:layout_width="match_parent"
+                            android:layout_height="wrap_content"
+                            android:layout_weight="1"
+                            android:textAppearance="?android:attr/textAppearanceMedium"/>
+                    </LinearLayout>
+                </FrameLayout>
+            </LinearLayout>
+        </TabHost>
+
+        <!-- Control buttons for the currently selected route. -->
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_weight="0">
+
+            <SeekBar android:id="@+id/seekbar"
+                 android:layout_width="fill_parent"
+                 android:layout_height="wrap_content"
+                 style="?android:attr/progressBarStyleHorizontal"
+                 android:max="100"
+                 android:progress="0"
+                 android:layout_gravity="center"
+                 android:layout_weight="1"/>
+
+            <ImageButton android:id="@+id/pause_resume_button"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_weight="0"
+                android:layout_gravity="right"
+                android:minWidth="48dp"
+                android:minHeight="48dp"
+                android:background="@null"
+                android:src="@drawable/ic_media_pause" />
+
+            <ImageButton android:id="@+id/stop_button"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_weight="0"
+                android:layout_gravity="right"
+                android:minWidth="48dp"
+                android:minHeight="48dp"
+                android:background="@null"
+                android:src="@drawable/ic_media_stop" />
+        </LinearLayout>
+
+    </LinearLayout>
+
+    <!-- Some content for visual interest in the case where no presentation is showing. -->
+    <FrameLayout android:id="@+id/player"
+        android:background="#ff000000"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1">
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:gravity="center">
+            <SurfaceView android:id="@+id/surface_view"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"/>
+        </LinearLayout>
+        <TextView
+            android:textColor="#ffaaaaaa"
+            android:text="@string/sample_media_route_activity_local"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_weight="0"
-            android:text="@string/statistics_button_text" />
-    </LinearLayout>
+            android:layout_gravity="top|center_horizontal" />
+    </FrameLayout>
 </LinearLayout>
diff --git a/samples/Support7Demos/res/layout/sample_media_router_presentation.xml b/samples/Support7Demos/res/layout/sample_media_router_presentation.xml
new file mode 100644
index 0000000..f029627
--- /dev/null
+++ b/samples/Support7Demos/res/layout/sample_media_router_presentation.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+
+<!-- The content that we show on secondary displays.
+     See corresponding Java code PresentationWithMediaRouterActivity.java. -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="#ff000000">
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:gravity="center">
+        <SurfaceView android:id="@+id/surface_view"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"/>
+    </LinearLayout>
+    <TextView
+        android:textColor="#ffaaaaaa"
+        android:text="@string/sample_media_route_activity_presentation"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="top|center_horizontal" />
+</FrameLayout>
diff --git a/samples/Support7Demos/res/menu/actions.xml b/samples/Support7Demos/res/menu/actions.xml
index fbae7b1..38d291e 100644
--- a/samples/Support7Demos/res/menu/actions.xml
+++ b/samples/Support7Demos/res/menu/actions.xml
@@ -19,7 +19,7 @@
           android:icon="@android:drawable/ic_menu_search"
           android:title="@string/action_bar_search"
           app:showAsAction="ifRoom"
-          app:actionProviderClass="android.support.v7.widget.SearchActionProvider" />
+          app:actionViewClass="android.support.v7.widget.SearchView" />
     <item android:id="@+id/action_add"
           android:icon="@android:drawable/ic_menu_add"
           android:title="@string/action_bar_add" />
diff --git a/samples/Support7Demos/res/values/arrays.xml b/samples/Support7Demos/res/values/arrays.xml
index f5616a1..8d658eb 100644
--- a/samples/Support7Demos/res/values/arrays.xml
+++ b/samples/Support7Demos/res/values/arrays.xml
@@ -16,18 +16,16 @@
 
 <resources>
     <string-array name="media_names">
-        <item>My favorite video of cats</item>
-        <item>Cats on parade</item>
-        <item>Cats with hats</item>
-        <item>Hats on cats</item>
-        <item>Cats on mats</item>
+        <item>Big Buck Bunny</item>
+        <item>Elephants Dream</item>
+        <item>Sintel</item>
+        <item>Tears of Steel</item>
     </string-array>
 
     <string-array name="media_uris">
-        <item>http://cats.example.com/favorite-cats.mp4</item>
-        <item>http://cats.example.com/cats-on-parade.mp4</item>
-        <item>http://cats.example.com/cats-with-hats.mp4</item>
-        <item>http://cats.example.com/hats-on-cats.mp4</item>
-        <item>http://cats.example.com/cats-on-mats.mp4</item>
+        <item>http://archive.org/download/BigBuckBunny_328/BigBuckBunny_512kb.mp4</item>
+        <item>http://archive.org/download/ElephantsDream_277/elephant_dreams_640_512kb.mp4</item>
+        <item>http://archive.org/download/Sintel/sintel-2048-stereo_512kb.mp4</item>
+        <item>http://archive.org/download/Tears-of-Steel/tears_of_steel_720p.mp4</item>
     </string-array>
 </resources>
diff --git a/samples/Support7Demos/res/values/strings.xml b/samples/Support7Demos/res/values/strings.xml
index 6a8ac77..cbbc640 100644
--- a/samples/Support7Demos/res/values/strings.xml
+++ b/samples/Support7Demos/res/values/strings.xml
@@ -26,8 +26,9 @@
             use MediaRouter from the support library.  Select a route from the action bar.</string>
     <string name="media_route_menu_title">Play on...</string>
 
-    <string name="play_button_text">Play</string>
-    <string name="statistics_button_text">Show Statistics</string>
+    <string name="library_tab_text">Library</string>
+    <string name="playlist_tab_text">Playlist</string>
+    <string name="statistics_tab_text">Statistics</string>
 
     <string name="sample_media_route_provider_service">Media Route Provider Service Support Library Sample</string>
     <string name="fixed_volume_route_name">Fixed Volume Remote Playback Route</string>
@@ -88,4 +89,8 @@
     <string name="action_bar_fragment_has_options_menu">Set has options menu to true</string>
     <string name="action_bar_fragment_menu_visibility">Set menu visibility to true</string>
 
+    <string name="sample_media_route_provider_remote">Remote Playback (Simulated)</string>
+    <string name="sample_media_route_activity_local">Local Playback</string>
+    <string name="sample_media_route_activity_presentation">Local Playback on Presentation Display</string>
+
 </resources>
diff --git a/samples/Support7Demos/src/com/example/android/supportv7/app/ActionBarUsage.java b/samples/Support7Demos/src/com/example/android/supportv7/app/ActionBarUsage.java
index d6152cc..6ed59fb 100644
--- a/samples/Support7Demos/src/com/example/android/supportv7/app/ActionBarUsage.java
+++ b/samples/Support7Demos/src/com/example/android/supportv7/app/ActionBarUsage.java
@@ -15,18 +15,19 @@
  */
 package com.example.android.supportv7.app;
 
+import com.example.android.supportv7.R;
+
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.support.v4.view.MenuItemCompat;
-import android.support.v4.widget.SearchViewCompat;
 import android.support.v7.app.ActionBarActivity;
+import android.support.v7.widget.SearchView;
+import android.text.TextUtils;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
-import android.view.View;
 import android.widget.TextView;
 import android.widget.Toast;
-import com.example.android.supportv7.R;
 
 /**
  * This demonstrates idiomatic usage of the Action Bar. The default Honeycomb theme
@@ -49,8 +50,9 @@
     public boolean onCreateOptionsMenu(Menu menu) {
         MenuInflater inflater = getMenuInflater();
         inflater.inflate(R.menu.actions, menu);
-        View searchView = MenuItemCompat.getActionView(menu.findItem(R.id.action_search));
-        SearchViewCompat.setOnQueryTextListener(searchView, mOnQueryTextListener);
+        SearchView searchView = (SearchView) MenuItemCompat
+                .getActionView(menu.findItem(R.id.action_search));
+        searchView.setOnQueryTextListener(mOnQueryTextListener);
         return true;
     }
 
@@ -80,11 +82,11 @@
 
     // The following callbacks are called for the SearchView.OnQueryChangeListener
     // For more about using SearchView, see src/.../view/SearchView1.java and SearchView2.java
-    private final SearchViewCompat.OnQueryTextListenerCompat mOnQueryTextListener =
-            new SearchViewCompat.OnQueryTextListenerCompat() {
+    private final SearchView.OnQueryTextListener mOnQueryTextListener =
+            new SearchView.OnQueryTextListener() {
         @Override
         public boolean onQueryTextChange(String newText) {
-            newText = newText.isEmpty() ? "" : "Query so far: " + newText;
+            newText = TextUtils.isEmpty(newText) ? "" : "Query so far: " + newText;
             mSearchText.setText(newText);
             return true;
         }
diff --git a/samples/Support7Demos/src/com/example/android/supportv7/media/MediaPlayerWrapper.java b/samples/Support7Demos/src/com/example/android/supportv7/media/MediaPlayerWrapper.java
new file mode 100644
index 0000000..9aa78d8
--- /dev/null
+++ b/samples/Support7Demos/src/com/example/android/supportv7/media/MediaPlayerWrapper.java
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2013 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.supportv7.media;
+
+import com.example.android.supportv7.R;
+
+import android.content.Context;
+import android.net.Uri;
+import android.os.Handler;
+import android.util.Log;
+import android.media.MediaPlayer;
+import android.view.Surface;
+import android.view.Gravity;
+import android.graphics.SurfaceTexture;
+import java.io.IOException;
+
+/**
+ * MediaPlayerWrapper handles playback of a single media item, and is used for
+ * both local and remote playback.
+ */
+public class MediaPlayerWrapper implements
+        MediaPlayer.OnPreparedListener,
+        MediaPlayer.OnCompletionListener,
+        MediaPlayer.OnErrorListener,
+        MediaPlayer.OnSeekCompleteListener,
+        OverlayDisplayWindow.OverlayWindowListener,
+        MediaSessionManager.Callback {
+    private static final String TAG = "MediaPlayerWrapper";
+    private static final boolean DEBUG = false;
+
+    private static final int STATE_IDLE = 0;
+    private static final int STATE_PLAY_PENDING = 1;
+    private static final int STATE_READY = 2;
+    private static final int STATE_PLAYING = 3;
+    private static final int STATE_PAUSED = 4;
+
+    private final Context mContext;
+    private final Handler mHandler = new Handler();
+    private MediaPlayer mMediaPlayer;
+    private int mState = STATE_IDLE;
+    private Callback mCallback;
+    private Surface mSurface;
+    private int mSeekToPos;
+
+    public MediaPlayerWrapper(Context context) {
+        mContext = context;
+        reset();
+    }
+
+    public void release() {
+        onStop();
+        mMediaPlayer.release();
+    }
+
+    public void setCallback(Callback cb) {
+        mCallback = cb;
+    }
+
+    // MediaSessionManager.Callback
+    @Override
+    public void onNewItem(Uri uri) {
+        reset();
+        try {
+            mMediaPlayer.setDataSource(mContext, uri);
+            mMediaPlayer.prepareAsync();
+        } catch (IllegalStateException e) {
+            Log.e(TAG, "MediaPlayer throws IllegalStateException, uri=" + uri);
+        } catch (IOException e) {
+            Log.e(TAG, "MediaPlayer throws IOException, uri=" + uri);
+        } catch (IllegalArgumentException e) {
+            Log.e(TAG, "MediaPlayer throws IllegalArgumentException, uri=" + uri);
+        } catch (SecurityException e) {
+            Log.e(TAG, "MediaPlayer throws SecurityException, uri=" + uri);
+        }
+    }
+
+    @Override
+    public void onStart() {
+        if (mState == STATE_READY || mState == STATE_PAUSED) {
+            mMediaPlayer.start();
+            mState = STATE_PLAYING;
+        } else if (mState == STATE_IDLE){
+            mState = STATE_PLAY_PENDING;
+        }
+    }
+
+    @Override
+    public void onStop() {
+        if (mState == STATE_PLAYING || mState == STATE_PAUSED) {
+            mMediaPlayer.stop();
+            mState = STATE_IDLE;
+        }
+    }
+
+    @Override
+    public void onPause() {
+        if (mState == STATE_PLAYING) {
+            mMediaPlayer.pause();
+            mState = STATE_PAUSED;
+        }
+    }
+
+    @Override
+    public void onSeek(long pos) {
+        if (DEBUG) {
+            Log.d(TAG, "onSeek: pos=" + pos);
+        }
+        if (mState == STATE_PLAYING || mState == STATE_PAUSED) {
+            mMediaPlayer.seekTo((int)pos);
+            mSeekToPos = (int)pos;
+        } else if (mState == STATE_IDLE || mState == STATE_PLAY_PENDING) {
+            // Seek before onPrepared() arrives,
+            // need to performed delayed seek in onPrepared()
+            mSeekToPos = (int)pos;
+        }
+    }
+
+    @Override
+    public void onGetStatus(MediaQueueItem item) {
+        if (mState == STATE_PLAYING || mState == STATE_PAUSED) {
+            // use mSeekToPos if we're currently seeking (mSeekToPos is reset
+            // when seeking is completed)
+            item.setContentDuration(mMediaPlayer.getDuration());
+            item.setContentPosition(mSeekToPos > 0 ?
+                    mSeekToPos : mMediaPlayer.getCurrentPosition());
+        }
+    }
+
+    //OverlayDisplayWindow listeners
+    @Override
+    public void onWindowCreated(Surface surface) {
+        if (DEBUG) {
+            Log.d(TAG, "onWindowCreated");
+        }
+        mSurface = surface;
+        mMediaPlayer.setSurface(surface);
+    }
+
+    @Override
+    public void onWindowDestroyed() {
+        if (DEBUG) {
+            Log.d(TAG, "onWindowDestroyed");
+        }
+    }
+
+    //MediaPlayer Listeners
+    @Override
+    public void onPrepared(MediaPlayer mp) {
+        if (DEBUG) {
+            Log.d(TAG,"onPrepared");
+        }
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                if (mState == STATE_IDLE) {
+                    mState = STATE_READY;
+                    updateVideoRect();
+                } else if (mState == STATE_PLAY_PENDING) {
+                    mState = STATE_PLAYING;
+                    updateVideoRect();
+                    if (mSeekToPos > 0) {
+                        Log.d(TAG, "Seeking to initial pos " + mSeekToPos);
+                        mMediaPlayer.seekTo((int)mSeekToPos);
+                    }
+                    mMediaPlayer.start();
+                }
+                if (mCallback != null) {
+                    mCallback.onStatusChanged();
+                }
+            }
+        });
+    }
+
+    @Override
+    public void onCompletion(MediaPlayer mp) {
+        if (DEBUG) {
+            Log.d(TAG,"onCompletion");
+        }
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                if (mCallback != null) {
+                    mCallback.onCompletion();
+                }
+            }
+        });
+    }
+
+    @Override
+    public boolean onError(MediaPlayer mp, int what, int extra) {
+        if (DEBUG) {
+            Log.d(TAG,"onError");
+        }
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                if (mCallback != null) {
+                    mCallback.onError();
+                }
+            }
+        });
+        // return true so that onCompletion is not called
+        return true;
+    }
+
+    @Override
+    public void onSeekComplete(MediaPlayer mp) {
+        if (DEBUG) {
+            Log.d(TAG, "onSeekComplete");
+        }
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mSeekToPos = 0;
+                if (mCallback != null) {
+                    mCallback.onStatusChanged();
+                }
+            }
+        });
+    }
+
+    private void reset() {
+        if (mMediaPlayer != null) {
+            mMediaPlayer.stop();
+            mMediaPlayer.release();
+            mMediaPlayer = null;
+        }
+        mMediaPlayer = new MediaPlayer();
+        mMediaPlayer.setOnPreparedListener(this);
+        mMediaPlayer.setOnCompletionListener(this);
+        mMediaPlayer.setOnErrorListener(this);
+        mMediaPlayer.setOnSeekCompleteListener(this);
+        if (mSurface != null) {
+            mMediaPlayer.setSurface(mSurface);
+        }
+        mState = STATE_IDLE;
+        mSeekToPos = 0;
+    }
+
+    private void updateVideoRect() {
+        if (mState != STATE_IDLE && mState != STATE_PLAY_PENDING) {
+            int videoWidth = mMediaPlayer.getVideoWidth();
+            int videoHeight = mMediaPlayer.getVideoHeight();
+            if (videoWidth > 0 && videoHeight > 0) {
+                if (mCallback != null) {
+                    mCallback.onSizeChanged(videoWidth, videoHeight);
+                }
+            } else {
+                Log.e(TAG, "video rect is 0x0!");
+            }
+        }
+    }
+
+    public static abstract class Callback {
+        public void onError() {}
+        public void onCompletion() {}
+        public void onStatusChanged() {}
+        public void onSizeChanged(int width, int height) {}
+    }
+}
diff --git a/samples/Support7Demos/src/com/example/android/supportv7/media/MediaQueueItem.java b/samples/Support7Demos/src/com/example/android/supportv7/media/MediaQueueItem.java
new file mode 100644
index 0000000..5440d86
--- /dev/null
+++ b/samples/Support7Demos/src/com/example/android/supportv7/media/MediaQueueItem.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2013 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.supportv7.media;
+
+import android.support.v7.media.MediaItemStatus;
+import android.net.Uri;
+import android.app.PendingIntent;
+
+/**
+ * MediaQueueItem helps keep track of the current status of an media item.
+ */
+final class MediaQueueItem {
+    // immutables
+    private final String mSessionId;
+    private final String mItemId;
+    private final Uri mUri;
+    private final PendingIntent mUpdateReceiver;
+    // changeable states
+    private int mPlaybackState = MediaItemStatus.PLAYBACK_STATE_PENDING;
+    private long mContentPosition;
+    private long mContentDuration;
+
+    public MediaQueueItem(String qid, String iid, Uri uri, PendingIntent pi) {
+        mSessionId = qid;
+        mItemId = iid;
+        mUri = uri;
+        mUpdateReceiver = pi;
+    }
+
+    public void setState(int state) {
+        mPlaybackState = state;
+    }
+
+    public void setContentPosition(long pos) {
+        mContentPosition = pos;
+    }
+
+    public void setContentDuration(long duration) {
+        mContentDuration = duration;
+    }
+
+    public String getSessionId() {
+        return mSessionId;
+    }
+
+    public String getItemId() {
+        return mItemId;
+    }
+
+    public Uri getUri() {
+        return mUri;
+    }
+
+    public PendingIntent getUpdateReceiver() {
+        return mUpdateReceiver;
+    }
+
+    public int getState() {
+        return mPlaybackState;
+    }
+
+    public long getContentPosition() {
+        return mContentPosition;
+    }
+
+    public long getContentDuration() {
+        return mContentDuration;
+    }
+
+    public MediaItemStatus getStatus() {
+        return new MediaItemStatus.Builder(mPlaybackState)
+            .setContentPosition(mContentPosition)
+            .setContentDuration(mContentDuration)
+            .build();
+    }
+
+    @Override
+    public String toString() {
+        String state[] = {
+            "PENDING",
+            "PLAYING",
+            "PAUSED",
+            "BUFFERING",
+            "FINISHED",
+            "CANCELED",
+            "INVALIDATED",
+            "ERROR"
+        };
+        return "[" + mSessionId + "|" + mItemId + "|"
+            + state[mPlaybackState] + "] " + mUri.toString();
+    }
+}
\ No newline at end of file
diff --git a/samples/Support7Demos/src/com/example/android/supportv7/media/MediaSessionManager.java b/samples/Support7Demos/src/com/example/android/supportv7/media/MediaSessionManager.java
new file mode 100644
index 0000000..9258998
--- /dev/null
+++ b/samples/Support7Demos/src/com/example/android/supportv7/media/MediaSessionManager.java
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2013 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.supportv7.media;
+
+import java.util.List;
+import java.util.ArrayList;
+import android.util.Log;
+import android.net.Uri;
+import android.app.PendingIntent;
+import android.support.v7.media.MediaItemStatus;
+
+/**
+ * MediaSessionManager manages a media session as a queue. It supports common
+ * queuing behaviors such as enqueue/remove of media items, pause/resume/stop,
+ * etc.
+ *
+ * Actual playback of a single media item is abstracted into a set of
+ * callbacks MediaSessionManager.Callback, and is handled outside this class.
+ */
+public class MediaSessionManager {
+    private static final String TAG = "MediaSessionManager";
+
+    private String mSessionId;
+    private String mItemId;
+    private String mCurItemId;
+    private boolean mIsPlaying = true;
+    private Callback mCallback;
+    private List<MediaQueueItem> mQueue = new ArrayList<MediaQueueItem>();
+
+    public MediaSessionManager() {
+    }
+
+    // Queue item (this maps to the ENQUEUE in the API which queues the item)
+    public MediaQueueItem enqueue(String sid, Uri uri, PendingIntent receiver) {
+        // fail if queue id is invalid
+        if (sid != null && !sid.equals(mSessionId)) {
+            Log.d(TAG, "invalid session id, mSessionId="+mSessionId+", sid="+sid);
+            return null;
+        }
+
+        // if queue id is unspecified, invalidate current queue
+        if (sid == null) {
+            invalidate();
+        }
+
+        mQueue.add(new MediaQueueItem(mSessionId, mItemId, uri, receiver));
+
+        if (updatePlaybackState()) {
+            MediaQueueItem item = findItem(mItemId);
+            mItemId = inc(mItemId);
+            if (item == null) {
+                Log.d(TAG, "item not found after it's added");
+            }
+            return item;
+        }
+
+        removeItem(mItemId, MediaItemStatus.PLAYBACK_STATE_ERROR);
+        return null;
+    }
+
+    public MediaQueueItem remove(String sid, String iid) {
+        if (sid == null || !sid.equals(mSessionId)) {
+            return null;
+        }
+        return removeItem(iid, MediaItemStatus.PLAYBACK_STATE_CANCELED);
+    }
+
+    // handles ERROR / COMPLETION
+    public MediaQueueItem finish(boolean error) {
+        return removeItem(mCurItemId, error ? MediaItemStatus.PLAYBACK_STATE_ERROR :
+                MediaItemStatus.PLAYBACK_STATE_FINISHED);
+    }
+
+    public MediaQueueItem seek(String sid, String iid, long pos) {
+        if (sid == null || !sid.equals(mSessionId)) {
+            return null;
+        }
+        for (int i = 0; i < mQueue.size(); i++) {
+            MediaQueueItem item = mQueue.get(i);
+            if (iid.equals(item.getItemId())) {
+                if (pos != item.getContentPosition()) {
+                    item.setContentPosition(pos);
+                    if (item.getState() == MediaItemStatus.PLAYBACK_STATE_PLAYING
+                            || item.getState() == MediaItemStatus.PLAYBACK_STATE_PAUSED) {
+                        if (mCallback != null) {
+                            mCallback.onSeek(pos);
+                        }
+                    }
+                }
+                return item;
+            }
+        }
+        return null;
+    }
+
+    public MediaQueueItem getCurrentItem() {
+        return getStatus(mSessionId, mCurItemId);
+    }
+
+    public MediaQueueItem getStatus(String sid, String iid) {
+        if (sid == null || !sid.equals(mSessionId)) {
+            return null;
+        }
+        for (int i = 0; i < mQueue.size(); i++) {
+            MediaQueueItem item = mQueue.get(i);
+            if (iid.equals(item.getItemId())) {
+                if (item.getState() == MediaItemStatus.PLAYBACK_STATE_PLAYING
+                        || item.getState() == MediaItemStatus.PLAYBACK_STATE_PAUSED) {
+                    if (mCallback != null) {
+                        mCallback.onGetStatus(item);
+                    }
+                }
+                return item;
+            }
+        }
+        return null;
+    }
+
+    public boolean pause(String sid) {
+        if (sid == null || !sid.equals(mSessionId)) {
+            return false;
+        }
+        mIsPlaying = false;
+        return updatePlaybackState();
+    }
+
+    public boolean resume(String sid) {
+        if (sid == null || !sid.equals(mSessionId)) {
+            return false;
+        }
+        mIsPlaying = true;
+        return updatePlaybackState();
+    }
+
+    public boolean stop(String sid) {
+        if (sid == null || !sid.equals(mSessionId)) {
+            return false;
+        }
+        clear();
+        return true;
+    }
+
+    public void setCallback(Callback cb) {
+        mCallback = cb;
+    }
+
+    @Override
+    public String toString() {
+        String result = "Media Queue: ";
+        if (!mQueue.isEmpty()) {
+            for (MediaQueueItem item : mQueue) {
+                result += "\n" + item.toString();
+            }
+        } else {
+            result += "<empty>";
+        }
+        return result;
+    }
+
+    private String inc(String id) {
+        return (id == null) ? "0" : Integer.toString(Integer.parseInt(id)+1);
+    }
+
+    // play the item at queue head
+    private void play() {
+        MediaQueueItem item = mQueue.get(0);
+        if (item.getState() == MediaItemStatus.PLAYBACK_STATE_PENDING
+                || item.getState() == MediaItemStatus.PLAYBACK_STATE_PAUSED) {
+            mCurItemId = item.getItemId();
+            if (mCallback != null) {
+                if (item.getState() == MediaItemStatus.PLAYBACK_STATE_PENDING) {
+                    mCallback.onNewItem(item.getUri());
+                }
+                mCallback.onStart();
+            }
+            item.setState(MediaItemStatus.PLAYBACK_STATE_PLAYING);
+        }
+    }
+
+    // stop the currently playing item
+    private void stop() {
+        MediaQueueItem item = mQueue.get(0);
+        if (item.getState() == MediaItemStatus.PLAYBACK_STATE_PLAYING
+                || item.getState() == MediaItemStatus.PLAYBACK_STATE_PAUSED) {
+            if (mCallback != null) {
+                mCallback.onStop();
+            }
+            item.setState(MediaItemStatus.PLAYBACK_STATE_FINISHED);
+        }
+    }
+
+    // pause the currently playing item
+    private void pause() {
+        MediaQueueItem item = mQueue.get(0);
+        if (item.getState() == MediaItemStatus.PLAYBACK_STATE_PENDING
+                || item.getState() == MediaItemStatus.PLAYBACK_STATE_PLAYING) {
+            if (mCallback != null) {
+                if (item.getState() == MediaItemStatus.PLAYBACK_STATE_PENDING) {
+                    mCallback.onNewItem(item.getUri());
+                } else if (item.getState() == MediaItemStatus.PLAYBACK_STATE_PLAYING) {
+                    mCallback.onPause();
+                }
+            }
+            item.setState(MediaItemStatus.PLAYBACK_STATE_PAUSED);
+        }
+    }
+
+    private void clear() {
+        if (mQueue.size() > 0) {
+            stop();
+            mQueue.clear();
+        }
+    }
+
+    private void invalidate() {
+        clear();
+        mSessionId = inc(mSessionId);
+        mItemId = "0";
+        mIsPlaying = true;
+    }
+
+    private boolean updatePlaybackState() {
+        if (mQueue.isEmpty()) {
+            return true;
+        }
+
+        if (mIsPlaying) {
+            play();
+        } else {
+            pause();
+        }
+        return true;
+    }
+
+    private MediaQueueItem findItem(String iid) {
+        for (MediaQueueItem item : mQueue) {
+            if (iid.equals(item.getItemId())) {
+                return item;
+            }
+        }
+        return null;
+    }
+
+    private MediaQueueItem removeItem(String iid, int state) {
+        List<MediaQueueItem> queue =
+                new ArrayList<MediaQueueItem>(mQueue.size());
+        MediaQueueItem found = null;
+        for (MediaQueueItem item : mQueue) {
+            if (iid.equals(item.getItemId())) {
+                if (item.getState() == MediaItemStatus.PLAYBACK_STATE_PLAYING
+                        || item.getState() == MediaItemStatus.PLAYBACK_STATE_PAUSED) {
+                    stop();
+                }
+                item.setState(state);
+                found = item;
+            } else {
+                queue.add(item);
+            }
+        }
+        if (found != null) {
+            mQueue = queue;
+            updatePlaybackState();
+        }
+        return found;
+    }
+
+    public interface Callback {
+        public void onStart();
+        public void onPause();
+        public void onStop();
+        public void onSeek(long pos);
+        public void onGetStatus(MediaQueueItem item);
+        public void onNewItem(Uri uri);
+    }
+}
diff --git a/samples/Support7Demos/src/com/example/android/supportv7/media/OverlayDisplayWindow.java b/samples/Support7Demos/src/com/example/android/supportv7/media/OverlayDisplayWindow.java
new file mode 100644
index 0000000..11a2889
--- /dev/null
+++ b/samples/Support7Demos/src/com/example/android/supportv7/media/OverlayDisplayWindow.java
@@ -0,0 +1,362 @@
+/*
+ * Copyright (C) 2012 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.supportv7.media;
+import com.example.android.supportv7.R;
+
+import android.content.Context;
+import android.graphics.SurfaceTexture;
+import android.hardware.display.DisplayManager;
+import android.util.Log;
+import android.view.Display;
+import android.util.DisplayMetrics;
+import android.view.GestureDetector;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.ScaleGestureDetector;
+import android.view.TextureView;
+import android.view.View;
+import android.view.Surface;
+import android.view.WindowManager;
+import android.view.TextureView.SurfaceTextureListener;
+import android.widget.TextView;
+
+/**
+ * Manages an overlay display window, used for simulating remote playback.
+ */
+public class OverlayDisplayWindow {
+    private static final String TAG = "OverlayDisplayWindow";
+    private static final boolean DEBUG = false;
+
+    private final float INITIAL_SCALE = 0.5f;
+    private final float MIN_SCALE = 0.3f;
+    private final float MAX_SCALE = 1.0f;
+    private final float WINDOW_ALPHA = 0.8f;
+
+    // When true, disables support for moving and resizing the overlay.
+    // The window is made non-touchable, which makes it possible to
+    // directly interact with the content underneath.
+    private final boolean DISABLE_MOVE_AND_RESIZE = false;
+
+    private final Context mContext;
+    private final int mWidth;
+    private final int mHeight;
+    private final int mGravity;
+    private OverlayWindowListener mListener;
+    private final String mTitle;
+
+    private final DisplayManager mDisplayManager;
+    private final WindowManager mWindowManager;
+
+
+    private final Display mDefaultDisplay;
+    private final DisplayMetrics mDefaultDisplayMetrics = new DisplayMetrics();
+
+    private View mWindowContent;
+    private WindowManager.LayoutParams mWindowParams;
+    private TextureView mTextureView;
+    private TextView mTitleTextView;
+
+    private GestureDetector mGestureDetector;
+    private ScaleGestureDetector mScaleGestureDetector;
+
+    private boolean mWindowVisible;
+    private int mWindowX;
+    private int mWindowY;
+    private float mWindowScale;
+
+    private float mLiveTranslationX;
+    private float mLiveTranslationY;
+    private float mLiveScale = 1.0f;
+
+    public OverlayDisplayWindow(Context context, String name,
+            int width, int height, int gravity) {
+        mContext = context;
+        mWidth = width;
+        mHeight = height;
+        mGravity = gravity;
+        mTitle = name;
+
+        mDisplayManager = (DisplayManager)context.getSystemService(
+                Context.DISPLAY_SERVICE);
+        mWindowManager = (WindowManager)context.getSystemService(
+                Context.WINDOW_SERVICE);
+
+        mDefaultDisplay = mWindowManager.getDefaultDisplay();
+        updateDefaultDisplayInfo();
+
+        createWindow();
+    }
+
+    public void setOverlayWindowListener(OverlayWindowListener listener) {
+        mListener = listener;
+    }
+
+    public Context getContext() {
+        return mContext;
+    }
+
+    public void show() {
+        if (!mWindowVisible) {
+            mDisplayManager.registerDisplayListener(mDisplayListener, null);
+            if (!updateDefaultDisplayInfo()) {
+                mDisplayManager.unregisterDisplayListener(mDisplayListener);
+                return;
+            }
+
+            clearLiveState();
+            updateWindowParams();
+            mWindowManager.addView(mWindowContent, mWindowParams);
+            mWindowVisible = true;
+        }
+    }
+
+    public void dismiss() {
+        if (mWindowVisible) {
+            mDisplayManager.unregisterDisplayListener(mDisplayListener);
+            mWindowManager.removeView(mWindowContent);
+            mWindowVisible = false;
+        }
+    }
+
+    public void relayout() {
+        if (mWindowVisible) {
+            updateWindowParams();
+            mWindowManager.updateViewLayout(mWindowContent, mWindowParams);
+        }
+    }
+
+    public void updateAspectRatio(int width, int height) {
+        if (mWidth * height < mHeight * width) {
+            mTextureView.getLayoutParams().width = mWidth;
+            mTextureView.getLayoutParams().height = mWidth * height / width;
+        } else {
+            mTextureView.getLayoutParams().width = mHeight * width / height;
+            mTextureView.getLayoutParams().height = mHeight;
+        }
+        relayout();
+    }
+
+    private boolean updateDefaultDisplayInfo() {
+        mDefaultDisplay.getMetrics(mDefaultDisplayMetrics);
+        return true;
+    }
+
+    private void createWindow() {
+        LayoutInflater inflater = LayoutInflater.from(mContext);
+
+        mWindowContent = inflater.inflate(
+                R.layout.overlay_display_window, null);
+        mWindowContent.setOnTouchListener(mOnTouchListener);
+
+        mTextureView = (TextureView)mWindowContent.findViewById(
+                R.id.overlay_display_window_texture);
+        mTextureView.setPivotX(0);
+        mTextureView.setPivotY(0);
+        mTextureView.getLayoutParams().width = mWidth;
+        mTextureView.getLayoutParams().height = mHeight;
+        mTextureView.setOpaque(false);
+        mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
+
+        mTitleTextView = (TextView)mWindowContent.findViewById(
+                R.id.overlay_display_window_title);
+        mTitleTextView.setText(mTitle);
+
+        mWindowParams = new WindowManager.LayoutParams(
+                WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+        mWindowParams.flags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+                | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
+                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+                | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+        if (DISABLE_MOVE_AND_RESIZE) {
+            mWindowParams.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+        }
+        mWindowParams.alpha = WINDOW_ALPHA;
+        mWindowParams.gravity = Gravity.TOP | Gravity.LEFT;
+        mWindowParams.setTitle(mTitle);
+
+        mGestureDetector = new GestureDetector(mContext, mOnGestureListener);
+        mScaleGestureDetector = new ScaleGestureDetector(mContext, mOnScaleGestureListener);
+
+        // Set the initial position and scale.
+        // The position and scale will be clamped when the display is first shown.
+        mWindowX = (mGravity & Gravity.LEFT) == Gravity.LEFT ?
+                0 : mDefaultDisplayMetrics.widthPixels;
+        mWindowY = (mGravity & Gravity.TOP) == Gravity.TOP ?
+                0 : mDefaultDisplayMetrics.heightPixels;
+        Log.d(TAG, mDefaultDisplayMetrics.toString());
+        mWindowScale = INITIAL_SCALE;
+
+        // calculate and save initial settings
+        updateWindowParams();
+        saveWindowParams();
+    }
+
+    private void updateWindowParams() {
+        float scale = mWindowScale * mLiveScale;
+        scale = Math.min(scale, (float)mDefaultDisplayMetrics.widthPixels / mWidth);
+        scale = Math.min(scale, (float)mDefaultDisplayMetrics.heightPixels / mHeight);
+        scale = Math.max(MIN_SCALE, Math.min(MAX_SCALE, scale));
+
+        float offsetScale = (scale / mWindowScale - 1.0f) * 0.5f;
+        int width = (int)(mWidth * scale);
+        int height = (int)(mHeight * scale);
+        int x = (int)(mWindowX + mLiveTranslationX - width * offsetScale);
+        int y = (int)(mWindowY + mLiveTranslationY - height * offsetScale);
+        x = Math.max(0, Math.min(x, mDefaultDisplayMetrics.widthPixels - width));
+        y = Math.max(0, Math.min(y, mDefaultDisplayMetrics.heightPixels - height));
+
+        if (DEBUG) {
+            Log.d(TAG, "updateWindowParams: scale=" + scale
+                    + ", offsetScale=" + offsetScale
+                    + ", x=" + x + ", y=" + y
+                    + ", width=" + width + ", height=" + height);
+        }
+
+        mTextureView.setScaleX(scale);
+        mTextureView.setScaleY(scale);
+
+        mTextureView.setTranslationX(
+                (mWidth - mTextureView.getLayoutParams().width) * scale / 2);
+        mTextureView.setTranslationY(
+                (mHeight - mTextureView.getLayoutParams().height) * scale / 2);
+
+        mWindowParams.x = x;
+        mWindowParams.y = y;
+        mWindowParams.width = width;
+        mWindowParams.height = height;
+    }
+
+    private void saveWindowParams() {
+        mWindowX = mWindowParams.x;
+        mWindowY = mWindowParams.y;
+        mWindowScale = mTextureView.getScaleX();
+        clearLiveState();
+    }
+
+    private void clearLiveState() {
+        mLiveTranslationX = 0f;
+        mLiveTranslationY = 0f;
+        mLiveScale = 1.0f;
+    }
+
+    private final DisplayManager.DisplayListener mDisplayListener =
+            new DisplayManager.DisplayListener() {
+        @Override
+        public void onDisplayAdded(int displayId) {
+        }
+
+        @Override
+        public void onDisplayChanged(int displayId) {
+            if (displayId == mDefaultDisplay.getDisplayId()) {
+                if (updateDefaultDisplayInfo()) {
+                    relayout();
+                } else {
+                    dismiss();
+                }
+            }
+        }
+
+        @Override
+        public void onDisplayRemoved(int displayId) {
+            if (displayId == mDefaultDisplay.getDisplayId()) {
+                dismiss();
+            }
+        }
+    };
+
+    private final SurfaceTextureListener mSurfaceTextureListener =
+            new SurfaceTextureListener() {
+        @Override
+        public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture,
+                int width, int height) {
+            if (mListener != null) {
+                mListener.onWindowCreated(new Surface(surfaceTexture));
+            }
+        }
+
+        @Override
+        public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
+            if (mListener != null) {
+                mListener.onWindowDestroyed();
+            }
+            return true;
+        }
+
+        @Override
+        public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture,
+                int width, int height) {
+        }
+
+        @Override
+        public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
+        }
+    };
+
+    private final View.OnTouchListener mOnTouchListener = new View.OnTouchListener() {
+        @Override
+        public boolean onTouch(View view, MotionEvent event) {
+            // Work in screen coordinates.
+            final float oldX = event.getX();
+            final float oldY = event.getY();
+            event.setLocation(event.getRawX(), event.getRawY());
+
+            mGestureDetector.onTouchEvent(event);
+            mScaleGestureDetector.onTouchEvent(event);
+
+            switch (event.getActionMasked()) {
+                case MotionEvent.ACTION_UP:
+                case MotionEvent.ACTION_CANCEL:
+                    saveWindowParams();
+                    break;
+            }
+
+            // Revert to window coordinates.
+            event.setLocation(oldX, oldY);
+            return true;
+        }
+    };
+
+    private final GestureDetector.OnGestureListener mOnGestureListener =
+            new GestureDetector.SimpleOnGestureListener() {
+        @Override
+        public boolean onScroll(MotionEvent e1, MotionEvent e2,
+                float distanceX, float distanceY) {
+            mLiveTranslationX -= distanceX;
+            mLiveTranslationY -= distanceY;
+            relayout();
+            return true;
+        }
+    };
+
+    private final ScaleGestureDetector.OnScaleGestureListener mOnScaleGestureListener =
+            new ScaleGestureDetector.SimpleOnScaleGestureListener() {
+        @Override
+        public boolean onScale(ScaleGestureDetector detector) {
+            mLiveScale *= detector.getScaleFactor();
+            relayout();
+            return true;
+        }
+    };
+
+    // Watches for significant changes in the overlay display window lifecycle.
+    public interface OverlayWindowListener {
+        public void onWindowCreated(Surface surface);
+        public void onWindowDestroyed();
+    }
+}
\ No newline at end of file
diff --git a/samples/Support7Demos/src/com/example/android/supportv7/media/SampleMediaRouteProvider.java b/samples/Support7Demos/src/com/example/android/supportv7/media/SampleMediaRouteProvider.java
index 916710c..2ab61a5 100644
--- a/samples/Support7Demos/src/com/example/android/supportv7/media/SampleMediaRouteProvider.java
+++ b/samples/Support7Demos/src/com/example/android/supportv7/media/SampleMediaRouteProvider.java
@@ -26,6 +26,7 @@
 import android.media.MediaRouter;
 import android.net.Uri;
 import android.os.Bundle;
+import android.app.PendingIntent;
 import android.support.v7.media.MediaControlIntent;
 import android.support.v7.media.MediaItemStatus;
 import android.support.v7.media.MediaRouteProvider;
@@ -34,9 +35,8 @@
 import android.support.v7.media.MediaRouteDescriptor;
 import android.util.Log;
 import android.widget.Toast;
-
+import android.view.Gravity;
 import java.util.ArrayList;
-import java.util.UUID;
 
 /**
  * Demonstrates how to create a custom media route provider.
@@ -77,6 +77,14 @@
     public static final String DATA_PLAYBACK_COUNT =
             "com.example.android.supportv7.media.EXTRA_PLAYBACK_COUNT";
 
+    /*
+     * Set ENABLE_QUEUEING to true to test queuing on MRP. This will make
+     * MRP expose the following two experimental hidden APIs:
+     *     ACTION_ENQUEUE
+     *     ACTION_REMOVE
+     */
+    public static final boolean ENABLE_QUEUEING = false;
+
     private static final ArrayList<IntentFilter> CONTROL_FILTERS;
     static {
         IntentFilter f1 = new IntentFilter();
@@ -88,11 +96,39 @@
         f2.addAction(MediaControlIntent.ACTION_PLAY);
         f2.addDataScheme("http");
         f2.addDataScheme("https");
+        f2.addDataScheme("rtsp");
+        f2.addDataScheme("file");
         addDataTypeUnchecked(f2, "video/*");
 
+        IntentFilter f3 = new IntentFilter();
+        f3.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
+        f3.addAction(MediaControlIntent.ACTION_SEEK);
+        f3.addAction(MediaControlIntent.ACTION_GET_STATUS);
+        f3.addAction(MediaControlIntent.ACTION_PAUSE);
+        f3.addAction(MediaControlIntent.ACTION_RESUME);
+        f3.addAction(MediaControlIntent.ACTION_STOP);
+
+        IntentFilter f4 = new IntentFilter();
+        f4.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
+        f4.addAction(MediaControlIntent.ACTION_ENQUEUE);
+        f4.addDataScheme("http");
+        f4.addDataScheme("https");
+        f4.addDataScheme("rtsp");
+        f4.addDataScheme("file");
+        addDataTypeUnchecked(f4, "video/*");
+
+        IntentFilter f5 = new IntentFilter();
+        f5.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
+        f5.addAction(MediaControlIntent.ACTION_REMOVE);
+
         CONTROL_FILTERS = new ArrayList<IntentFilter>();
         CONTROL_FILTERS.add(f1);
         CONTROL_FILTERS.add(f2);
+        CONTROL_FILTERS.add(f3);
+        if (ENABLE_QUEUEING) {
+            CONTROL_FILTERS.add(f4);
+            CONTROL_FILTERS.add(f5);
+        }
     }
 
     private static void addDataTypeUnchecked(IntentFilter filter, String type) {
@@ -104,7 +140,7 @@
     }
 
     private int mVolume = 5;
-    private int mPlaybackCount;
+    private int mEnqueueCount;
 
     public SampleMediaRouteProvider(Context context) {
         super(context);
@@ -145,36 +181,51 @@
                 new MediaRouteProviderDescriptor.Builder()
                 .addRoute(routeDescriptor1)
                 .addRoute(routeDescriptor2)
-                .addDiscoverableControlFilters(CONTROL_FILTERS)
                 .build();
         setDescriptor(providerDescriptor);
     }
 
-    private String generateStreamId() {
-        return UUID.randomUUID().toString();
+    private void showToast(String msg) {
+        Toast toast = Toast.makeText(getContext(),
+                "[provider] " + msg, Toast.LENGTH_LONG);
+        toast.setGravity(Gravity.TOP, 0, 100);
+        toast.show();
     }
 
     private final class SampleRouteController extends MediaRouteProvider.RouteController {
         private final String mRouteId;
+        // Create an overlay display window (used for simulating the remote playback only)
+        private final OverlayDisplayWindow mOverlay = new OverlayDisplayWindow(getContext(),
+                getContext().getResources().getString(R.string.sample_media_route_provider_remote),
+                1024, 768, Gravity.CENTER);
+        private final MediaPlayerWrapper mMediaPlayer = new MediaPlayerWrapper(getContext());
+        private final MediaSessionManager mSessionManager = new MediaSessionManager();
 
         public SampleRouteController(String routeId) {
             mRouteId = routeId;
+            mSessionManager.setCallback(mMediaPlayer);
+            mOverlay.setOverlayWindowListener(mMediaPlayer);
+            mMediaPlayer.setCallback(new MediaPlayerCallback());
             Log.d(TAG, mRouteId + ": Controller created");
         }
 
         @Override
         public void onRelease() {
             Log.d(TAG, mRouteId + ": Controller released");
+            mMediaPlayer.release();
         }
 
         @Override
         public void onSelect() {
             Log.d(TAG, mRouteId + ": Selected");
+            mOverlay.show();
         }
 
         @Override
         public void onUnselect() {
             Log.d(TAG, mRouteId + ": Unselected");
+            mMediaPlayer.onStop();
+            mOverlay.dismiss();
         }
 
         @Override
@@ -193,6 +244,45 @@
             }
         }
 
+        @Override
+        public boolean onControlRequest(Intent intent, ControlRequestCallback callback) {
+            Log.d(TAG, mRouteId + ": Received control request " + intent);
+            String action = intent.getAction();
+            if (intent.hasCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) {
+                boolean success = false;
+                if (action.equals(MediaControlIntent.ACTION_PLAY)) {
+                    success = handlePlay(intent, callback);
+                } else if (action.equals(MediaControlIntent.ACTION_ENQUEUE)) {
+                    success = handleEnqueue(intent, callback);
+                } else if (action.equals(MediaControlIntent.ACTION_REMOVE)) {
+                    success = handleRemove(intent, callback);
+                } else if (action.equals(MediaControlIntent.ACTION_SEEK)) {
+                    success = handleSeek(intent, callback);
+                } else if (action.equals(MediaControlIntent.ACTION_GET_STATUS)) {
+                    success = handleGetStatus(intent, callback);
+                } else if (action.equals(MediaControlIntent.ACTION_PAUSE)) {
+                    success = handlePause(intent, callback);
+                } else if (action.equals(MediaControlIntent.ACTION_RESUME)) {
+                    success = handleResume(intent, callback);
+                } else if (action.equals(MediaControlIntent.ACTION_STOP)) {
+                    success = handleStop(intent, callback);
+                }
+                Log.d(TAG, mSessionManager.toString());
+                return success;
+            }
+
+            if (action.equals(ACTION_GET_STATISTICS)
+                    && intent.hasCategory(CATEGORY_SAMPLE_ROUTE)) {
+                Bundle data = new Bundle();
+                data.putInt(DATA_PLAYBACK_COUNT, mEnqueueCount);
+                if (callback != null) {
+                    callback.onResult(data);
+                }
+                return true;
+            }
+            return false;
+        }
+
         private void setVolumeInternal(int volume) {
             if (volume >= 0 && volume <= VOLUME_MAX) {
                 mVolume = volume;
@@ -201,66 +291,198 @@
             }
         }
 
-        @Override
-        public boolean onControlRequest(Intent intent, ControlRequestCallback callback) {
-            Log.d(TAG, mRouteId + ": Received control request " + intent);
-            if (intent.getAction().equals(MediaControlIntent.ACTION_PLAY)
-                    && intent.hasCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
-                    && intent.getData() != null) {
-                mPlaybackCount +=1;
-
-                Uri uri = intent.getData();
-                int queueBehavior = intent.getIntExtra(
-                        MediaControlIntent.EXTRA_ITEM_QUEUE_BEHAVIOR,
-                        MediaControlIntent.ITEM_QUEUE_BEHAVIOR_PLAY_NOW);
-                double contentPosition = intent.getDoubleExtra(
-                        MediaControlIntent.EXTRA_ITEM_CONTENT_POSITION, 0);
-                Bundle metadata = intent.getBundleExtra(MediaControlIntent.EXTRA_ITEM_METADATA);
-                Bundle headers = intent.getBundleExtra(
-                        MediaControlIntent.EXTRA_ITEM_HTTP_HEADERS);
-
-                Log.d(TAG, mRouteId + ": Received play request, uri=" + uri
-                        + ", queueBehavior=" + queueBehavior
-                        + ", contentPosition=" + contentPosition
-                        + ", metadata=" + metadata
-                        + ", headers=" + headers);
-
-                if (uri.toString().contains("hats")) {
-                    // Simulate generating an error whenever the uri contains the word 'hats'.
-                    Toast.makeText(getContext(), "Route rejected play request: uri=" + uri
-                            + ", no hats allowed!", Toast.LENGTH_LONG).show();
-                    if (callback != null) {
-                        callback.onError("Simulated error.  No hats allowed!", null);
-                    }
-                } else {
-                    Toast.makeText(getContext(), "Route received play request: uri=" + uri,
-                            Toast.LENGTH_LONG).show();
-                    String streamId = generateStreamId();
-                    if (callback != null) {
-                        MediaItemStatus status = new MediaItemStatus.Builder(
-                                MediaItemStatus.PLAYBACK_STATE_PLAYING)
-                                .setContentPosition(contentPosition)
-                                .build();
-
-                        Bundle result = new Bundle();
-                        result.putString(MediaControlIntent.EXTRA_ITEM_ID, streamId);
-                        result.putBundle(MediaControlIntent.EXTRA_ITEM_STATUS, status.asBundle());
-                        callback.onResult(result);
-                    }
-                }
-                return true;
-            }
-
-            if (intent.getAction().equals(ACTION_GET_STATISTICS)
-                    && intent.hasCategory(CATEGORY_SAMPLE_ROUTE)) {
-                Bundle data = new Bundle();
-                data.putInt(DATA_PLAYBACK_COUNT, mPlaybackCount);
-                if (callback != null) {
-                    callback.onResult(data);
-                }
-                return true;
+        private boolean handlePlay(Intent intent, ControlRequestCallback callback) {
+            String sid = intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID);
+            if (sid == null || mSessionManager.stop(sid)) {
+                Log.d(TAG, "handleEnqueue");
+                return handleEnqueue(intent, callback);
             }
             return false;
         }
+
+        private boolean handleEnqueue(Intent intent, ControlRequestCallback callback) {
+            if (intent.getData() == null) {
+                return false;
+            }
+
+            mEnqueueCount +=1;
+
+            boolean enqueue = intent.getAction().equals(MediaControlIntent.ACTION_ENQUEUE);
+            Uri uri = intent.getData();
+            String sid = intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID);
+            long pos = intent.getLongExtra(MediaControlIntent.EXTRA_ITEM_CONTENT_POSITION, 0);
+            Bundle metadata = intent.getBundleExtra(MediaControlIntent.EXTRA_ITEM_METADATA);
+            Bundle headers = intent.getBundleExtra(MediaControlIntent.EXTRA_ITEM_HTTP_HEADERS);
+            PendingIntent receiver = (PendingIntent)intent.getParcelableExtra(
+                    MediaControlIntent.EXTRA_ITEM_STATUS_UPDATE_RECEIVER);
+
+            Log.d(TAG, mRouteId + ": Received " + (enqueue?"enqueue":"play") + " request"
+                    + ", uri=" + uri
+                    + ", sid=" + sid
+                    + ", pos=" + pos
+                    + ", metadata=" + metadata
+                    + ", headers=" + headers
+                    + ", receiver=" + receiver);
+            MediaQueueItem item = mSessionManager.enqueue(sid, uri, receiver);
+            if (callback != null) {
+                if (item != null) {
+                    Bundle result = new Bundle();
+                    result.putString(MediaControlIntent.EXTRA_SESSION_ID, item.getSessionId());
+                    result.putString(MediaControlIntent.EXTRA_ITEM_ID, item.getItemId());
+                    result.putBundle(MediaControlIntent.EXTRA_ITEM_STATUS,
+                            item.getStatus().asBundle());
+                    callback.onResult(result);
+                } else {
+                    callback.onError("Failed to open " + uri.toString(), null);
+                }
+            }
+            return true;
+        }
+
+        private boolean handleRemove(Intent intent, ControlRequestCallback callback) {
+            String sid = intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID);
+            String iid = intent.getStringExtra(MediaControlIntent.EXTRA_ITEM_ID);
+            MediaQueueItem item = mSessionManager.remove(sid, iid);
+            if (callback != null) {
+                if (item != null) {
+                    Bundle result = new Bundle();
+                    result.putBundle(MediaControlIntent.EXTRA_ITEM_STATUS,
+                            item.getStatus().asBundle());
+                    callback.onResult(result);
+                } else {
+                    callback.onError("Failed to remove" +
+                            ", sid=" + sid + ", iid=" + iid, null);
+                }
+            }
+            return (item != null);
+        }
+
+        private boolean handleSeek(Intent intent, ControlRequestCallback callback) {
+            String sid = intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID);
+            String iid = intent.getStringExtra(MediaControlIntent.EXTRA_ITEM_ID);
+            long pos = intent.getLongExtra(MediaControlIntent.EXTRA_ITEM_CONTENT_POSITION, 0);
+            Log.d(TAG, mRouteId + ": Received seek request, pos=" + pos);
+            MediaQueueItem item = mSessionManager.seek(sid, iid, pos);
+            if (callback != null) {
+                if (item != null) {
+                    Bundle result = new Bundle();
+                    result.putBundle(MediaControlIntent.EXTRA_ITEM_STATUS,
+                            item.getStatus().asBundle());
+                    callback.onResult(result);
+                } else {
+                    callback.onError("Failed to seek" +
+                            ", sid=" + sid + ", iid=" + iid + ", pos=" + pos, null);
+                }
+            }
+            return (item != null);
+        }
+
+        private boolean handleGetStatus(Intent intent, ControlRequestCallback callback) {
+            String sid = intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID);
+            String iid = intent.getStringExtra(MediaControlIntent.EXTRA_ITEM_ID);
+            MediaQueueItem item = mSessionManager.getStatus(sid, iid);
+            if (callback != null) {
+                if (item != null) {
+                    Bundle result = new Bundle();
+                    result.putBundle(MediaControlIntent.EXTRA_ITEM_STATUS,
+                            item.getStatus().asBundle());
+                    callback.onResult(result);
+                } else {
+                    callback.onError("Failed to get status" +
+                            ", sid=" + sid + ", iid=" + iid, null);
+                }
+            }
+            return (item != null);
+        }
+
+        private boolean handlePause(Intent intent, ControlRequestCallback callback) {
+            String sid = intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID);
+            boolean success = mSessionManager.pause(sid);
+            if (callback != null) {
+                if (success) {
+                    callback.onResult(null);
+                } else {
+                    callback.onError("Failed to pause, sid=" + sid, null);
+                }
+            }
+            return success;
+        }
+
+        private boolean handleResume(Intent intent, ControlRequestCallback callback) {
+            String sid = intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID);
+            boolean success = mSessionManager.resume(sid);
+            if (callback != null) {
+                if (success) {
+                    callback.onResult(null);
+                } else {
+                    callback.onError("Failed to resume, sid=" + sid, null);
+                }
+            }
+            return success;
+        }
+
+        private boolean handleStop(Intent intent, ControlRequestCallback callback) {
+            String sid = intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID);
+            boolean success = mSessionManager.stop(sid);
+            if (callback != null) {
+                if (success) {
+                    callback.onResult(null);
+                } else {
+                    callback.onError("Failed to stop, sid=" + sid, null);
+                }
+            }
+            return success;
+        }
+
+        private void handleFinish(boolean error) {
+            MediaQueueItem item = mSessionManager.finish(error);
+            if (item != null) {
+                handleStatusChange(item);
+            }
+        }
+
+        private void handleStatusChange(MediaQueueItem item) {
+            if (item == null) {
+                item = mSessionManager.getCurrentItem();
+            }
+            if (item != null) {
+                PendingIntent receiver = item.getUpdateReceiver();
+                if (receiver != null) {
+                    Intent intent = new Intent();
+                    intent.putExtra(MediaControlIntent.EXTRA_SESSION_ID, item.getSessionId());
+                    intent.putExtra(MediaControlIntent.EXTRA_ITEM_ID, item.getItemId());
+                    intent.putExtra(MediaControlIntent.EXTRA_ITEM_STATUS,
+                            item.getStatus().asBundle());
+                    try {
+                        receiver.send(getContext(), 0, intent);
+                        Log.d(TAG, mRouteId + ": Sending status update from provider");
+                    } catch (PendingIntent.CanceledException e) {
+                        Log.d(TAG, mRouteId + ": Failed to send status update!");
+                    }
+                }
+            }
+        }
+
+        private final class MediaPlayerCallback extends MediaPlayerWrapper.Callback {
+            @Override
+            public void onError() {
+                handleFinish(true);
+            }
+
+            @Override
+            public void onCompletion() {
+                handleFinish(false);
+            }
+
+            @Override
+            public void onStatusChanged() {
+                handleStatusChange(null);
+            }
+
+            @Override
+            public void onSizeChanged(int width, int height) {
+                mOverlay.updateAspectRatio(width, height);
+            }
+        }
     }
 }
\ No newline at end of file
diff --git a/samples/Support7Demos/src/com/example/android/supportv7/media/SampleMediaRouterActivity.java b/samples/Support7Demos/src/com/example/android/supportv7/media/SampleMediaRouterActivity.java
index 7e570f1..cca7e10 100644
--- a/samples/Support7Demos/src/com/example/android/supportv7/media/SampleMediaRouterActivity.java
+++ b/samples/Support7Demos/src/com/example/android/supportv7/media/SampleMediaRouterActivity.java
@@ -18,29 +18,61 @@
 
 import com.example.android.supportv7.R;
 
+import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.BroadcastReceiver;
+import android.content.res.Resources;
+import android.content.DialogInterface;
+import android.app.PendingIntent;
+import android.app.Presentation;
 import android.net.Uri;
+import android.os.Handler;
 import android.os.Bundle;
+import android.os.SystemClock;
+import android.support.v4.app.FragmentManager;
 import android.support.v4.view.MenuItemCompat;
 import android.support.v7.app.ActionBarActivity;
 import android.support.v7.app.MediaRouteActionProvider;
+import android.support.v7.app.MediaRouteDiscoveryFragment;
 import android.support.v7.media.MediaControlIntent;
 import android.support.v7.media.MediaRouter;
+import android.support.v7.media.MediaRouter.Callback;
 import android.support.v7.media.MediaRouter.RouteInfo;
 import android.support.v7.media.MediaRouter.ProviderInfo;
 import android.support.v7.media.MediaRouteSelector;
+import android.support.v7.media.MediaItemStatus;
 import android.util.Log;
+import android.view.Gravity;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.View.OnClickListener;
-import android.widget.AdapterView.OnItemClickListener;
+import android.view.ViewGroup;
+import android.view.Display;
+import android.view.Surface;
+import android.view.SurfaceView;
+import android.view.SurfaceHolder;
+import android.view.WindowManager;
 import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
 import android.widget.ArrayAdapter;
 import android.widget.Button;
+import android.widget.ImageButton;
 import android.widget.ListView;
 import android.widget.TextView;
 import android.widget.Toast;
+import android.widget.FrameLayout;
+import android.widget.TabHost;
+import android.widget.TabHost.TabSpec;
+import android.widget.TabHost.OnTabChangeListener;
+import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+
+
+import java.util.ArrayList;
+import java.util.List;
+import java.io.File;
 
 /**
  * <h3>Media Router Support Activity</h3>
@@ -52,15 +84,222 @@
  * </p>
  */
 public class SampleMediaRouterActivity extends ActionBarActivity {
-    private final String TAG = "MediaRouterSupport";
+    private static final String TAG = "MediaRouterSupport";
+    private static final String DISCOVERY_FRAGMENT_TAG = "DiscoveryFragment";
+    private static final String ACTION_STATUS_CHANGE =
+            "com.example.android.supportv7.media.ACTION_STATUS_CHANGE";
 
     private MediaRouter mMediaRouter;
     private MediaRouteSelector mSelector;
-    private ArrayAdapter<MediaItem> mMediaItems;
+    private LibraryAdapter mLibraryItems;
+    private PlaylistAdapter mPlayListItems;
     private TextView mInfoTextView;
-    private ListView mMediaListView;
-    private Button mPlayButton;
-    private Button mStatisticsButton;
+    private ListView mLibraryView;
+    private ListView mPlayListView;
+    private ImageButton mPauseResumeButton;
+    private ImageButton mStopButton;
+    private SeekBar mSeekBar;
+    private String mStatsInfo;
+    private boolean mPaused;
+    private boolean mNeedResume;
+    private boolean mSeeking;
+    private long mLastStatusTime;
+    private PlaylistAdapter mSavedPlaylist;
+
+    private final Handler mHandler = new Handler();
+    private final Runnable mUpdateSeekRunnable = new Runnable() {
+        @Override
+        public void run() {
+            updateProgress(getCheckedMediaQueueItem());
+            // update Ui every 1 second
+            mHandler.postDelayed(this, 1000);
+        }
+    };
+
+    private final MediaPlayerWrapper mMediaPlayer = new MediaPlayerWrapper(this);
+    private final MediaPlayerWrapper.Callback mMediaPlayerCB =
+            new MediaPlayerWrapper.Callback()  {
+        @Override
+        public void onError() {
+            mPlayer.onFinish(true);
+        }
+
+        @Override
+        public void onCompletion() {
+            mPlayer.onFinish(false);
+        }
+
+        @Override
+        public void onSizeChanged(int width, int height) {
+            mLocalPlayer.updateSize(width, height);
+        }
+
+        @Override
+        public void onStatusChanged() {
+            if (!mSeeking) {
+                updateUi();
+            }
+        }
+    };
+
+    private final RemotePlayer mRemotePlayer = new RemotePlayer();
+    private final LocalPlayer mLocalPlayer = new LocalPlayer();
+    private Player mPlayer;
+    private MediaSessionManager.Callback mPlayerCB;
+
+    private final MediaRouter.Callback mMediaRouterCB = new MediaRouter.Callback() {
+        // Return a custom callback that will simply log all of the route events
+        // for demonstration purposes.
+        @Override
+        public void onRouteAdded(MediaRouter router, RouteInfo route) {
+            Log.d(TAG, "onRouteAdded: route=" + route);
+        }
+
+        @Override
+        public void onRouteChanged(MediaRouter router, RouteInfo route) {
+            Log.d(TAG, "onRouteChanged: route=" + route);
+            mPlayer.showStatistics();
+        }
+
+        @Override
+        public void onRouteRemoved(MediaRouter router, RouteInfo route) {
+            Log.d(TAG, "onRouteRemoved: route=" + route);
+        }
+
+        @Override
+        public void onRouteSelected(MediaRouter router, RouteInfo route) {
+            Log.d(TAG, "onRouteSelected: route=" + route);
+
+            Player player = mPlayer;
+            MediaSessionManager.Callback playerCB = mPlayerCB;
+
+            if (route.supportsControlCategory(
+                    MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) {
+                Intent enqueueIntent = new Intent(MediaControlIntent.ACTION_ENQUEUE);
+                enqueueIntent.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
+                enqueueIntent.setDataAndType(Uri.parse("http://"), "video/mp4");
+
+                Intent removeIntent = new Intent(MediaControlIntent.ACTION_REMOVE);
+                removeIntent.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
+
+                // Remote Playback:
+                //   If route supports remote queuing, let it manage the queue;
+                //   otherwise, manage the queue locally and feed it one item at a time
+                if (route.supportsControlRequest(enqueueIntent)
+                 && route.supportsControlRequest(removeIntent)) {
+                    player = mRemotePlayer;
+                } else {
+                    player = mLocalPlayer;
+                }
+                playerCB = mRemotePlayer;
+                mRemotePlayer.reset();
+            } else {
+                // Local Playback:
+                //   Use local player and feed media player one item at a time
+                player = mLocalPlayer;
+                playerCB = mMediaPlayer;
+            }
+
+            if (player != mPlayer || playerCB != mPlayerCB) {
+                // save current playlist
+                PlaylistAdapter playlist = new PlaylistAdapter();
+                for (int i = 0; i < mPlayListItems.getCount(); i++) {
+                    MediaQueueItem item = mPlayListItems.getItem(i);
+                    if (item.getState() == MediaItemStatus.PLAYBACK_STATE_PLAYING
+                            || item.getState() == MediaItemStatus.PLAYBACK_STATE_PAUSED) {
+                        long position = item.getContentPosition();
+                        long timeDelta = mPaused ? 0 :
+                                (SystemClock.elapsedRealtime() - mLastStatusTime);
+                        item.setContentPosition(position + timeDelta);
+                    }
+                    playlist.add(item);
+                }
+
+                // switch players
+                mPlayer.stop();
+                mPaused = false;
+                mLocalPlayer.setCallback(playerCB);
+                mPlayerCB = playerCB;
+                mPlayer = player;
+                mPlayer.showStatistics();
+                mLocalPlayer.updatePresentation();
+
+                // migrate playlist to new route
+                int count = playlist.getCount();
+                if (isRemoteQueue()) {
+                    // if queuing is managed remotely, only enqueue the first
+                    // item, as we need to have the returned session id to
+                    // enqueue the rest of the playlist items
+                    mSavedPlaylist = playlist;
+                    count = 1;
+                }
+                for (int i = 0; i < count; i++) {
+                    final MediaQueueItem item = playlist.getItem(i);
+                    mPlayer.enqueue(item.getUri(), item.getContentPosition());
+                }
+            }
+            updateUi();
+        }
+
+        @Override
+        public void onRouteUnselected(MediaRouter router, RouteInfo route) {
+            Log.d(TAG, "onRouteUnselected: route=" + route);
+            mPlayer.showStatistics();
+        }
+
+        @Override
+        public void onRouteVolumeChanged(MediaRouter router, RouteInfo route) {
+            Log.d(TAG, "onRouteVolumeChanged: route=" + route);
+        }
+
+        @Override
+        public void onRoutePresentationDisplayChanged(
+                MediaRouter router, RouteInfo route) {
+            Log.d(TAG, "onRoutePresentationDisplayChanged: route=" + route);
+        }
+
+        @Override
+        public void onProviderAdded(MediaRouter router, ProviderInfo provider) {
+            Log.d(TAG, "onRouteProviderAdded: provider=" + provider);
+        }
+
+        @Override
+        public void onProviderRemoved(MediaRouter router, ProviderInfo provider) {
+            Log.d(TAG, "onRouteProviderRemoved: provider=" + provider);
+        }
+
+        @Override
+        public void onProviderChanged(MediaRouter router, ProviderInfo provider) {
+            Log.d(TAG, "onRouteProviderChanged: provider=" + provider);
+        }
+    };
+
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            Log.d(TAG, "Received status update: " + intent);
+            if (intent.getAction().equals(ACTION_STATUS_CHANGE)) {
+                String sid = intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID);
+                String iid = intent.getStringExtra(MediaControlIntent.EXTRA_ITEM_ID);
+                MediaItemStatus status = MediaItemStatus.fromBundle(
+                    intent.getBundleExtra(MediaControlIntent.EXTRA_ITEM_STATUS));
+
+                if (status.getPlaybackState() ==
+                        MediaItemStatus.PLAYBACK_STATE_FINISHED) {
+                    mPlayer.onFinish(false);
+                } else if (status.getPlaybackState() ==
+                        MediaItemStatus.PLAYBACK_STATE_ERROR) {
+                    mPlayer.onFinish(true);
+                    showToast("Error while playing item" +
+                            ", sid " + sid + ", iid " + iid);
+                } else {
+                    if (!mSeeking) {
+                        updateUi();
+                    }
+                }
+            }
+        }
+    };
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -78,65 +317,196 @@
                 .addControlCategory(SampleMediaRouteProvider.CATEGORY_SAMPLE_ROUTE)
                 .build();
 
-        // Populate an array adapter with fake media items.
+        // Add a fragment to take care of media route discovery.
+        // This fragment automatically adds or removes a callback whenever the activity
+        // is started or stopped.
+        FragmentManager fm = getSupportFragmentManager();
+        DiscoveryFragment fragment = (DiscoveryFragment)fm.findFragmentByTag(
+                DISCOVERY_FRAGMENT_TAG);
+        if (fragment == null) {
+            fragment = new DiscoveryFragment(mMediaRouterCB);
+            fragment.setRouteSelector(mSelector);
+            fm.beginTransaction()
+                    .add(fragment, DISCOVERY_FRAGMENT_TAG)
+                    .commit();
+        } else {
+            fragment.setCallback(mMediaRouterCB);
+            fragment.setRouteSelector(mSelector);
+        }
+
+        // Populate an array adapter with streaming media items.
         String[] mediaNames = getResources().getStringArray(R.array.media_names);
         String[] mediaUris = getResources().getStringArray(R.array.media_uris);
-        mMediaItems = new ArrayAdapter<MediaItem>(this,
-                android.R.layout.simple_list_item_single_choice, android.R.id.text1);
+        mLibraryItems = new LibraryAdapter();
         for (int i = 0; i < mediaNames.length; i++) {
-            mMediaItems.add(new MediaItem(mediaNames[i], Uri.parse(mediaUris[i])));
+            mLibraryItems.add(new MediaItem(
+                    "[streaming] "+mediaNames[i], Uri.parse(mediaUris[i])));
         }
 
+        // Scan local /sdcard/ directory for media files.
+        String sdcard = "/sdcard/";
+        File file = new File(sdcard);
+        File list[] = file.listFiles();
+        for (int i = 0; i < list.length; i++) {
+            String filename = list[i].getName();
+            if (filename.matches(".*\\.(m4v|mp4)")) {
+                mLibraryItems.add(new MediaItem(
+                        "[local] "+filename, Uri.parse("file:///sdcard/" + filename)));
+            }
+        }
+
+        mPlayListItems = new PlaylistAdapter();
+
         // Initialize the layout.
         setContentView(R.layout.sample_media_router);
 
-        mInfoTextView = (TextView)findViewById(R.id.info);
+        TabHost tabHost=(TabHost)findViewById(R.id.tabHost);
+        tabHost.setup();
+        String tabName = getResources().getString(R.string.library_tab_text);
+        TabSpec spec1=tabHost.newTabSpec(tabName);
+        spec1.setContent(R.id.tab1);
+        spec1.setIndicator(tabName);
 
-        mMediaListView = (ListView)findViewById(R.id.media);
-        mMediaListView.setAdapter(mMediaItems);
-        mMediaListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
-        mMediaListView.setOnItemClickListener(new OnItemClickListener() {
+        tabName = getResources().getString(R.string.playlist_tab_text);
+        TabSpec spec2=tabHost.newTabSpec(tabName);
+        spec2.setIndicator(tabName);
+        spec2.setContent(R.id.tab2);
+
+        tabName = getResources().getString(R.string.statistics_tab_text);
+        TabSpec spec3=tabHost.newTabSpec(tabName);
+        spec3.setIndicator(tabName);
+        spec3.setContent(R.id.tab3);
+
+        tabHost.addTab(spec1);
+        tabHost.addTab(spec2);
+        tabHost.addTab(spec3);
+        tabHost.setOnTabChangedListener(new OnTabChangeListener() {
+            @Override
+            public void onTabChanged(String arg0) {
+                if (arg0.equals(getResources().getString(
+                        R.string.statistics_tab_text))) {
+                    mPlayer.showStatistics();
+                }
+                updateUi();
+            }
+        });
+
+        mLibraryView = (ListView) findViewById(R.id.media);
+        mLibraryView.setAdapter(mLibraryItems);
+        mLibraryView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
+        mLibraryView.setOnItemClickListener(new OnItemClickListener() {
             @Override
             public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                 updateButtons();
             }
         });
 
-        mPlayButton = (Button)findViewById(R.id.play_button);
-        mPlayButton.setOnClickListener(new OnClickListener() {
+        mPlayListView = (ListView) findViewById(R.id.playlist);
+        mPlayListView.setAdapter(mPlayListItems);
+        mPlayListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
+        mPlayListView.setOnItemClickListener(new OnItemClickListener() {
             @Override
-            public void onClick(View v) {
-                play();
+            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+                updateButtons();
             }
         });
 
-        mStatisticsButton = (Button)findViewById(R.id.statistics_button);
-        mStatisticsButton.setOnClickListener(new OnClickListener() {
+        mInfoTextView = (TextView) findViewById(R.id.info);
+
+        mPauseResumeButton = (ImageButton)findViewById(R.id.pause_resume_button);
+        mPauseResumeButton.setOnClickListener(new OnClickListener() {
             @Override
             public void onClick(View v) {
-                showStatistics();
+                if (!mPaused) {
+                    mPlayer.pause();
+                } else {
+                    mPlayer.resume();
+                }
             }
         });
+
+        mStopButton = (ImageButton)findViewById(R.id.stop_button);
+        mStopButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                mPlayer.stop();
+                clearContent();
+            }
+        });
+
+        mSeekBar = (SeekBar) findViewById(R.id.seekbar);
+        mSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
+            @Override
+            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+                MediaQueueItem item = getCheckedMediaQueueItem();
+                if (fromUser && item != null && item.getContentDuration() > 0) {
+                    long pos = progress * item.getContentDuration() / 100;
+                    mPlayer.seek(item.getSessionId(), item.getItemId(), pos);
+                    item.setContentPosition(pos);
+                    mLastStatusTime = SystemClock.elapsedRealtime();
+                }
+            }
+            @Override
+            public void onStartTrackingTouch(SeekBar seekBar) {
+                mSeeking = true;
+            }
+            @Override
+            public void onStopTrackingTouch(SeekBar seekBar) {
+                mSeeking = false;
+                updateUi();
+            }
+        });
+
+        // Schedule Ui update
+        mHandler.postDelayed(mUpdateSeekRunnable, 1000);
+
+        // Use local playback with media player by default
+        mLocalPlayer.onCreate();
+        mMediaPlayer.setCallback(mMediaPlayerCB);
+        mLocalPlayer.setCallback(mMediaPlayer);
+        mPlayerCB = mMediaPlayer;
+        mPlayer = mLocalPlayer;
+
+        // Register broadcast receiver to receive status update from MRP
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(SampleMediaRouterActivity.ACTION_STATUS_CHANGE);
+        registerReceiver(mReceiver, filter);
     }
 
     @Override
-    protected void onResume() {
+    public void onStart() {
         // Be sure to call the super class.
-        super.onResume();
-
-        // Listen for changes to media routes.
-        mMediaRouter.addCallback(mSelector, mCallback,
-                MediaRouter.CALLBACK_FLAG_UNFILTERED_EVENTS);
-        updateRouteDescription();
+        super.onStart();
+        mPlayer.showStatistics();
     }
 
     @Override
-    protected void onPause() {
-        // Be sure to call the super class.
+    public void onPause() {
+        // pause media player for local playback case only
+        if (!isRemotePlayback() && !mPaused) {
+            mNeedResume = true;
+            mPlayer.pause();
+        }
         super.onPause();
+    }
 
-        // Stop listening for changes to media routes.
-        mMediaRouter.removeCallback(mCallback);
+    @Override
+    public void onResume() {
+        // resume media player for local playback case only
+        if (!isRemotePlayback() && mNeedResume) {
+            mPlayer.resume();
+            mNeedResume = false;
+        }
+        super.onResume();
+    }
+
+    @Override
+    public void onDestroy() {
+        // Unregister broadcast receiver
+        unregisterReceiver(mReceiver);
+        mPlayer.stop();
+        mMediaPlayer.release();
+        super.onDestroy();
     }
 
     @Override
@@ -158,179 +528,876 @@
 
     private void updateRouteDescription() {
         RouteInfo route = mMediaRouter.getSelectedRoute();
-        mInfoTextView.setText("Currently selected route: " + route.getName()
-                + " from provider " + route.getProvider().getPackageName()
-                + ", description: " + route.getDescription());
+        mInfoTextView.setText("Currently selected route:"
+                + "\nName: " + route.getName()
+                + "\nProvider: " + route.getProvider().getPackageName()
+                + "\nDescription: " + route.getDescription()
+                + "\nStatistics: " + mStatsInfo);
         updateButtons();
+        mLocalPlayer.updatePresentation();
+    }
+
+    private void clearContent() {
+        //TO-DO: clear surface view
     }
 
     private void updateButtons() {
         MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute();
-
-        MediaItem item = getCheckedMediaItem();
-        if (item != null) {
-            mPlayButton.setEnabled(route.supportsControlRequest(makePlayIntent(item)));
-        } else {
-            mPlayButton.setEnabled(false);
-        }
-
-        mStatisticsButton.setEnabled(route.supportsControlRequest(makeStatisticsIntent()));
+        // show pause or resume icon depending on current state
+        mPauseResumeButton.setImageResource(mPaused ?
+                R.drawable.ic_media_play : R.drawable.ic_media_pause);
+        // only enable seek bar when duration is known
+        MediaQueueItem item = getCheckedMediaQueueItem();
+        mSeekBar.setEnabled(item != null && item.getContentDuration() > 0);
     }
 
-    private void play() {
-        final MediaItem item = getCheckedMediaItem();
-        if (item == null) {
-            return;
-        }
-
-        MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute();
-        Intent intent = makePlayIntent(item);
-        if (route.supportsControlRequest(intent)) {
-            MediaRouter.ControlRequestCallback callback =
-                    new MediaRouter.ControlRequestCallback() {
-                @Override
-                public void onResult(Bundle data) {
-                    String streamId = data != null ? data.getString(
-                            MediaControlIntent.EXTRA_ITEM_ID) : null;
-
-                    Log.d(TAG, "Play request succeeded: data=" + data + " , streamId=" + streamId);
-                    Toast.makeText(SampleMediaRouterActivity.this,
-                            "Now playing " + item.mName,
-                            Toast.LENGTH_LONG).show();
+    private void updateProgress(MediaQueueItem queueItem) {
+        // Estimate content position from last status time and elapsed time.
+        // (Note this might be slightly out of sync with remote side, however
+        // it avoids frequent polling the MRP.)
+        int progress = 0;
+        if (queueItem != null) {
+            int state = queueItem.getState();
+            long duration = queueItem.getContentDuration();
+            if (duration <= 0) {
+                if (state == MediaItemStatus.PLAYBACK_STATE_PLAYING
+                        || state == MediaItemStatus.PLAYBACK_STATE_PAUSED) {
+                    updateUi();
                 }
-
-                @Override
-                public void onError(String error, Bundle data) {
-                    Log.d(TAG, "Play request failed: error=" + error + ", data=" + data);
-                    Toast.makeText(SampleMediaRouterActivity.this,
-                            "Unable to play " + item.mName + ", error: " + error,
-                            Toast.LENGTH_LONG).show();
-                }
-            };
-
-            Log.d(TAG, "Sending play request: intent=" + intent);
-            route.sendControlRequest(intent, callback);
-        } else {
-            Log.d(TAG, "Play request not supported: intent=" + intent);
-            Toast.makeText(SampleMediaRouterActivity.this,
-                    "Play not supported for " + item.mName, Toast.LENGTH_LONG).show();
+            } else {
+                long position = queueItem.getContentPosition();
+                long timeDelta = mPaused ? 0 :
+                        (SystemClock.elapsedRealtime() - mLastStatusTime);
+                progress = (int)(100.0 * (position + timeDelta) / duration);
+            }
         }
+        mSeekBar.setProgress(progress);
     }
 
-    private void showStatistics() {
-        MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute();
-        Intent intent = makeStatisticsIntent();
-        if (route.supportsControlRequest(intent)) {
-            MediaRouter.ControlRequestCallback callback = new MediaRouter.ControlRequestCallback() {
-                @Override
-                public void onResult(Bundle data) {
-                    Log.d(TAG, "Statistics request succeeded: data=" + data);
-                    if (data != null) {
-                        int playbackCount = data.getInt(
-                                SampleMediaRouteProvider.DATA_PLAYBACK_COUNT, -1);
-                        Toast.makeText(SampleMediaRouterActivity.this,
-                                "Total playback count: " + playbackCount,
-                                Toast.LENGTH_LONG).show();
-                    } else {
-                        Toast.makeText(SampleMediaRouterActivity.this,
-                                "Statistics query did not return any data",
-                                Toast.LENGTH_LONG).show();
-                    }
-                }
+    private void updateUi() {
+        updatePlaylist();
+        updateButtons();
+    }
 
-                @Override
-                public void onError(String error, Bundle data) {
-                    Log.d(TAG, "Statistics request failed: error=" + error + ", data=" + data);
-                    Toast.makeText(SampleMediaRouterActivity.this,
-                            "Unable to query statistics, error: " + error,
-                            Toast.LENGTH_LONG).show();
-                }
-            };
-
-            Log.d(TAG, "Sent statistics request: intent=" + intent);
-            route.sendControlRequest(intent, callback);
-        } else {
-            Log.d(TAG, "Statistics request not supported: intent=" + intent);
-            Toast.makeText(SampleMediaRouterActivity.this,
-                    "Statistics not supported.", Toast.LENGTH_LONG).show();
+    private void updatePlaylist() {
+        Log.d(TAG, "updatePlaylist");
+        final PlaylistAdapter playlist = new PlaylistAdapter();
+        // make a copy of current playlist
+        for (int i = 0; i < mPlayListItems.getCount(); i++) {
+            playlist.add(mPlayListItems.getItem(i));
         }
-    }
+        // clear mPlayListItems first, items will be added back when we get
+        // status back from provider.
+        mPlayListItems.clear();
+        mPlayListView.invalidate();
 
-    private Intent makePlayIntent(MediaItem item) {
-        Intent intent = new Intent(MediaControlIntent.ACTION_PLAY);
-        intent.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
-        intent.setDataAndType(item.mUri, "video/mp4");
-        return intent;
-    }
-
-    private Intent makeStatisticsIntent() {
-        Intent intent = new Intent(SampleMediaRouteProvider.ACTION_GET_STATISTICS);
-        intent.addCategory(SampleMediaRouteProvider.CATEGORY_SAMPLE_ROUTE);
-        return intent;
+        for (int i = 0; i < playlist.getCount(); i++) {
+            final MediaQueueItem item = playlist.getItem(i);
+            final boolean update = (i == playlist.getCount() - 1);
+            mPlayer.getStatus(item, update);
+        }
     }
 
     private MediaItem getCheckedMediaItem() {
-        int index = mMediaListView.getCheckedItemPosition();
-        if (index >= 0 && index < mMediaItems.getCount()) {
-            return mMediaItems.getItem(index);
+        int index = mLibraryView.getCheckedItemPosition();
+        if (index >= 0 && index < mLibraryItems.getCount()) {
+            return mLibraryItems.getItem(index);
         }
         return null;
     }
 
-    private final MediaRouter.Callback mCallback = new MediaRouter.Callback() {
-        @Override
-        public void onRouteAdded(MediaRouter router, RouteInfo route) {
-            Log.d(TAG, "onRouteAdded: route=" + route);
+    private MediaQueueItem getCheckedMediaQueueItem() {
+        int count = mPlayListView.getCount();
+        int index = mPlayListView.getCheckedItemPosition();
+        if (count > 0) {
+            if (index < 0 || index >= count) {
+                index = 0;
+                mPlayListView.setItemChecked(0, true);
+            }
+            return mPlayListItems.getItem(index);
+        }
+        return null;
+    }
+
+    private void enqueuePlaylist() {
+        if (mSavedPlaylist != null) {
+            final PlaylistAdapter playlist = mSavedPlaylist;
+            mSavedPlaylist = null;
+            // migrate playlist (except for the 1st item) to new route
+            for (int i = 1; i < playlist.getCount(); i++) {
+                final MediaQueueItem item = playlist.getItem(i);
+                mPlayer.enqueue(item.getUri(), item.getContentPosition());
+            }
+        }
+    }
+
+    private boolean isRemoteQueue() {
+        return mPlayer == mRemotePlayer;
+    }
+
+    private boolean isRemotePlayback() {
+        return mPlayerCB == mRemotePlayer;
+    }
+
+    private void showToast(String msg) {
+        Toast toast = Toast.makeText(SampleMediaRouterActivity.this,
+                "[app] " + msg, Toast.LENGTH_LONG);
+        toast.setGravity(Gravity.TOP, 0, 100);
+        toast.show();
+    }
+
+    private abstract class Player {
+        abstract void enqueue(final Uri uri, long pos);
+        abstract void remove(final MediaQueueItem item);
+        abstract void seek(String sid, String iid, long pos);
+        abstract void getStatus(final MediaQueueItem item, final boolean update);
+        abstract void pause();
+        abstract void resume();
+        abstract void stop();
+        abstract void showStatistics();
+        abstract void onFinish(boolean error);
+    }
+
+    private class LocalPlayer extends Player implements SurfaceHolder.Callback {
+        private final MediaSessionManager mSessionManager = new MediaSessionManager();
+        private String mSessionId;
+        // The presentation to show on the secondary display.
+        private DemoPresentation mPresentation;
+        private SurfaceView mSurfaceView;
+        private FrameLayout mLayout;
+        private int mVideoWidth;
+        private int mVideoHeight;
+
+        public void onCreate() {
+            mLayout = (FrameLayout)findViewById(R.id.player);
+            mSurfaceView = (SurfaceView)findViewById(R.id.surface_view);
+            SurfaceHolder holder = mSurfaceView.getHolder();
+            holder.addCallback(mLocalPlayer);
+        }
+
+        public void setCallback(MediaSessionManager.Callback cb) {
+            mSessionManager.setCallback(cb);
         }
 
         @Override
-        public void onRouteChanged(MediaRouter router, RouteInfo route) {
-            Log.d(TAG, "onRouteChanged: route=" + route);
+        public void enqueue(final Uri uri, long pos) {
+            Log.d(TAG, "LocalPlayer: enqueue, uri=" + uri + ", pos=" + pos);
+            MediaQueueItem playlistItem = mSessionManager.enqueue(mSessionId, uri, null);
+            mSessionId = playlistItem.getSessionId();
+            mPlayListItems.add(playlistItem);
+            if (pos > 0) {
+                // Seek to initial position if needed
+                mPlayer.seek(mSessionId, playlistItem.getItemId(), pos);
+            }
+            updateUi();
+        }
+
+        @Override
+        public void remove(final MediaQueueItem item) {
+            Log.d(TAG, "LocalPlayer: remove, item=" + item);
+            mSessionManager.remove(item.getSessionId(), item.getItemId());
+            updateUi();
+        }
+
+        @Override
+        public void seek(String sid, String iid, long pos) {
+            Log.d(TAG, "LocalPlayer: seek, sid=" + sid + ", iid=" + iid);
+            mSessionManager.seek(sid, iid, pos);
+        }
+
+        @Override
+        public void getStatus(final MediaQueueItem item, final boolean update) {
+            Log.d(TAG, "LocalPlayer: getStatus, item=" + item + ", update=" + update);
+            MediaQueueItem playlistItem =
+                    mSessionManager.getStatus(item.getSessionId(), item.getItemId());
+            if (playlistItem != null) {
+                mLastStatusTime = playlistItem.getStatus().getTimestamp();
+                mPlayListItems.add(item);
+                mPlayListView.invalidate();
+            }
+            if (update) {
+                clearContent();
+                updateButtons();
+            }
+        }
+
+        @Override
+        public void pause() {
+            Log.d(TAG, "LocalPlayer: pause");
+            mSessionManager.pause(mSessionId);
+            mPaused = true;
+            updateUi();
+        }
+
+        @Override
+        public void resume() {
+            Log.d(TAG, "LocalPlayer: resume");
+            mSessionManager.resume(mSessionId);
+            mPaused = false;
+            updateUi();
+        }
+
+        @Override
+        public void stop() {
+            Log.d(TAG, "LocalPlayer: stop");
+            mSessionManager.stop(mSessionId);
+            mSessionId = null;
+            mPaused = false;
+            // For demo purpose, invalidate remote session when local session
+            // is stopped (note this is not necessary, remote player could reuse
+            // the same session)
+            mRemotePlayer.reset();
+            updateUi();
+        }
+
+        @Override
+        public void showStatistics() {
+            Log.d(TAG, "LocalPlayer: showStatistics");
+            mStatsInfo = null;
+            if (isRemotePlayback()) {
+                mRemotePlayer.showStatistics();
+            }
             updateRouteDescription();
         }
 
         @Override
-        public void onRouteRemoved(MediaRouter router, RouteInfo route) {
-            Log.d(TAG, "onRouteRemoved: route=" + route);
+        public void onFinish(boolean error) {
+            MediaQueueItem item = mSessionManager.finish(error);
+            updateUi();
+            if (error) {
+                showToast("Failed to play item " + item.getUri());
+            }
+        }
+
+        // SurfaceHolder.Callback
+        @Override
+        public void surfaceChanged(SurfaceHolder holder, int format,
+                int width, int height) {
+            Log.d(TAG, "surfaceChanged "+width+"x"+height);
+            mMediaPlayer.onWindowCreated(holder.getSurface());
         }
 
         @Override
-        public void onRouteSelected(MediaRouter router, RouteInfo route) {
-            Log.d(TAG, "onRouteSelected: route=" + route);
-            updateRouteDescription();
+        public void surfaceCreated(SurfaceHolder holder) {
+            Log.d(TAG, "surfaceCreated");
+            mMediaPlayer.onWindowCreated(holder.getSurface());
+            mLocalPlayer.updateSize(mVideoWidth, mVideoHeight);
         }
 
         @Override
-        public void onRouteUnselected(MediaRouter router, RouteInfo route) {
-            Log.d(TAG, "onRouteUnselected: route=" + route);
-            updateRouteDescription();
+        public void surfaceDestroyed(SurfaceHolder holder) {
+            Log.d(TAG, "surfaceDestroyed");
+        }
+
+        private void updateSize(int width, int height) {
+            if (width > 0 && height > 0) {
+                if (mPresentation == null) {
+                    int surfaceWidth = mLayout.getWidth();
+                    int surfaceHeight = mLayout.getHeight();
+
+                    // Calculate the new size of mSurfaceView, so that video is centered
+                    // inside the framelayout with proper letterboxing/pillarboxing
+                    ViewGroup.LayoutParams lp = mSurfaceView.getLayoutParams();
+                    if (surfaceWidth * height < surfaceHeight * width) {
+                        // Black bars on top&bottom, mSurfaceView has full layout width,
+                        // while height is derived from video's aspect ratio
+                        lp.width = surfaceWidth;
+                        lp.height = surfaceWidth * height / width;
+                    } else {
+                        // Black bars on left&right, mSurfaceView has full layout height,
+                        // while width is derived from video's aspect ratio
+                        lp.width = surfaceHeight * width / height;
+                        lp.height = surfaceHeight;
+                    }
+                    Log.d(TAG, "video rect is "+lp.width+"x"+lp.height);
+                    mSurfaceView.setLayoutParams(lp);
+                } else {
+                    mPresentation.updateSize(width, height);
+                }
+                mVideoWidth = width;
+                mVideoHeight = height;
+            } else {
+                mVideoWidth = mVideoHeight = 0;
+            }
+        }
+
+        private void updatePresentation() {
+            // Get the current route and its presentation display.
+            MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute();
+            Display presentationDisplay = route != null ? route.getPresentationDisplay() : null;
+
+            // Dismiss the current presentation if the display has changed.
+            if (mPresentation != null && mPresentation.getDisplay() != presentationDisplay) {
+                Log.i(TAG, "Dismissing presentation because the current route no longer "
+                        + "has a presentation display.");
+                mPresentation.dismiss();
+                mPresentation = null;
+            }
+
+            // Show a new presentation if needed.
+            if (mPresentation == null && presentationDisplay != null) {
+                Log.i(TAG, "Showing presentation on display: " + presentationDisplay);
+                mPresentation = new DemoPresentation(
+                        SampleMediaRouterActivity.this, presentationDisplay);
+                mPresentation.setOnDismissListener(mOnDismissListener);
+                try {
+                    mPresentation.show();
+                } catch (WindowManager.InvalidDisplayException ex) {
+                    Log.w(TAG, "Couldn't show presentation!  Display was removed in "
+                            + "the meantime.", ex);
+                    mPresentation = null;
+                }
+            }
+
+            if (mPresentation != null || route.supportsControlCategory(
+                    MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) {
+                mSurfaceView.setVisibility(View.GONE);
+                mLayout.setVisibility(View.GONE);
+            } else {
+                mLayout.setVisibility(View.VISIBLE);
+                mSurfaceView.setVisibility(View.VISIBLE);
+            }
+        }
+
+        // Listens for when presentations are dismissed.
+        private final DialogInterface.OnDismissListener mOnDismissListener =
+                new DialogInterface.OnDismissListener() {
+            @Override
+            public void onDismiss(DialogInterface dialog) {
+                if (dialog == mPresentation) {
+                    Log.i(TAG, "Presentation was dismissed.");
+                    mPresentation = null;
+                    updatePresentation();
+                }
+            }
+        };
+
+        private final class DemoPresentation extends Presentation {
+            private SurfaceView mSurfaceView;
+
+            public DemoPresentation(Context context, Display display) {
+                super(context, display);
+            }
+
+            @Override
+            protected void onCreate(Bundle savedInstanceState) {
+                // Be sure to call the super class.
+                super.onCreate(savedInstanceState);
+
+                // Get the resources for the context of the presentation.
+                // Notice that we are getting the resources from the context
+                // of the presentation.
+                Resources r = getContext().getResources();
+
+                // Inflate the layout.
+                setContentView(R.layout.sample_media_router_presentation);
+
+                // Set up the surface view for visual interest.
+                mSurfaceView = (SurfaceView)findViewById(R.id.surface_view);
+                SurfaceHolder holder = mSurfaceView.getHolder();
+                holder.addCallback(mLocalPlayer);
+            }
+
+            public void updateSize(int width, int height) {
+                int surfaceHeight=getWindow().getDecorView().getHeight();
+                int surfaceWidth=getWindow().getDecorView().getWidth();
+                ViewGroup.LayoutParams lp = mSurfaceView.getLayoutParams();
+                if (surfaceWidth * height < surfaceHeight * width) {
+                    lp.width = surfaceWidth;
+                    lp.height = surfaceWidth * height / width;
+                } else {
+                    lp.width = surfaceHeight * width / height;
+                    lp.height = surfaceHeight;
+                }
+                Log.d(TAG, "video rect is "+lp.width+"x"+lp.height);
+                mSurfaceView.setLayoutParams(lp);
+            }
+
+            public void clearContent() {
+                //TO-DO: clear surface view
+            }
+        }
+    }
+
+    private class RemotePlayer extends Player implements MediaSessionManager.Callback {
+        private MediaQueueItem mQueueItem;
+        private MediaQueueItem mPlaylistItem;
+        private String mSessionId;
+        private String mItemId;
+        private long mPosition;
+
+        public void reset() {
+            mQueueItem = null;
+            mPlaylistItem = null;
+            mSessionId = null;
+            mItemId = null;
+            mPosition = 0;
+        }
+
+        // MediaSessionManager.Callback
+        @Override
+        public void onStart() {
+            resume();
         }
 
         @Override
-        public void onRouteVolumeChanged(MediaRouter router, RouteInfo route) {
-            Log.d(TAG, "onRouteVolumeChanged: route=" + route);
+        public void onPause() {
+            pause();
         }
 
         @Override
-        public void onRoutePresentationDisplayChanged(MediaRouter router, RouteInfo route) {
-            Log.d(TAG, "onRoutePresentationDisplayChanged: route=" + route);
+        public void onStop() {
+            stop();
         }
 
         @Override
-        public void onProviderAdded(MediaRouter router, ProviderInfo provider) {
-            Log.d(TAG, "onRouteProviderAdded: provider=" + provider);
+        public void onSeek(long pos) {
+            // If we're currently performing a Play/Enqueue, do not seek
+            // until we get the result back (or we may not have valid session
+            // and item ids); otherwise do the seek now
+            if (mSessionId != null) {
+                seek(mSessionId, mItemId, pos);
+            }
+            // Set current position to seek-to position, actual position will
+            // be updated when next getStatus is completed.
+            mPosition = pos;
         }
 
         @Override
-        public void onProviderRemoved(MediaRouter router, ProviderInfo provider) {
-            Log.d(TAG, "onRouteProviderRemoved: provider=" + provider);
+        public void onGetStatus(MediaQueueItem item) {
+            if (mQueueItem != null) {
+                mPlaylistItem = item;
+                getStatus(mQueueItem, false);
+            }
         }
 
         @Override
-        public void onProviderChanged(MediaRouter router, ProviderInfo provider) {
-            Log.d(TAG, "onRouteProviderChanged: provider=" + provider);
+        public void onNewItem(Uri uri) {
+            mPosition = 0;
+            play(uri, false, 0);
         }
-    };
+
+        // Player API
+        @Override
+        public void enqueue(final Uri uri, long pos) {
+            play(uri, true, pos);
+        }
+
+        @Override
+        public void remove(final MediaQueueItem item) {
+            MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute();
+            Intent intent = makeRemoveIntent(item);
+            if (route.supportsControlRequest(intent)) {
+                MediaRouter.ControlRequestCallback callback =
+                        new MediaRouter.ControlRequestCallback() {
+                    @Override
+                    public void onResult(Bundle data) {
+                        MediaItemStatus status = MediaItemStatus.fromBundle(
+                                data.getBundle(MediaControlIntent.EXTRA_ITEM_STATUS));
+                        Log.d(TAG, "Remove request succeeded: status=" + status.toString());
+                        updateUi();
+                    }
+
+                    @Override
+                    public void onError(String error, Bundle data) {
+                        Log.d(TAG, "Remove request failed: error=" + error + ", data=" + data);
+                    }
+                };
+
+                Log.d(TAG, "Sending remove request: intent=" + intent);
+                route.sendControlRequest(intent, callback);
+            } else {
+                Log.d(TAG, "Remove request not supported!");
+            }
+        }
+
+        @Override
+        public void seek(String sid, String iid, long pos) {
+            MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute();
+            Intent intent = makeSeekIntent(sid, iid, pos);
+            if (route.supportsControlRequest(intent)) {
+                MediaRouter.ControlRequestCallback callback =
+                        new MediaRouter.ControlRequestCallback() {
+                    @Override
+                    public void onResult(Bundle data) {
+                        MediaItemStatus status = MediaItemStatus.fromBundle(
+                                data.getBundle(MediaControlIntent.EXTRA_ITEM_STATUS));
+                        Log.d(TAG, "Seek request succeeded: status=" + status.toString());
+                    }
+
+                    @Override
+                    public void onError(String error, Bundle data) {
+                        Log.d(TAG, "Seek request failed: error=" + error + ", data=" + data);
+                    }
+                };
+
+                Log.d(TAG, "Sending seek request: intent=" + intent);
+                route.sendControlRequest(intent, callback);
+            } else {
+                Log.d(TAG, "Seek request not supported!");
+            }
+        }
+
+        @Override
+        public void getStatus(final MediaQueueItem item, final boolean update) {
+            MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute();
+            Intent intent = makeGetStatusIntent(item);
+            if (route.supportsControlRequest(intent)) {
+                MediaRouter.ControlRequestCallback callback =
+                        new MediaRouter.ControlRequestCallback() {
+                    @Override
+                    public void onResult(Bundle data) {
+                        if (data != null) {
+                            String sid = data.getString(MediaControlIntent.EXTRA_SESSION_ID);
+                            String iid = data.getString(MediaControlIntent.EXTRA_ITEM_ID);
+                            MediaItemStatus status = MediaItemStatus.fromBundle(
+                                    data.getBundle(MediaControlIntent.EXTRA_ITEM_STATUS));
+                            Log.d(TAG, "GetStatus request succeeded: status=" + status.toString());
+                            //showToast("GetStatus request succeeded " + item.mName);
+                            if (isRemoteQueue()) {
+                                int state = status.getPlaybackState();
+                                if (state == MediaItemStatus.PLAYBACK_STATE_PLAYING
+                                        || state == MediaItemStatus.PLAYBACK_STATE_PAUSED
+                                        || state == MediaItemStatus.PLAYBACK_STATE_PENDING) {
+                                    item.setState(state);
+                                    item.setContentPosition(status.getContentPosition());
+                                    item.setContentDuration(status.getContentDuration());
+                                    mLastStatusTime = status.getTimestamp();
+                                    mPlayListItems.add(item);
+                                    mPlayListView.invalidate();
+                                    // update buttons as the queue count might have changed
+                                    if (update) {
+                                        clearContent();
+                                        updateButtons();
+                                    }
+                                }
+                            } else {
+                                if (mPlaylistItem != null) {
+                                    mPlaylistItem.setContentPosition(status.getContentPosition());
+                                    mPlaylistItem.setContentDuration(status.getContentDuration());
+                                    mPlaylistItem = null;
+                                    updateButtons();
+                                }
+                            }
+                        }
+                    }
+
+                    @Override
+                    public void onError(String error, Bundle data) {
+                        Log.d(TAG, "GetStatus request failed: error=" + error + ", data=" + data);
+                        //showToast("Unable to get status ");
+                        if (isRemoteQueue()) {
+                            if (update) {
+                                clearContent();
+                                updateButtons();
+                            }
+                        }
+                    }
+                };
+
+                Log.d(TAG, "Sending GetStatus request: intent=" + intent);
+                route.sendControlRequest(intent, callback);
+            } else {
+                Log.d(TAG, "GetStatus request not supported!");
+            }
+        }
+
+        @Override
+        public void pause() {
+            Intent intent = makePauseIntent();
+            MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute();
+            if (route.supportsControlRequest(intent)) {
+                MediaRouter.ControlRequestCallback callback =
+                        new MediaRouter.ControlRequestCallback() {
+                    @Override
+                    public void onResult(Bundle data) {
+                        Log.d(TAG, "Pause request succeeded");
+                        if (isRemoteQueue()) {
+                            mPaused = true;
+                            updateUi();
+                        }
+                    }
+
+                    @Override
+                    public void onError(String error, Bundle data) {
+                        Log.d(TAG, "Pause request failed: error=" + error);
+                    }
+                };
+
+                Log.d(TAG, "Sending pause request");
+                route.sendControlRequest(intent, callback);
+            } else {
+                Log.d(TAG, "Pause request not supported!");
+            }
+        }
+
+        @Override
+        public void resume() {
+            Intent intent = makeResumeIntent();
+            MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute();
+            if (route.supportsControlRequest(intent)) {
+                MediaRouter.ControlRequestCallback callback =
+                        new MediaRouter.ControlRequestCallback() {
+                    @Override
+                    public void onResult(Bundle data) {
+                        Log.d(TAG, "Resume request succeeded");
+                        if (isRemoteQueue()) {
+                            mPaused = false;
+                            updateUi();
+                        }
+                    }
+
+                    @Override
+                    public void onError(String error, Bundle data) {
+                        Log.d(TAG, "Resume request failed: error=" + error);
+                    }
+                };
+
+                Log.d(TAG, "Sending resume request");
+                route.sendControlRequest(intent, callback);
+            } else {
+                Log.d(TAG, "Resume request not supported!");
+            }
+        }
+
+        @Override
+        public void stop() {
+            Intent intent = makeStopIntent();
+            MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute();
+            if (route.supportsControlRequest(intent)) {
+                MediaRouter.ControlRequestCallback callback =
+                        new MediaRouter.ControlRequestCallback() {
+                    @Override
+                    public void onResult(Bundle data) {
+                        Log.d(TAG, "Stop request succeeded");
+                        if (isRemoteQueue()) {
+                            // Reset mSessionId, so that next Play/Enqueue
+                            // starts a new session
+                            mQueueItem = null;
+                            mSessionId = null;
+                            mPaused = false;
+                            updateUi();
+                        }
+                    }
+
+                    @Override
+                    public void onError(String error, Bundle data) {
+                        Log.d(TAG, "Stop request failed: error=" + error);
+                    }
+                };
+
+                Log.d(TAG, "Sending stop request");
+                route.sendControlRequest(intent, callback);
+            } else {
+                Log.d(TAG, "Stop request not supported!");
+            }
+        }
+
+        @Override
+        public void showStatistics() {
+            MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute();
+            Intent intent = makeStatisticsIntent();
+            if (route.supportsControlRequest(intent)) {
+                MediaRouter.ControlRequestCallback callback =
+                        new MediaRouter.ControlRequestCallback() {
+                    @Override
+                    public void onResult(Bundle data) {
+                        Log.d(TAG, "Statistics request succeeded: data=" + data);
+                        if (data != null) {
+                            int playbackCount = data.getInt(
+                                    SampleMediaRouteProvider.DATA_PLAYBACK_COUNT, -1);
+                            mStatsInfo = "Total playback count: " + playbackCount;
+                        } else {
+                            showToast("Statistics query did not return any data");
+                        }
+                        updateRouteDescription();
+                    }
+
+                    @Override
+                    public void onError(String error, Bundle data) {
+                        Log.d(TAG, "Statistics request failed: error=" + error + ", data=" + data);
+                        showToast("Unable to query statistics, error: " + error);
+                        updateRouteDescription();
+                    }
+                };
+
+                Log.d(TAG, "Sent statistics request: intent=" + intent);
+                route.sendControlRequest(intent, callback);
+            } else {
+                Log.d(TAG, "Statistics request not supported!");
+            }
+
+        }
+
+        @Override
+        public void onFinish(boolean error) {
+            updateUi();
+        }
+
+        private void play(final Uri uri, boolean enqueue, final long pos) {
+            // save the initial seek position
+            mPosition = pos;
+            MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute();
+            Intent intent = makePlayIntent(uri, enqueue);
+            final String request = enqueue ? "Enqueue" : "Play";
+            if (route.supportsControlRequest(intent)) {
+                MediaRouter.ControlRequestCallback callback =
+                        new MediaRouter.ControlRequestCallback() {
+                    @Override
+                    public void onResult(Bundle data) {
+                        if (data != null) {
+                            String sid = data.getString(MediaControlIntent.EXTRA_SESSION_ID);
+                            String iid = data.getString(MediaControlIntent.EXTRA_ITEM_ID);
+                            MediaItemStatus status = MediaItemStatus.fromBundle(
+                                    data.getBundle(MediaControlIntent.EXTRA_ITEM_STATUS));
+                            Log.d(TAG, request + " request succeeded: data=" + data +
+                                    ", sid=" + sid + ", iid=" + iid);
+
+                            // perform delayed initial seek
+                            if (mSessionId == null && mPosition > 0) {
+                                seek(sid, iid, mPosition);
+                            }
+
+                            mSessionId = sid;
+                            mItemId = iid;
+                            mQueueItem = new MediaQueueItem(sid, iid, null, null);
+
+                            if (isRemoteQueue()) {
+                                MediaQueueItem playlistItem =
+                                        new MediaQueueItem(sid, iid, uri, null);
+                                playlistItem.setState(status.getPlaybackState());
+                                mPlayListItems.add(playlistItem);
+                                updateUi();
+                                enqueuePlaylist();
+                            }
+                        }
+                    }
+
+                    @Override
+                    public void onError(String error, Bundle data) {
+                        Log.d(TAG, request + " request failed: error=" + error + ", data=" + data);
+                        showToast("Unable to " + request + uri + ", error: " + error);
+                    }
+                };
+
+                Log.d(TAG, "Sending " + request + " request: intent=" + intent);
+                route.sendControlRequest(intent, callback);
+            } else {
+                Log.d(TAG, request + " request not supported!");
+            }
+        }
+
+        private Intent makePlayIntent(Uri uri, boolean enqueue) {
+            Intent intent = new Intent(
+                    enqueue ? MediaControlIntent.ACTION_ENQUEUE
+                            : MediaControlIntent.ACTION_PLAY);
+            intent.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
+            intent.setDataAndType(uri, "video/mp4");
+
+            // Provide a valid session id, or none (which starts a new session)
+            if (mSessionId != null) {
+                intent.putExtra(MediaControlIntent.EXTRA_SESSION_ID, mSessionId);
+            }
+
+            // PendingIntent for receiving status update from MRP
+            Intent statusIntent = new Intent(SampleMediaRouterActivity.ACTION_STATUS_CHANGE);
+            intent.putExtra(MediaControlIntent.EXTRA_ITEM_STATUS_UPDATE_RECEIVER,
+                    PendingIntent.getBroadcast(SampleMediaRouterActivity.this,
+                            0, statusIntent, 0));
+
+            return intent;
+        }
+
+        private Intent makeRemoveIntent(MediaQueueItem item) {
+            Intent intent = new Intent(MediaControlIntent.ACTION_REMOVE);
+            intent.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
+            intent.putExtra(MediaControlIntent.EXTRA_SESSION_ID, item.getSessionId());
+            intent.putExtra(MediaControlIntent.EXTRA_ITEM_ID, item.getItemId());
+            return intent;
+        }
+
+        private Intent makeSeekIntent(String sid, String iid, long pos) {
+            Intent intent = new Intent(MediaControlIntent.ACTION_SEEK);
+            intent.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
+            intent.putExtra(MediaControlIntent.EXTRA_SESSION_ID, sid);
+            intent.putExtra(MediaControlIntent.EXTRA_ITEM_ID, iid);
+            intent.putExtra(MediaControlIntent.EXTRA_ITEM_CONTENT_POSITION, pos);
+            return intent;
+        }
+
+        private Intent makePauseIntent() {
+            Intent intent = new Intent(MediaControlIntent.ACTION_PAUSE);
+            intent.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
+            if (mSessionId != null) {
+                intent.putExtra(MediaControlIntent.EXTRA_SESSION_ID, mSessionId);
+            }
+            return intent;
+        }
+
+        private Intent makeResumeIntent() {
+            Intent intent = new Intent(MediaControlIntent.ACTION_RESUME);
+            intent.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
+            if (mSessionId != null) {
+                intent.putExtra(MediaControlIntent.EXTRA_SESSION_ID, mSessionId);
+            }
+            return intent;
+        }
+
+        private Intent makeStopIntent() {
+            Intent intent = new Intent(MediaControlIntent.ACTION_STOP);
+            intent.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
+            if (mSessionId != null) {
+                intent.putExtra(MediaControlIntent.EXTRA_SESSION_ID, mSessionId);
+            }
+            return intent;
+        }
+
+        private Intent makeGetStatusIntent(MediaQueueItem item) {
+            Intent intent = new Intent(MediaControlIntent.ACTION_GET_STATUS);
+            intent.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
+            intent.putExtra(MediaControlIntent.EXTRA_SESSION_ID, item.getSessionId());
+            intent.putExtra(MediaControlIntent.EXTRA_ITEM_ID, item.getItemId());
+            return intent;
+         }
+
+        private Intent makeStatisticsIntent() {
+            Intent intent = new Intent(SampleMediaRouteProvider.ACTION_GET_STATISTICS);
+            intent.addCategory(SampleMediaRouteProvider.CATEGORY_SAMPLE_ROUTE);
+            return intent;
+        }
+    }
+
+    public static final class DiscoveryFragment extends MediaRouteDiscoveryFragment {
+        private static final String TAG = "DiscoveryFragment";
+        private Callback mCallback;
+
+        public DiscoveryFragment() {
+            mCallback = null;
+        }
+
+        public DiscoveryFragment(Callback cb) {
+            mCallback = cb;
+        }
+
+        public void setCallback(Callback cb) {
+            mCallback = cb;
+        }
+
+        @Override
+        public Callback onCreateCallback() {
+            return mCallback;
+        }
+
+        @Override
+        public int onPrepareCallbackFlags() {
+            // Add the CALLBACK_FLAG_UNFILTERED_EVENTS flag to ensure that we will
+            // observe and log all route events including those that are for routes
+            // that do not match our selector.  This is only for demonstration purposes
+            // and should not be needed by most applications.
+            return super.onPrepareCallbackFlags()
+                    | MediaRouter.CALLBACK_FLAG_UNFILTERED_EVENTS;
+        }
+    }
 
     private static final class MediaItem {
         public final String mName;
@@ -347,6 +1414,76 @@
         }
     }
 
+    private final class LibraryAdapter extends ArrayAdapter<MediaItem> {
+        public LibraryAdapter() {
+            super(SampleMediaRouterActivity.this, R.layout.media_item);
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            final View v;
+            if (convertView == null) {
+                v = getLayoutInflater().inflate(R.layout.media_item, null);
+            } else {
+                v = convertView;
+            }
+
+            final MediaItem item = getItem(position);
+
+            TextView tv = (TextView)v.findViewById(R.id.item_text);
+            tv.setText(item.mName);
+
+            ImageButton b = (ImageButton)v.findViewById(R.id.item_action);
+            b.setImageResource(R.drawable.ic_menu_add);
+            b.setTag(item);
+            b.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    if (item != null) {
+                        mPlayer.enqueue(item.mUri, 0);
+                    }
+                }
+            });
+
+            return v;
+        }
+    }
+
+    private final class PlaylistAdapter extends ArrayAdapter<MediaQueueItem> {
+        public PlaylistAdapter() {
+            super(SampleMediaRouterActivity.this, R.layout.media_item);
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            final View v;
+            if (convertView == null) {
+                v = getLayoutInflater().inflate(R.layout.media_item, null);
+            } else {
+                v = convertView;
+            }
+
+            final MediaQueueItem item = getItem(position);
+
+            TextView tv = (TextView)v.findViewById(R.id.item_text);
+            tv.setText(item.toString());
+
+            ImageButton b = (ImageButton)v.findViewById(R.id.item_action);
+            b.setImageResource(R.drawable.ic_menu_delete);
+            b.setTag(item);
+            b.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    if (item != null) {
+                        mPlayer.remove(item);
+                    }
+                }
+            });
+
+            return v;
+        }
+    }
+
     /**
      * Trivial subclass of this activity used to provide another copy of the
      * same activity using a light theme instead of the dark theme.
diff --git a/samples/devbytes/animation/ActivityAnimations/AndroidManifest.xml b/samples/devbytes/animation/ActivityAnimations/AndroidManifest.xml
new file mode 100644
index 0000000..eeb5378
--- /dev/null
+++ b/samples/devbytes/animation/ActivityAnimations/AndroidManifest.xml
@@ -0,0 +1,45 @@
+<!-- Copyright (C) 2013 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.example.android.activityanim"
+          android:versionCode="1"
+          android:versionName="1.0" >
+
+    <uses-sdk
+            android:minSdkVersion="16"
+            android:targetSdkVersion="17" />
+
+    <application
+            android:allowBackup="true"
+            android:icon="@drawable/ic_launcher"
+            android:label="@string/app_name"
+            android:theme="@style/AppTheme" >
+        <activity
+                android:name="com.example.android.activityanim.ActivityAnimations"
+                android:label="@string/app_name" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <activity
+                android:name="com.example.android.activityanim.PictureDetailsActivity"
+                android:label="@string/subactivity_name"
+                android:theme="@style/Transparent" >
+        </activity>
+    </application>
+
+</manifest>
\ No newline at end of file
diff --git a/samples/devbytes/animation/ActivityAnimations/res/drawable-hdpi/ic_launcher.png b/samples/devbytes/animation/ActivityAnimations/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..96a442e
--- /dev/null
+++ b/samples/devbytes/animation/ActivityAnimations/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/ActivityAnimations/res/drawable-mdpi/ic_launcher.png b/samples/devbytes/animation/ActivityAnimations/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..359047d
--- /dev/null
+++ b/samples/devbytes/animation/ActivityAnimations/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/ActivityAnimations/res/drawable-nodpi/p1.jpg b/samples/devbytes/animation/ActivityAnimations/res/drawable-nodpi/p1.jpg
new file mode 100644
index 0000000..9745818
--- /dev/null
+++ b/samples/devbytes/animation/ActivityAnimations/res/drawable-nodpi/p1.jpg
Binary files differ
diff --git a/samples/devbytes/animation/ActivityAnimations/res/drawable-nodpi/p2.jpg b/samples/devbytes/animation/ActivityAnimations/res/drawable-nodpi/p2.jpg
new file mode 100644
index 0000000..db8731f
--- /dev/null
+++ b/samples/devbytes/animation/ActivityAnimations/res/drawable-nodpi/p2.jpg
Binary files differ
diff --git a/samples/devbytes/animation/ActivityAnimations/res/drawable-nodpi/p3.jpg b/samples/devbytes/animation/ActivityAnimations/res/drawable-nodpi/p3.jpg
new file mode 100644
index 0000000..b240b3a
--- /dev/null
+++ b/samples/devbytes/animation/ActivityAnimations/res/drawable-nodpi/p3.jpg
Binary files differ
diff --git a/samples/devbytes/animation/ActivityAnimations/res/drawable-nodpi/p4.jpg b/samples/devbytes/animation/ActivityAnimations/res/drawable-nodpi/p4.jpg
new file mode 100644
index 0000000..4de9292
--- /dev/null
+++ b/samples/devbytes/animation/ActivityAnimations/res/drawable-nodpi/p4.jpg
Binary files differ
diff --git a/samples/devbytes/animation/ActivityAnimations/res/drawable-xhdpi/ic_launcher.png b/samples/devbytes/animation/ActivityAnimations/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..71c6d76
--- /dev/null
+++ b/samples/devbytes/animation/ActivityAnimations/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/ActivityAnimations/res/layout/activity_animations.xml b/samples/devbytes/animation/ActivityAnimations/res/layout/activity_animations.xml
new file mode 100644
index 0000000..c11a568
--- /dev/null
+++ b/samples/devbytes/animation/ActivityAnimations/res/layout/activity_animations.xml
@@ -0,0 +1,21 @@
+<!-- Copyright (C) 2013 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.
+-->
+<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_gravity="center_horizontal"
+        android:id="@+id/gridLayout" >
+
+</GridLayout>
\ No newline at end of file
diff --git a/samples/devbytes/animation/ActivityAnimations/res/layout/picture_info.xml b/samples/devbytes/animation/ActivityAnimations/res/layout/picture_info.xml
new file mode 100644
index 0000000..cb2ced2
--- /dev/null
+++ b/samples/devbytes/animation/ActivityAnimations/res/layout/picture_info.xml
@@ -0,0 +1,41 @@
+<!-- Copyright (C) 2013 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.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:id="@+id/topLevelLayout">
+    
+    <view
+        class="com.example.android.activityanim.ShadowLayout"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:id="@+id/shadowLayout"
+        android:visibility="visible" >
+
+        <TextView
+            android:id="@+id/description"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_below="@+id/imageView" />
+        <ImageView
+            android:id="@+id/imageView"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_centerInParent="true"
+            android:scaleType="centerInside" />
+    
+    
+    </view>
+</FrameLayout>
\ No newline at end of file
diff --git a/samples/devbytes/animation/ActivityAnimations/res/menu/activity_better_window_animations.xml b/samples/devbytes/animation/ActivityAnimations/res/menu/activity_better_window_animations.xml
new file mode 100644
index 0000000..aab540e
--- /dev/null
+++ b/samples/devbytes/animation/ActivityAnimations/res/menu/activity_better_window_animations.xml
@@ -0,0 +1,24 @@
+<!-- Copyright (C) 2013 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.
+-->
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <item
+        android:id="@+id/menu_slow"
+        android:orderInCategory="100"
+        android:showAsAction="never"
+        android:title="@string/menu_slow_animations"
+        android:checkable="true"/>
+
+</menu>
\ No newline at end of file
diff --git a/samples/devbytes/animation/ActivityAnimations/res/values/strings.xml b/samples/devbytes/animation/ActivityAnimations/res/values/strings.xml
new file mode 100644
index 0000000..f9409b5
--- /dev/null
+++ b/samples/devbytes/animation/ActivityAnimations/res/values/strings.xml
@@ -0,0 +1,21 @@
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <string name="app_name">Activity Animations</string>
+    <string name="subactivity_name">PictureInfo!</string>
+    <string name="menu_slow_animations">Slow</string>
+
+</resources>
\ No newline at end of file
diff --git a/samples/devbytes/animation/ActivityAnimations/res/values/styles.xml b/samples/devbytes/animation/ActivityAnimations/res/values/styles.xml
new file mode 100644
index 0000000..9d83342
--- /dev/null
+++ b/samples/devbytes/animation/ActivityAnimations/res/values/styles.xml
@@ -0,0 +1,39 @@
+<!-- Copyright (C) 2013 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.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <!--
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+        <!--
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        -->
+    </style>
+
+    <!-- Application theme. -->
+    <style name="AppTheme" parent="AppBaseTheme">
+        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+    </style>
+
+    <style name="Transparent">
+        <item name="android:windowNoTitle">true</item>
+        <item name="android:windowIsTranslucent">true</item>
+        <item name="android:windowBackground">@android:color/transparent</item>
+    </style>
+</resources>
\ No newline at end of file
diff --git a/samples/devbytes/animation/ActivityAnimations/src/com/example/android/activityanim/ActivityAnimations.java b/samples/devbytes/animation/ActivityAnimations/src/com/example/android/activityanim/ActivityAnimations.java
new file mode 100644
index 0000000..4a3e0d9
--- /dev/null
+++ b/samples/devbytes/animation/ActivityAnimations/src/com/example/android/activityanim/ActivityAnimations.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2013 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.activityanim;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
+import android.graphics.drawable.BitmapDrawable;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.GridLayout;
+import android.widget.ImageView;
+
+/**
+ * This example shows how to create a custom activity animation when you want something more
+ * than window animations can provide. The idea is to disable window animations for the
+ * activities and to instead launch or return from the sub-activity immediately, but use
+ * property animations inside the activities to customize the transition.
+ *
+ * Watch the associated video for this demo on the DevBytes channel of developer.android.com
+ * or on the DevBytes playlist in the androiddevelopers channel on YouTube at
+ * https://www.youtube.com/playlist?list=PLWz5rJ2EKKc_XOgcRukSoKKjewFJZrKV0.
+ */
+public class ActivityAnimations extends Activity {
+
+    private static final String PACKAGE = "com.example.android.activityanim";
+    static float sAnimatorScale = 1;
+
+    GridLayout mGridLayout;
+    HashMap<ImageView, PictureData> mPicturesData = new HashMap<ImageView, PictureData>();
+    BitmapUtils mBitmapUtils = new BitmapUtils();
+    
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_animations);
+
+        // Grayscale filter used on all thumbnails
+        ColorMatrix grayMatrix = new ColorMatrix();
+        grayMatrix.setSaturation(0);
+        ColorMatrixColorFilter grayscaleFilter = new ColorMatrixColorFilter(grayMatrix);
+        
+        mGridLayout = (GridLayout) findViewById(R.id.gridLayout);
+        mGridLayout.setColumnCount(3);
+        mGridLayout.setUseDefaultMargins(true);
+        
+        // add all photo thumbnails to layout
+        Resources resources = getResources();
+        ArrayList<PictureData> pictures = mBitmapUtils.loadPhotos(resources);
+        for (int i = 0; i < pictures.size(); ++i) {
+            PictureData pictureData = pictures.get(i);
+            BitmapDrawable thumbnailDrawable =
+                    new BitmapDrawable(resources, pictureData.thumbnail);
+            thumbnailDrawable.setColorFilter(grayscaleFilter);
+            ImageView imageView = new ImageView(this);
+            imageView.setOnClickListener(thumbnailClickListener);
+            imageView.setImageDrawable(thumbnailDrawable);
+            mPicturesData.put(imageView, pictureData);
+            mGridLayout.addView(imageView);
+        }
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        getMenuInflater().inflate(R.menu.activity_better_window_animations, menu);
+        return true;
+    }
+    
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        if (item.getItemId() == R.id.menu_slow) {
+            sAnimatorScale = item.isChecked() ? 1 : 5;
+            item.setChecked(!item.isChecked());
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
+    /**
+     * When the user clicks a thumbnail, bundle up information about it and launch the
+     * details activity.
+     */
+    private View.OnClickListener thumbnailClickListener = new View.OnClickListener() {
+        
+        @Override
+        public void onClick(View v) {
+            // Interesting data to pass across are the thumbnail size/location, the
+            // resourceId of the source bitmap, the picture description, and the
+            // orientation (to avoid returning back to an obsolete configuration if
+            // the device rotates again in the meantime)
+            int[] screenLocation = new int[2];
+            v.getLocationOnScreen(screenLocation);
+            PictureData info = mPicturesData.get(v);
+            Intent subActivity = new Intent(ActivityAnimations.this,
+                    PictureDetailsActivity.class);
+            int orientation = getResources().getConfiguration().orientation;
+            subActivity.
+                    putExtra(PACKAGE + ".orientation", orientation).
+                    putExtra(PACKAGE + ".resourceId", info.resourceId).
+                    putExtra(PACKAGE + ".left", screenLocation[0]).
+                    putExtra(PACKAGE + ".top", screenLocation[1]).
+                    putExtra(PACKAGE + ".width", v.getWidth()).
+                    putExtra(PACKAGE + ".height", v.getHeight()).
+                    putExtra(PACKAGE + ".description", info.description);
+            startActivity(subActivity);
+            
+            // Override transitions: we don't want the normal window animation in addition
+            // to our custom one
+            overridePendingTransition(0, 0);
+        }
+    };
+
+}
diff --git a/samples/devbytes/animation/ActivityAnimations/src/com/example/android/activityanim/BitmapUtils.java b/samples/devbytes/animation/ActivityAnimations/src/com/example/android/activityanim/BitmapUtils.java
new file mode 100644
index 0000000..a8034dc
--- /dev/null
+++ b/samples/devbytes/animation/ActivityAnimations/src/com/example/android/activityanim/BitmapUtils.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2013 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.activityanim;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.drawable.BitmapDrawable;
+import android.widget.ImageView;
+
+public class BitmapUtils {
+    
+    int[] mPhotos = {
+            R.drawable.p1,
+            R.drawable.p2,
+            R.drawable.p3,
+            R.drawable.p4
+    };
+    
+    String[] mDescriptions = {
+            "This picture was taken while sunbathing in a natural hot spring, which was " +
+            "unfortunately filled with acid, which is a lasting memory from that trip, whenever I " +
+            "I look at my own skin.",
+            "I took this shot with a pinhole camera mounted on a tripod constructed out of " +
+            "soda straws. I felt that that combination best captured the beauty of the landscape " +
+            "in juxtaposition with the detritus of mankind.",
+            "I don't remember where or when I took this picture. All I know is that I was really " +
+            "drunk at the time, and I woke up without my left sock.",
+            "Right before I took this picture, there was a busload of school children right " +
+            "in my way. I knew the perfect shot was coming, so I quickly yelled 'Free candy!!!' " +
+            "and they scattered.",
+    };
+
+    static HashMap<Integer, Bitmap> sBitmapResourceMap = new HashMap<Integer, Bitmap>();
+
+    /**
+     * Load pictures and descriptions. A real app wouldn't do it this way, but that's
+     * not the point of this animation demo. Loading asynchronously is a better way to go
+     * for what can be time-consuming operations.
+     */
+    public ArrayList<PictureData> loadPhotos(Resources resources) {
+        ArrayList<PictureData> pictures = new ArrayList<PictureData>();
+        for (int i = 0; i < 30; ++i) {
+            int resourceId = mPhotos[(int) (Math.random() * mPhotos.length)];
+            Bitmap bitmap = getBitmap(resources, resourceId);
+            Bitmap thumbnail = getThumbnail(bitmap, 200);
+            String description = mDescriptions[(int) (Math.random() * mDescriptions.length)];
+            pictures.add(new PictureData(resourceId, description, thumbnail));
+        }
+        return pictures;
+    }
+
+    /**
+     * Utility method to get bitmap from cache or, if not there, load it
+     * from its resource.
+     */
+    static Bitmap getBitmap(Resources resources, int resourceId) {
+        Bitmap bitmap = sBitmapResourceMap.get(resourceId);
+        if (bitmap == null) {
+            bitmap = BitmapFactory.decodeResource(resources, resourceId);
+            sBitmapResourceMap.put(resourceId, bitmap);
+        }        
+        return bitmap;
+    }
+    
+    /**
+     * Create and return a thumbnail image given the original source bitmap and a max
+     * dimension (width or height).
+     */
+    private Bitmap getThumbnail(Bitmap original, int maxDimension) {
+        int width = original.getWidth();
+        int height = original.getHeight();
+        int scaledWidth, scaledHeight;
+        if (width >= height) {
+            float scaleFactor = (float) maxDimension / width;
+            scaledWidth = 200;
+            scaledHeight = (int) (scaleFactor * height);
+        } else {
+            float scaleFactor = (float) maxDimension / height;
+            scaledWidth = (int) (scaleFactor * width);
+            scaledHeight = 200;
+        }
+        Bitmap thumbnail = Bitmap.createScaledBitmap(original, scaledWidth, scaledHeight, true);
+        
+        return thumbnail;
+    }
+    
+
+}
diff --git a/samples/devbytes/animation/ActivityAnimations/src/com/example/android/activityanim/PictureData.java b/samples/devbytes/animation/ActivityAnimations/src/com/example/android/activityanim/PictureData.java
new file mode 100644
index 0000000..eb2d126
--- /dev/null
+++ b/samples/devbytes/animation/ActivityAnimations/src/com/example/android/activityanim/PictureData.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2013 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.activityanim;
+
+import android.graphics.Bitmap;
+
+public class PictureData {
+    int resourceId;
+    String description;
+    Bitmap thumbnail;
+    
+    public PictureData(int resourceId, String description, Bitmap thumbnail) {
+        this.resourceId = resourceId;
+        this.description = description;
+        this.thumbnail = thumbnail;
+    }
+}
diff --git a/samples/devbytes/animation/ActivityAnimations/src/com/example/android/activityanim/PictureDetailsActivity.java b/samples/devbytes/animation/ActivityAnimations/src/com/example/android/activityanim/PictureDetailsActivity.java
new file mode 100644
index 0000000..e1674c9
--- /dev/null
+++ b/samples/devbytes/animation/ActivityAnimations/src/com/example/android/activityanim/PictureDetailsActivity.java
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2013 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.activityanim;
+
+import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
+import android.app.Activity;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.ColorDrawable;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewTreeObserver;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+/**
+ * This sub-activity shows a zoomed-in view of a specific photo, along with the
+ * picture's text description. Most of the logic is for the animations that will
+ * be run when the activity is being launched and exited. When launching,
+ * the large version of the picture will resize from the thumbnail version in the
+ * main activity, colorizing it from the thumbnail's grayscale version at the
+ * same time. Meanwhile, the black background of the activity will fade in and
+ * the description will eventually slide into place. The exit animation runs all
+ * of this in reverse.
+ * 
+ */
+public class PictureDetailsActivity extends Activity {
+
+    private static final TimeInterpolator sDecelerator = new DecelerateInterpolator();
+    private static final TimeInterpolator sAccelerator = new AccelerateInterpolator();
+    private static final String PACKAGE_NAME = "com.example.android.activityanim";
+    private static final int ANIM_DURATION = 500;
+
+    private BitmapDrawable mBitmapDrawable;
+    private ColorMatrix colorizerMatrix = new ColorMatrix();
+    ColorDrawable mBackground;
+    int mLeftDelta;
+    int mTopDelta;
+    float mWidthScale;
+    float mHeightScale;
+    private ImageView mImageView;
+    private TextView mTextView;
+    private FrameLayout mTopLevelLayout;
+    private ShadowLayout mShadowLayout;
+    private int mOriginalOrientation;
+    
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.picture_info);
+        mImageView = (ImageView) findViewById(R.id.imageView);
+        mTopLevelLayout = (FrameLayout) findViewById(R.id.topLevelLayout);
+        mShadowLayout = (ShadowLayout) findViewById(R.id.shadowLayout);
+        mTextView = (TextView) findViewById(R.id.description);
+        
+        // Retrieve the data we need for the picture/description to display and
+        // the thumbnail to animate it from
+        Bundle bundle = getIntent().getExtras();
+        Bitmap bitmap = BitmapUtils.getBitmap(getResources(),
+                bundle.getInt(PACKAGE_NAME + ".resourceId"));
+        String description = bundle.getString(PACKAGE_NAME + ".description");
+        final int thumbnailTop = bundle.getInt(PACKAGE_NAME + ".top");
+        final int thumbnailLeft = bundle.getInt(PACKAGE_NAME + ".left");
+        final int thumbnailWidth = bundle.getInt(PACKAGE_NAME + ".width");
+        final int thumbnailHeight = bundle.getInt(PACKAGE_NAME + ".height");
+        mOriginalOrientation = bundle.getInt(PACKAGE_NAME + ".orientation");
+        
+        mBitmapDrawable = new BitmapDrawable(getResources(), bitmap);
+        mImageView.setImageDrawable(mBitmapDrawable);
+        mTextView.setText(description);
+        
+        mBackground = new ColorDrawable(Color.BLACK);
+        mTopLevelLayout.setBackground(mBackground);
+
+        // Only run the animation if we're coming from the parent activity, not if
+        // we're recreated automatically by the window manager (e.g., device rotation)
+        if (savedInstanceState == null) {
+            ViewTreeObserver observer = mImageView.getViewTreeObserver();
+            observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+                
+                @Override
+                public boolean onPreDraw() {
+                    mImageView.getViewTreeObserver().removeOnPreDrawListener(this);
+
+                    // Figure out where the thumbnail and full size versions are, relative
+                    // to the screen and each other
+                    int[] screenLocation = new int[2];
+                    mImageView.getLocationOnScreen(screenLocation);
+                    mLeftDelta = thumbnailLeft - screenLocation[0];
+                    mTopDelta = thumbnailTop - screenLocation[1];
+                    
+                    // Scale factors to make the large version the same size as the thumbnail
+                    mWidthScale = (float) thumbnailWidth / mImageView.getWidth();
+                    mHeightScale = (float) thumbnailHeight / mImageView.getHeight();
+    
+                    runEnterAnimation();
+                    
+                    return true;
+                }
+            });
+        }
+    }
+
+    /**
+     * The enter animation scales the picture in from its previous thumbnail
+     * size/location, colorizing it in parallel. In parallel, the background of the
+     * activity is fading in. When the pictue is in place, the text description
+     * drops down.
+     */
+    public void runEnterAnimation() {
+        final long duration = (long) (ANIM_DURATION * ActivityAnimations.sAnimatorScale);
+        
+        // Set starting values for properties we're going to animate. These
+        // values scale and position the full size version down to the thumbnail
+        // size/location, from which we'll animate it back up
+        mImageView.setPivotX(0);
+        mImageView.setPivotY(0);
+        mImageView.setScaleX(mWidthScale);
+        mImageView.setScaleY(mHeightScale);
+        mImageView.setTranslationX(mLeftDelta);
+        mImageView.setTranslationY(mTopDelta);
+        
+        // We'll fade the text in later
+        mTextView.setAlpha(0);
+        
+        // Animate scale and translation to go from thumbnail to full size
+        mImageView.animate().setDuration(duration).
+                scaleX(1).scaleY(1).
+                translationX(0).translationY(0).
+                setInterpolator(sDecelerator).
+                withEndAction(new Runnable() {
+                    public void run() {
+                        // Animate the description in after the image animation
+                        // is done. Slide and fade the text in from underneath
+                        // the picture.
+                        mTextView.setTranslationY(-mTextView.getHeight());
+                        mTextView.animate().setDuration(duration/2).
+                                translationY(0).alpha(1).
+                                setInterpolator(sDecelerator);
+                    }
+                });
+        
+        // Fade in the black background
+        ObjectAnimator bgAnim = ObjectAnimator.ofInt(mBackground, "alpha", 0, 255);
+        bgAnim.setDuration(duration);
+        bgAnim.start();
+        
+        // Animate a color filter to take the image from grayscale to full color.
+        // This happens in parallel with the image scaling and moving into place.
+        ObjectAnimator colorizer = ObjectAnimator.ofFloat(PictureDetailsActivity.this,
+                "saturation", 0, 1);
+        colorizer.setDuration(duration);
+        colorizer.start();
+
+        // Animate a drop-shadow of the image
+        ObjectAnimator shadowAnim = ObjectAnimator.ofFloat(mShadowLayout, "shadowDepth", 0, 1);
+        shadowAnim.setDuration(duration);
+        shadowAnim.start();
+    }
+    
+    /**
+     * The exit animation is basically a reverse of the enter animation, except that if
+     * the orientation has changed we simply scale the picture back into the center of
+     * the screen.
+     * 
+     * @param endAction This action gets run after the animation completes (this is
+     * when we actually switch activities)
+     */
+    public void runExitAnimation(final Runnable endAction) {
+        final long duration = (long) (ANIM_DURATION * ActivityAnimations.sAnimatorScale);
+
+        // No need to set initial values for the reverse animation; the image is at the
+        // starting size/location that we want to start from. Just animate to the
+        // thumbnail size/location that we retrieved earlier 
+        
+        // Caveat: configuration change invalidates thumbnail positions; just animate
+        // the scale around the center. Also, fade it out since it won't match up with
+        // whatever's actually in the center
+        final boolean fadeOut;
+        if (getResources().getConfiguration().orientation != mOriginalOrientation) {
+            mImageView.setPivotX(mImageView.getWidth() / 2);
+            mImageView.setPivotY(mImageView.getHeight() / 2);
+            mLeftDelta = 0;
+            mTopDelta = 0;
+            fadeOut = true;
+        } else {
+            fadeOut = false;
+        }
+
+        // First, slide/fade text out of the way
+        mTextView.animate().translationY(-mTextView.getHeight()).alpha(0).
+                setDuration(duration/2).setInterpolator(sAccelerator).
+                withEndAction(new Runnable() {
+                    public void run() {
+                        // Animate image back to thumbnail size/location
+                        mImageView.animate().setDuration(duration).
+                                scaleX(mWidthScale).scaleY(mHeightScale).
+                                translationX(mLeftDelta).translationY(mTopDelta).
+                                withEndAction(endAction);
+                        if (fadeOut) {
+                            mImageView.animate().alpha(0);
+                        }
+                        // Fade out background
+                        ObjectAnimator bgAnim = ObjectAnimator.ofInt(mBackground, "alpha", 0);
+                        bgAnim.setDuration(duration);
+                        bgAnim.start();
+
+                        // Animate the shadow of the image
+                        ObjectAnimator shadowAnim = ObjectAnimator.ofFloat(mShadowLayout,
+                                "shadowDepth", 1, 0);
+                        shadowAnim.setDuration(duration);
+                        shadowAnim.start();
+
+                        // Animate a color filter to take the image back to grayscale,
+                        // in parallel with the image scaling and moving into place.
+                        ObjectAnimator colorizer =
+                                ObjectAnimator.ofFloat(PictureDetailsActivity.this,
+                                "saturation", 1, 0);
+                        colorizer.setDuration(duration);
+                        colorizer.start();
+                    }
+                });
+
+        
+    }
+
+    /**
+     * Overriding this method allows us to run our exit animation first, then exiting
+     * the activity when it is complete.
+     */
+    @Override
+    public void onBackPressed() {
+        runExitAnimation(new Runnable() {
+            public void run() {
+                // *Now* go ahead and exit the activity
+                finish();
+            }
+        });
+    }
+
+    /**
+     * This is called by the colorizing animator. It sets a saturation factor that is then
+     * passed onto a filter on the picture's drawable.
+     * @param value
+     */
+    public void setSaturation(float value) {
+        colorizerMatrix.setSaturation(value);
+        ColorMatrixColorFilter colorizerFilter = new ColorMatrixColorFilter(colorizerMatrix);
+        mBitmapDrawable.setColorFilter(colorizerFilter);
+    }
+    
+    @Override
+    public void finish() {
+        super.finish();
+        
+        // override transitions to skip the standard window animations
+        overridePendingTransition(0, 0);
+    }
+}
diff --git a/samples/devbytes/animation/ActivityAnimations/src/com/example/android/activityanim/ShadowLayout.java b/samples/devbytes/animation/ActivityAnimations/src/com/example/android/activityanim/ShadowLayout.java
new file mode 100644
index 0000000..b3bc961
--- /dev/null
+++ b/samples/devbytes/animation/ActivityAnimations/src/com/example/android/activityanim/ShadowLayout.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2013 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.activityanim;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BlurMaskFilter;
+import android.graphics.BlurMaskFilter.Blur;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.RelativeLayout;
+
+/**
+ * This custom layout paints a drop shadow behind all children. The size and opacity
+ * of the drop shadow is determined by a "depth" factor that can be set and animated.
+ */
+public class ShadowLayout extends RelativeLayout {
+
+    Paint mShadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+    float mShadowDepth;
+    Bitmap mShadowBitmap;
+    static final int BLUR_RADIUS = 6;
+    static final RectF sShadowRectF = new RectF(0, 0, 200, 200);
+    static final Rect sShadowRect = new Rect(0, 0, 200 + 2 * BLUR_RADIUS, 200 + 2 * BLUR_RADIUS);
+    static RectF tempShadowRectF = new RectF(0, 0, 0, 0);
+    
+    public ShadowLayout(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        init();
+    }
+
+    public ShadowLayout(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init();
+    }
+
+    public ShadowLayout(Context context) {
+        super(context);
+        init();
+    }
+    
+    /**
+     * Called by the constructors - sets up the drawing parameters for the drop shadow.
+     */
+    private void init() {
+        mShadowPaint.setColor(Color.BLACK);
+        mShadowPaint.setStyle(Style.FILL);
+        setWillNotDraw(false);
+        mShadowBitmap = Bitmap.createBitmap(sShadowRect.width(),
+                sShadowRect.height(), Bitmap.Config.ARGB_8888);
+        Canvas c = new Canvas(mShadowBitmap);
+        mShadowPaint.setMaskFilter(new BlurMaskFilter(BLUR_RADIUS, Blur.NORMAL));
+        c.translate(BLUR_RADIUS, BLUR_RADIUS);
+        c.drawRoundRect(sShadowRectF, sShadowRectF.width() / 40,
+                sShadowRectF.height() / 40, mShadowPaint);
+    }
+    
+    /**
+     * The "depth" factor determines the offset distance and opacity of the shadow (shadows that
+     * are further away from the source are offset greater and are more translucent).
+     * @param depth
+     */
+    public void setShadowDepth(float depth) {
+        if (depth != mShadowDepth) {
+            mShadowDepth = depth;
+            mShadowPaint.setAlpha((int) (100 + 150 * (1 - mShadowDepth)));
+            invalidate(); // We need to redraw when the shadow attributes change
+        }
+    }
+
+    /**
+     * Overriding onDraw allows us to draw shadows behind every child of this container.
+     * onDraw() is called to draw a layout's content before the children are drawn, so the
+     * shadows will be drawn first, behind the children (which is what we want).
+     */
+    @Override
+    protected void onDraw(Canvas canvas) {
+        for (int i = 0; i < getChildCount(); ++i) {
+            View child = getChildAt(i);
+            if (child.getVisibility() != View.VISIBLE || child.getAlpha() == 0) {
+                continue;
+            }
+            int depthFactor = (int) (80 * mShadowDepth);
+            canvas.save();
+            canvas.translate(child.getLeft() + depthFactor,
+                    child.getTop() + depthFactor);
+            canvas.concat(child.getMatrix());
+            tempShadowRectF.right = child.getWidth();
+            tempShadowRectF.bottom = child.getHeight();
+            canvas.drawBitmap(mShadowBitmap, sShadowRect, tempShadowRectF, mShadowPaint);
+            canvas.restore();
+        }
+    }
+    
+    
+}
diff --git a/samples/devbytes/animation/Anticipation/AndroidManifest.xml b/samples/devbytes/animation/Anticipation/AndroidManifest.xml
new file mode 100644
index 0000000..c941524
--- /dev/null
+++ b/samples/devbytes/animation/Anticipation/AndroidManifest.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.android.anticipation"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk
+        android:minSdkVersion="14"
+        android:targetSdkVersion="17" />
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/ic_launcher"
+        android:label="@string/app_name"
+        android:theme="@style/AppTheme" >
+        <activity
+            android:name="com.example.android.anticipation.Anticipation"
+            android:label="@string/app_name" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest>
\ No newline at end of file
diff --git a/samples/devbytes/animation/Anticipation/res/drawable-hdpi/ic_launcher.png b/samples/devbytes/animation/Anticipation/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..96a442e
--- /dev/null
+++ b/samples/devbytes/animation/Anticipation/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/Anticipation/res/drawable-mdpi/ic_launcher.png b/samples/devbytes/animation/Anticipation/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..359047d
--- /dev/null
+++ b/samples/devbytes/animation/Anticipation/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/Anticipation/res/drawable-xhdpi/ic_launcher.png b/samples/devbytes/animation/Anticipation/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..71c6d76
--- /dev/null
+++ b/samples/devbytes/animation/Anticipation/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/Anticipation/res/layout/main.xml b/samples/devbytes/animation/Anticipation/res/layout/main.xml
new file mode 100644
index 0000000..7da093f
--- /dev/null
+++ b/samples/devbytes/animation/Anticipation/res/layout/main.xml
@@ -0,0 +1,28 @@
+<!-- Copyright (C) 2013 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"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:id="@+id/container"
+    android:clipChildren="false"
+    tools:context=".Anticipation" >
+    
+    <view
+        class="com.example.android.anticipation.AnticiButton"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="AnticiButton"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/samples/devbytes/animation/Anticipation/res/values-v14/styles.xml b/samples/devbytes/animation/Anticipation/res/values-v14/styles.xml
new file mode 100644
index 0000000..6e9521a
--- /dev/null
+++ b/samples/devbytes/animation/Anticipation/res/values-v14/styles.xml
@@ -0,0 +1,26 @@
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <!--
+        Base application theme for API 14+. This theme completely replaces
+        AppBaseTheme from BOTH res/values/styles.xml and
+        res/values-v11/styles.xml on API 14+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+        <!-- API 14 theme customizations can go here. -->
+    </style>
+
+</resources>
\ No newline at end of file
diff --git a/samples/devbytes/animation/Anticipation/res/values/strings.xml b/samples/devbytes/animation/Anticipation/res/values/strings.xml
new file mode 100644
index 0000000..9097629
--- /dev/null
+++ b/samples/devbytes/animation/Anticipation/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <string name="app_name">Anticipation</string>
+    <string name="hello_world">Hello world!</string>
+    <string name="menu_settings">Settings</string>
+
+</resources>
\ No newline at end of file
diff --git a/samples/devbytes/animation/Anticipation/res/values/styles.xml b/samples/devbytes/animation/Anticipation/res/values/styles.xml
new file mode 100644
index 0000000..27658b7
--- /dev/null
+++ b/samples/devbytes/animation/Anticipation/res/values/styles.xml
@@ -0,0 +1,34 @@
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <!--
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Light">
+        <!--
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        -->
+    </style>
+
+    <!-- Application theme. -->
+    <style name="AppTheme" parent="AppBaseTheme">
+        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+    </style>
+
+</resources>
\ No newline at end of file
diff --git a/samples/devbytes/animation/Anticipation/src/com/example/android/anticipation/AnticiButton.java b/samples/devbytes/animation/Anticipation/src/com/example/android/anticipation/AnticiButton.java
new file mode 100644
index 0000000..707765b
--- /dev/null
+++ b/samples/devbytes/animation/Anticipation/src/com/example/android/anticipation/AnticiButton.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2013 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.anticipation;
+
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.RectF;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.LinearInterpolator;
+import android.view.animation.OvershootInterpolator;
+import android.widget.Button;
+
+/**
+ * Custom button which can be deformed by skewing the top left and right, to simulate
+ * anticipation and follow-through animation effects. Clicking on the button runs
+ * an animation which moves the button left or right, applying the skew effect to the
+ * button. The logic of drawing the button with a skew transform is handled in the
+ * draw() override.
+ */
+public class AnticiButton extends Button {
+
+    private static final LinearInterpolator sLinearInterpolator = new LinearInterpolator();
+    private static final DecelerateInterpolator sDecelerator = new DecelerateInterpolator(8);
+    private static final AccelerateInterpolator sAccelerator = new AccelerateInterpolator();
+    private static final OvershootInterpolator sOvershooter = new OvershootInterpolator();
+    private static final DecelerateInterpolator sQuickDecelerator = new DecelerateInterpolator();
+    
+    private float mSkewX = 0;
+    ObjectAnimator downAnim = null;
+    boolean mOnLeft = true;
+    RectF mTempRect = new RectF();
+    
+    public AnticiButton(Context context) {
+        super(context);
+        init();
+    }
+
+    public AnticiButton(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        init();
+    }
+
+    public AnticiButton(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init();
+    }
+
+    private void init() {
+        setOnTouchListener(mTouchListener);
+        setOnClickListener(new OnClickListener() {
+            public void onClick(View v) {
+                runClickAnim();
+            }
+        });
+    }
+
+    /**
+     * The skew effect is handled by changing the transform of the Canvas
+     * and then calling the usual superclass draw() method.
+     */
+    @Override
+    public void draw(Canvas canvas) {
+        if (mSkewX != 0) {
+            canvas.translate(0, getHeight());
+            canvas.skew(mSkewX, 0);
+            canvas.translate(0,  -getHeight());
+        }
+        super.draw(canvas);
+    }
+
+    /**
+     * Anticipate the future animation by rearing back, away from the direction of travel
+     */
+    private void runPressAnim() {
+        downAnim = ObjectAnimator.ofFloat(this, "skewX", mOnLeft ? .5f : -.5f);
+        downAnim.setDuration(2500);
+        downAnim.setInterpolator(sDecelerator);
+        downAnim.start();
+    }
+
+    /**
+     * Finish the "anticipation" animation (skew the button back from the direction of
+     * travel), animate it to the other side of the screen, then un-skew the button
+     * with an Overshoot effect.
+     */
+    private void runClickAnim() {
+        // Anticipation
+        ObjectAnimator finishDownAnim = null;
+        if (downAnim != null && downAnim.isRunning()) {
+            // finish the skew animation quickly
+            downAnim.cancel();
+            finishDownAnim = ObjectAnimator.ofFloat(this, "skewX",
+                    mOnLeft ? .5f : -.5f);
+            finishDownAnim.setDuration(150);
+            finishDownAnim.setInterpolator(sQuickDecelerator);
+        }
+        
+        // Slide. Use LinearInterpolator in this rare situation where we want to start
+        // and end fast (no acceleration or deceleration, since we're doing that part
+        // during the anticipation and overshoot phases).
+        ObjectAnimator moveAnim = ObjectAnimator.ofFloat(this,
+                View.TRANSLATION_X, mOnLeft ? 400 : 0);
+        moveAnim.setInterpolator(sLinearInterpolator);
+        moveAnim.setDuration(150);
+        
+        // Then overshoot by stopping the movement but skewing the button as if it couldn't
+        // all stop at once
+        ObjectAnimator skewAnim = ObjectAnimator.ofFloat(this, "skewX",
+                mOnLeft ? -.5f : .5f);
+        skewAnim.setInterpolator(sQuickDecelerator);
+        skewAnim.setDuration(100);
+        // and wobble it
+        ObjectAnimator wobbleAnim = ObjectAnimator.ofFloat(this, "skewX", 0);
+        wobbleAnim.setInterpolator(sOvershooter);
+        wobbleAnim.setDuration(150);
+        AnimatorSet set = new AnimatorSet();
+        set.playSequentially(moveAnim, skewAnim, wobbleAnim);
+        if (finishDownAnim != null) {
+            set.play(finishDownAnim).before(moveAnim);
+        }
+        set.start();
+        mOnLeft = !mOnLeft;
+    }
+
+    /**
+     * Restore the button to its un-pressed state
+     */
+    private void runCancelAnim() {
+        if (downAnim != null && downAnim.isRunning()) {
+            downAnim.cancel();
+            ObjectAnimator reverser = ObjectAnimator.ofFloat(this, "skewX", 0);
+            reverser.setDuration(200);
+            reverser.setInterpolator(sAccelerator);
+            reverser.start();
+            downAnim = null;
+        }
+    }
+
+    /**
+     * Handle touch events directly since we want to react on down/up events, not just
+     * button clicks
+     */
+    private View.OnTouchListener mTouchListener = new View.OnTouchListener() {
+        
+        @Override
+        public boolean onTouch(View v, MotionEvent event) {
+            switch (event.getAction()) {
+            case MotionEvent.ACTION_UP:
+                if (isPressed()) {
+                    performClick();
+                    setPressed(false);
+                    break;
+                }
+                // No click: Fall through; equivalent to cancel event
+            case MotionEvent.ACTION_CANCEL:
+                // Run the cancel animation in either case
+                runCancelAnim();
+                break;
+            case MotionEvent.ACTION_MOVE:
+                float x = event.getX();
+                float y = event.getY();
+                boolean isInside = (x > 0 && x < getWidth() &&
+                        y > 0 && y < getHeight());
+                if (isPressed() != isInside) {
+                    setPressed(isInside);
+                }
+                break;
+            case MotionEvent.ACTION_DOWN:
+                setPressed(true);
+                runPressAnim();
+                break;
+            default:
+                break;
+            }
+            return true;
+        }
+    };
+    
+    public float getSkewX() {
+        return mSkewX;
+    }
+    
+    /**
+     * Sets the amount of left/right skew on the button, which determines how far the button
+     * leans.
+     */
+    public void setSkewX(float value) {
+        if (value != mSkewX) {
+            mSkewX = value;
+            invalidate();             // force button to redraw with new skew value
+            invalidateSkewedBounds(); // also invalidate appropriate area of parent
+        }
+    }
+    
+    /**
+     * Need to invalidate proper area of parent for skewed bounds
+     */
+    private void invalidateSkewedBounds() {
+        if (mSkewX != 0) {
+            Matrix matrix = new Matrix();
+            matrix.setSkew(-mSkewX, 0);
+            mTempRect.set(0, 0, getRight(), getBottom());
+            matrix.mapRect(mTempRect);
+            mTempRect.offset(getLeft() + getTranslationX(), getTop() + getTranslationY());
+            ((View) getParent()).invalidate((int) mTempRect.left, (int) mTempRect.top,
+                    (int) (mTempRect.right +.5f), (int) (mTempRect.bottom + .5f));
+        }
+    }
+}
diff --git a/samples/devbytes/animation/Anticipation/src/com/example/android/anticipation/Anticipation.java b/samples/devbytes/animation/Anticipation/src/com/example/android/anticipation/Anticipation.java
new file mode 100644
index 0000000..4ef8f62
--- /dev/null
+++ b/samples/devbytes/animation/Anticipation/src/com/example/android/anticipation/Anticipation.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013 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.anticipation;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+
+/**
+ * This example shows how to animate some simple deformations on a standard UI widget
+ * to achieve some interactive and cartoon-ish effects.
+ *
+ * Watch the associated video for this demo on the DevBytes channel of developer.android.com
+ * or on the DevBytes playlist in the androiddevelopers channel on YouTube at
+ * https://www.youtube.com/playlist?list=PLWz5rJ2EKKc_XOgcRukSoKKjewFJZrKV0.
+ */
+public class Anticipation extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+    }
+
+}
diff --git a/samples/devbytes/animation/CardFlip/AndroidManifest.xml b/samples/devbytes/animation/CardFlip/AndroidManifest.xml
new file mode 100644
index 0000000..d915f3e
--- /dev/null
+++ b/samples/devbytes/animation/CardFlip/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<!-- Copyright (C) 2013 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.example.android.cardflip"
+          android:versionCode="1"
+          android:versionName="1.0">
+    <uses-sdk android:minSdkVersion="14"
+              android:targetSdkVersion="17"/>
+    <application android:label="@string/app_name" android:icon="@drawable/ic_launcher">
+        <activity android:name=".CardFlip"
+                  android:label="@string/app_name">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/samples/devbytes/animation/CardFlip/res/drawable-hdpi/blue.jpg b/samples/devbytes/animation/CardFlip/res/drawable-hdpi/blue.jpg
new file mode 100644
index 0000000..2f7b786
--- /dev/null
+++ b/samples/devbytes/animation/CardFlip/res/drawable-hdpi/blue.jpg
Binary files differ
diff --git a/samples/devbytes/animation/CardFlip/res/drawable-hdpi/ic_launcher.png b/samples/devbytes/animation/CardFlip/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..96a442e
--- /dev/null
+++ b/samples/devbytes/animation/CardFlip/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/CardFlip/res/drawable-hdpi/red.jpg b/samples/devbytes/animation/CardFlip/res/drawable-hdpi/red.jpg
new file mode 100644
index 0000000..f433603
--- /dev/null
+++ b/samples/devbytes/animation/CardFlip/res/drawable-hdpi/red.jpg
Binary files differ
diff --git a/samples/devbytes/animation/CardFlip/res/drawable-ldpi/ic_launcher.png b/samples/devbytes/animation/CardFlip/res/drawable-ldpi/ic_launcher.png
new file mode 100644
index 0000000..9923872
--- /dev/null
+++ b/samples/devbytes/animation/CardFlip/res/drawable-ldpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/CardFlip/res/drawable-mdpi/ic_launcher.png b/samples/devbytes/animation/CardFlip/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..359047d
--- /dev/null
+++ b/samples/devbytes/animation/CardFlip/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/CardFlip/res/drawable-xhdpi/ic_launcher.png b/samples/devbytes/animation/CardFlip/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..71c6d76
--- /dev/null
+++ b/samples/devbytes/animation/CardFlip/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/CardFlip/res/layout/main.xml b/samples/devbytes/animation/CardFlip/res/layout/main.xml
new file mode 100644
index 0000000..ef23d69
--- /dev/null
+++ b/samples/devbytes/animation/CardFlip/res/layout/main.xml
@@ -0,0 +1,19 @@
+<!-- Copyright (C) 2013 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.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/main_relative_layout"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+</RelativeLayout>
\ No newline at end of file
diff --git a/samples/devbytes/animation/CardFlip/res/values/integer.xml b/samples/devbytes/animation/CardFlip/res/values/integer.xml
new file mode 100644
index 0000000..2eb363c
--- /dev/null
+++ b/samples/devbytes/animation/CardFlip/res/values/integer.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <integer name="vertical_card_magin">30</integer>
+    <integer name="horizontal_card_magin">30</integer>
+
+</resources>
\ No newline at end of file
diff --git a/samples/devbytes/animation/CardFlip/res/values/strings.xml b/samples/devbytes/animation/CardFlip/res/values/strings.xml
new file mode 100644
index 0000000..bd248d1
--- /dev/null
+++ b/samples/devbytes/animation/CardFlip/res/values/strings.xml
@@ -0,0 +1,19 @@
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <string name="app_name">CardFlip</string>
+
+</resources>
diff --git a/samples/devbytes/animation/CardFlip/src/com/example/android/cardflip/CardFlip.java b/samples/devbytes/animation/CardFlip/src/com/example/android/cardflip/CardFlip.java
new file mode 100644
index 0000000..746afec
--- /dev/null
+++ b/samples/devbytes/animation/CardFlip/src/com/example/android/cardflip/CardFlip.java
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2013 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.cardflip;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.app.Activity;
+import android.os.Build;
+import android.os.Bundle;
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+import android.view.ViewTreeObserver;
+import android.widget.RelativeLayout;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This application creates 2 stacks of playing cards. Using fling events,
+ * these cards can be flipped from one stack to another where each flip comes with
+ * an associated animation. The cards can be flipped horizontally from left to right
+ * or right to left depending on which stack the animating card currently belongs to.
+ *
+ * This application demonstrates an animation where a stack of cards can either be
+ * be rotated out or back in about their bottom left corner in a counter-clockwise direction.
+ * Rotate out: Down fling on stack of cards
+ * Rotate in: Up fling on stack of cards
+ * Full rotation: Tap on stack of cards
+ *
+ * Note that in this demo touch events are disabled in the middle of any animation so
+ * only one card can be flipped at a time. When the cards are in a rotated-out
+ * state, no new cards can be rotated to or from that stack. These changes were made to
+ * simplify the code for this demo.
+ */
+
+public class CardFlip extends Activity implements CardFlipListener {
+
+    final static int CARD_PILE_OFFSET = 3;
+    final static int STARTING_NUMBER_CARDS = 15;
+    final static int RIGHT_STACK = 0;
+    final static int LEFT_STACK = 1;
+
+    int mCardWidth = 0;
+    int mCardHeight = 0;
+
+    int mVerticalPadding;
+    int mHorizontalPadding;
+
+    boolean mTouchEventsEnabled = true;
+    boolean[] mIsStackEnabled;
+
+    RelativeLayout mLayout;
+
+    List<ArrayList<CardView>> mStackCards;
+
+    GestureDetector gDetector;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+
+        mStackCards = new ArrayList<ArrayList<CardView>>();
+        mStackCards.add(new ArrayList<CardView>());
+        mStackCards.add(new ArrayList<CardView>());
+
+        mIsStackEnabled = new boolean[2];
+        mIsStackEnabled[0] = true;
+        mIsStackEnabled[1] = true;
+
+        mVerticalPadding = getResources().getInteger(R.integer.vertical_card_magin);
+        mHorizontalPadding = getResources().getInteger(R.integer.horizontal_card_magin);
+
+        gDetector = new GestureDetector(this, mGestureListener);
+
+        mLayout = (RelativeLayout)findViewById(R.id.main_relative_layout);
+        ViewTreeObserver observer = mLayout.getViewTreeObserver();
+        observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
+            @Override
+            public void onGlobalLayout() {
+                if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+                    mLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+                } else {
+                    mLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
+                }
+
+                mCardHeight = mLayout.getHeight();
+                mCardWidth = mLayout.getWidth() / 2;
+
+                for (int x = 0; x < STARTING_NUMBER_CARDS; x++) {
+                    addNewCard(RIGHT_STACK);
+                }
+            }
+        });
+    }
+
+    /**
+     * Adds a new card to the specified stack. Also performs all the necessary layout setup
+     * to place the card in the correct position.
+     */
+    public void addNewCard(int stack) {
+        CardView view = new CardView(this);
+        view.updateTranslation(mStackCards.get(stack).size());
+        view.setCardFlipListener(this);
+        view.setPadding(mHorizontalPadding, mVerticalPadding, mHorizontalPadding, mVerticalPadding);
+
+        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(mCardWidth,
+                mCardHeight);
+        params.topMargin = 0;
+        params.leftMargin = (stack == RIGHT_STACK ? mCardWidth : 0);
+
+        mStackCards.get(stack).add(view);
+        mLayout.addView(view, params);
+    }
+
+    /**
+     * Gesture Detector listens for fling events in order to potentially initiate
+     * a card flip event when a fling event occurs. Also listens for tap events in
+     * order to potentially initiate a full rotation animation.
+     */
+    private GestureDetector.SimpleOnGestureListener mGestureListener = new GestureDetector
+            .SimpleOnGestureListener() {
+        @Override
+        public boolean onSingleTapUp(MotionEvent motionEvent) {
+            int stack = getStack(motionEvent);
+            rotateCardsFullRotation(stack, CardView.Corner.BOTTOM_LEFT);
+            return true;
+        }
+
+        @Override
+        public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent2, float v,
+                               float v2) {
+            int stack = getStack(motionEvent);
+            ArrayList<CardView> cardStack = mStackCards.get(stack);
+            int size = cardStack.size();
+            if (size > 0) {
+                rotateCardView(cardStack.get(size - 1), stack, v, v2);
+            }
+            return true;
+        }
+    };
+
+    /** Returns the appropriate stack corresponding to the MotionEvent. */
+    public int getStack(MotionEvent ev) {
+        boolean isLeft = ev.getX() <= mCardWidth;
+        return isLeft ? LEFT_STACK : RIGHT_STACK;
+    }
+
+    /**
+     * Uses the stack parameter, along with the velocity values of the fling event
+     * to determine in what direction the card must be flipped. By the same logic, the
+     * new stack that the card belongs to after the animation is also determined
+     * and updated.
+     */
+    public void rotateCardView(final CardView cardView, int stack, float velocityX,
+                               float velocityY) {
+
+        boolean xGreaterThanY = Math.abs(velocityX) > Math.abs(velocityY);
+
+        boolean bothStacksEnabled = mIsStackEnabled[RIGHT_STACK] && mIsStackEnabled[LEFT_STACK];
+
+        ArrayList<CardView>leftStack = mStackCards.get(LEFT_STACK);
+        ArrayList<CardView>rightStack = mStackCards.get(RIGHT_STACK);
+
+        switch (stack) {
+            case RIGHT_STACK:
+                if (velocityX < 0 &&  xGreaterThanY) {
+                    if (!bothStacksEnabled) {
+                        break;
+                    }
+                    mLayout.bringChildToFront(cardView);
+                    mLayout.requestLayout();
+                    rightStack.remove(rightStack.size() - 1);
+                    leftStack.add(cardView);
+                    cardView.flipRightToLeft(leftStack.size() - 1, (int)velocityX);
+                    break;
+                } else if (!xGreaterThanY) {
+                    boolean rotateCardsOut = velocityY > 0;
+                    rotateCards(RIGHT_STACK, CardView.Corner.BOTTOM_LEFT, rotateCardsOut);
+                }
+                break;
+            case LEFT_STACK:
+                if (velocityX > 0 && xGreaterThanY) {
+                    if (!bothStacksEnabled) {
+                        break;
+                    }
+                    mLayout.bringChildToFront(cardView);
+                    mLayout.requestLayout();
+                    leftStack.remove(leftStack.size() - 1);
+                    rightStack.add(cardView);
+                    cardView.flipLeftToRight(rightStack.size() - 1, (int)velocityX);
+                    break;
+                } else if (!xGreaterThanY) {
+                    boolean rotateCardsOut = velocityY > 0;
+                    rotateCards(LEFT_STACK, CardView.Corner.BOTTOM_LEFT, rotateCardsOut);
+                }
+                break;
+            default:
+                break;
+        }
+    }
+
+    @Override
+    public void onCardFlipEnd() {
+        mTouchEventsEnabled = true;
+    }
+
+    @Override
+    public void onCardFlipStart() {
+        mTouchEventsEnabled = false;
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent me) {
+        if (mTouchEventsEnabled) {
+            return gDetector.onTouchEvent(me);
+        } else {
+            return super.onTouchEvent(me);
+        }
+    }
+
+    /**
+     * Retrieves an animator object for each card in the specified stack that either
+     * rotates it in or out depending on its current state. All of these animations
+     * are then played together.
+     */
+    public void rotateCards (final int stack, CardView.Corner corner,
+                             final boolean isRotatingOut) {
+        List<Animator> animations = new ArrayList<Animator>();
+
+        ArrayList <CardView> cards = mStackCards.get(stack);
+
+        for (int i = 0; i < cards.size(); i++) {
+            CardView cardView = cards.get(i);
+            animations.add(cardView.getRotationAnimator(i, corner, isRotatingOut, false));
+            mLayout.bringChildToFront(cardView);
+        }
+        /** All the cards are being brought to the front in order to guarantee that
+         * the cards being rotated in the current stack will overlay the cards in the
+         * other stack. After the z-ordering of all the cards is updated, a layout must
+         * be requested in order to apply the changes made.*/
+        mLayout.requestLayout();
+
+        AnimatorSet set = new AnimatorSet();
+        set.playTogether(animations);
+        set.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mIsStackEnabled[stack] = !isRotatingOut;
+            }
+        });
+        set.start();
+    }
+
+    /**
+     * Retrieves an animator object for each card in the specified stack to complete a
+     * full revolution around one of its corners, and plays all of them together.
+     */
+    public void rotateCardsFullRotation (int stack, CardView.Corner corner) {
+        List<Animator> animations = new ArrayList<Animator>();
+
+        ArrayList <CardView> cards = mStackCards.get(stack);
+        for (int i = 0; i < cards.size(); i++) {
+            CardView cardView = cards.get(i);
+            animations.add(cardView.getFullRotationAnimator(i, corner, false));
+            mLayout.bringChildToFront(cardView);
+        }
+        /** Same reasoning for bringing cards to front as in rotateCards().*/
+        mLayout.requestLayout();
+
+        mTouchEventsEnabled = false;
+        AnimatorSet set = new AnimatorSet();
+        set.playTogether(animations);
+        set.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mTouchEventsEnabled = true;
+            }
+        });
+        set.start();
+    }
+}
\ No newline at end of file
diff --git a/samples/devbytes/animation/CardFlip/src/com/example/android/cardflip/CardFlipListener.java b/samples/devbytes/animation/CardFlip/src/com/example/android/cardflip/CardFlipListener.java
new file mode 100644
index 0000000..0af6941
--- /dev/null
+++ b/samples/devbytes/animation/CardFlip/src/com/example/android/cardflip/CardFlipListener.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2013 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.cardflip;
+
+/**
+ * This interface is used to prevent flipping multiple cards at the same time.
+ * These callback methods are used to disable and re-enable touches when a card
+ * flip animation begins and ends respectively.
+ * */
+public interface CardFlipListener {
+    public void onCardFlipEnd();
+    public void onCardFlipStart();
+}
diff --git a/samples/devbytes/animation/CardFlip/src/com/example/android/cardflip/CardView.java b/samples/devbytes/animation/CardFlip/src/com/example/android/cardflip/CardView.java
new file mode 100644
index 0000000..9a3ab71
--- /dev/null
+++ b/samples/devbytes/animation/CardFlip/src/com/example/android/cardflip/CardView.java
@@ -0,0 +1,329 @@
+/*
+ * Copyright (C) 2013 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.cardflip;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.Keyframe;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.drawable.BitmapDrawable;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+
+/**
+ * This CardView object is a view which can flip horizontally about its edges,
+ * as well as rotate clockwise or counter-clockwise about any of its corners. In
+ * the middle of a flip animation, this view darkens to imitate a shadow-like effect.
+ *
+ * The key behind the design of this view is the fact that the layout parameters and
+ * the animation properties of this view are updated and reset respectively after
+ * every single animation. Therefore, every consecutive animation that this
+ * view experiences is completely independent of what its prior state was.
+ */
+public class CardView extends ImageView {
+
+    enum Corner {
+        TOP_LEFT,
+        TOP_RIGHT,
+        BOTTOM_LEFT,
+        BOTTOM_RIGHT
+    }
+
+    private final int CAMERA_DISTANCE = 8000;
+    private final int MIN_FLIP_DURATION = 300;
+    private final int VELOCITY_TO_DURATION_CONSTANT = 15;
+    private final int MAX_FLIP_DURATION = 700;
+    private final int ROTATION_PER_CARD = 2;
+    private final int ROTATION_DELAY_PER_CARD = 50;
+    private final int ROTATION_DURATION = 2000;
+    private final int ANTIALIAS_BORDER = 1;
+
+    private BitmapDrawable mFrontBitmapDrawable, mBackBitmapDrawable, mCurrentBitmapDrawable;
+
+    private boolean mIsFrontShowing = true;
+    private boolean mIsHorizontallyFlipped = false;
+
+    private Matrix mHorizontalFlipMatrix;
+
+    private CardFlipListener mCardFlipListener;
+
+    public CardView(Context context) {
+        super(context);
+        init(context);
+    }
+
+    public CardView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init(context);
+    }
+
+    /** Loads the bitmap drawables used for the front and back for this card.*/
+    public void init(Context context) {
+        mHorizontalFlipMatrix = new Matrix();
+
+        setCameraDistance(CAMERA_DISTANCE);
+
+        mFrontBitmapDrawable = bitmapWithBorder((BitmapDrawable)getResources()
+                .getDrawable(R.drawable.red));
+        mBackBitmapDrawable = bitmapWithBorder((BitmapDrawable) getResources()
+                .getDrawable(R.drawable.blue));
+
+        updateDrawableBitmap();
+    }
+
+    /**
+     *  Adding a 1 pixel transparent border around the bitmap can be used to
+     *  anti-alias the image as it rotates.
+     */
+    private BitmapDrawable bitmapWithBorder(BitmapDrawable bitmapDrawable) {
+        Bitmap bitmapWithBorder = Bitmap.createBitmap(bitmapDrawable.getIntrinsicWidth() +
+                ANTIALIAS_BORDER * 2, bitmapDrawable.getIntrinsicHeight() + ANTIALIAS_BORDER * 2,
+                Bitmap.Config.ARGB_8888);
+        Canvas canvas = new Canvas(bitmapWithBorder);
+        canvas.drawBitmap(bitmapDrawable.getBitmap(), ANTIALIAS_BORDER, ANTIALIAS_BORDER, null);
+        return new BitmapDrawable(getResources(), bitmapWithBorder);
+    }
+
+    /** Initiates a horizontal flip from right to left. */
+    public void flipRightToLeft(int numberInPile, int velocity) {
+        setPivotX(0);
+        flipHorizontally(numberInPile, false, velocity);
+    }
+
+    /** Initiates a horizontal flip from left to right. */
+    public void flipLeftToRight(int numberInPile, int velocity) {
+        setPivotX(getWidth());
+        flipHorizontally(numberInPile, true, velocity);
+    }
+
+    /**
+     * Animates a horizontal (about the y-axis) flip of this card.
+     * @param numberInPile Specifies how many cards are underneath this card in the new
+     *                     pile so as to properly adjust its position offset in the stack.
+     * @param clockwise Specifies whether the horizontal animation is 180 degrees
+     *                  clockwise or 180 degrees counter clockwise.
+     */
+    public void flipHorizontally (int numberInPile, boolean clockwise, int velocity) {
+        toggleFrontShowing();
+
+        PropertyValuesHolder rotation = PropertyValuesHolder.ofFloat(View.ROTATION_Y,
+                clockwise ? 180 : -180);
+
+        PropertyValuesHolder xOffset = PropertyValuesHolder.ofFloat(View.TRANSLATION_X,
+                numberInPile * CardFlip.CARD_PILE_OFFSET);
+        PropertyValuesHolder yOffset = PropertyValuesHolder.ofFloat(View.TRANSLATION_Y,
+                numberInPile * CardFlip.CARD_PILE_OFFSET);
+
+        ObjectAnimator cardAnimator = ObjectAnimator.ofPropertyValuesHolder(this, rotation,
+                xOffset, yOffset);
+        cardAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator valueAnimator) {
+                if (valueAnimator.getAnimatedFraction() >= 0.5) {
+                    updateDrawableBitmap();
+                }
+            }
+        });
+
+        Keyframe shadowKeyFrameStart = Keyframe.ofFloat(0, 0);
+        Keyframe shadowKeyFrameMid = Keyframe.ofFloat(0.5f, 1);
+        Keyframe shadowKeyFrameEnd = Keyframe.ofFloat(1, 0);
+        PropertyValuesHolder shadowPropertyValuesHolder = PropertyValuesHolder.ofKeyframe
+                ("shadow", shadowKeyFrameStart, shadowKeyFrameMid, shadowKeyFrameEnd);
+        ObjectAnimator colorizer = ObjectAnimator.ofPropertyValuesHolder(this,
+                shadowPropertyValuesHolder);
+
+        mCardFlipListener.onCardFlipStart();
+        AnimatorSet set = new AnimatorSet();
+        int duration = MAX_FLIP_DURATION - Math.abs(velocity) / VELOCITY_TO_DURATION_CONSTANT;
+        duration = duration < MIN_FLIP_DURATION ? MIN_FLIP_DURATION : duration;
+        set.setDuration(duration);
+        set.playTogether(cardAnimator, colorizer);
+        set.setInterpolator(new AccelerateDecelerateInterpolator());
+        set.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                toggleIsHorizontallyFlipped();
+                updateDrawableBitmap();
+                updateLayoutParams();
+                mCardFlipListener.onCardFlipEnd();
+            }
+        });
+        set.start();
+    }
+
+    /** Darkens this ImageView's image by applying a shadow color filter over it. */
+    public void setShadow(float value) {
+        int colorValue = (int)(255 - 200 * value);
+        setColorFilter(Color.rgb(colorValue, colorValue, colorValue),
+                android.graphics.PorterDuff.Mode.MULTIPLY);
+    }
+
+    public void toggleFrontShowing() {
+        mIsFrontShowing = !mIsFrontShowing;
+    }
+
+    public void toggleIsHorizontallyFlipped() {
+        mIsHorizontallyFlipped = !mIsHorizontallyFlipped;
+        invalidate();
+    }
+
+    @Override
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        super.onSizeChanged(w, h, oldw, oldh);
+        mHorizontalFlipMatrix.setScale(-1, 1, w / 2, h / 2);
+    }
+
+    /**
+     *  Scale the canvas horizontally about its midpoint in the case that the card
+     *  is in a horizontally flipped state.
+     */
+    @Override
+    protected void onDraw(Canvas canvas) {
+        if (mIsHorizontallyFlipped) {
+            canvas.concat(mHorizontalFlipMatrix);
+        }
+        super.onDraw(canvas);
+    }
+
+    /**
+     *  Updates the layout parameters of this view so as to reset the rotationX and
+     *  rotationY parameters, and remain independent of its previous position, while
+     *  also maintaining its current position in the layout.
+     */
+    public void updateLayoutParams () {
+        RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) getLayoutParams();
+
+        params.leftMargin = (int)(params.leftMargin + ((Math.abs(getRotationY()) % 360) / 180) *
+                (2 * getPivotX () - getWidth()));
+
+        setRotationX(0);
+        setRotationY(0);
+
+        setLayoutParams(params);
+    }
+
+    /**
+     * Toggles the visible bitmap of this view between its front and back drawables
+     * respectively.
+     */
+    public void updateDrawableBitmap () {
+        mCurrentBitmapDrawable = mIsFrontShowing ? mFrontBitmapDrawable : mBackBitmapDrawable;
+        setImageDrawable(mCurrentBitmapDrawable);
+    }
+
+    /**
+     * Sets the appropriate translation of this card depending on how many cards
+     * are in the pile underneath it.
+     */
+    public void updateTranslation (int numInPile) {
+        setTranslationX(CardFlip.CARD_PILE_OFFSET * numInPile);
+        setTranslationY(CardFlip.CARD_PILE_OFFSET * numInPile);
+    }
+
+    /**
+     * Returns a rotation animation which rotates this card by some degree about
+     * one of its corners either in the clockwise or counter-clockwise direction.
+     * Depending on how many cards lie below this one in the stack, this card will
+     * be rotated by a different amount so all the cards are visible when rotated out.
+     */
+    public ObjectAnimator getRotationAnimator (int cardFromTop, Corner corner,
+                                               boolean isRotatingOut, boolean isClockwise) {
+        rotateCardAroundCorner(corner);
+        int rotation = cardFromTop * ROTATION_PER_CARD;
+
+        if (!isClockwise) {
+            rotation = -rotation;
+        }
+
+        if (!isRotatingOut) {
+            rotation = 0;
+        }
+
+        return ObjectAnimator.ofFloat(this, View.ROTATION, rotation);
+    }
+
+    /**
+     * Returns a full rotation animator which rotates this card by 360 degrees
+     * about one of its corners either in the clockwise or counter-clockwise direction.
+     * Depending on how many cards lie below this one in the stack, a different start
+     * delay is applied to the animation so the cards don't all animate at once.
+     */
+    public ObjectAnimator getFullRotationAnimator (int cardFromTop, Corner corner,
+                                                   boolean isClockwise) {
+        final int currentRotation = (int)getRotation();
+
+        rotateCardAroundCorner(corner);
+        int rotation = 360 - currentRotation;
+        rotation =  isClockwise ? rotation : -rotation;
+
+        ObjectAnimator animator = ObjectAnimator.ofFloat(this, View.ROTATION, rotation);
+
+        animator.setStartDelay(ROTATION_DELAY_PER_CARD * cardFromTop);
+        animator.setDuration(ROTATION_DURATION);
+
+        animator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                setRotation(currentRotation);
+            }
+        });
+
+        return animator;
+    }
+
+    /**
+     * Sets the appropriate pivot of this card so that it can be rotated about
+     * any one of its four corners.
+     */
+    public void rotateCardAroundCorner(Corner corner) {
+        switch(corner) {
+            case TOP_LEFT:
+                setPivotX(0);
+                setPivotY(0);
+                break;
+            case TOP_RIGHT:
+                setPivotX(getWidth());
+                setPivotY(0);
+                break;
+            case BOTTOM_LEFT:
+                setPivotX(0);
+                setPivotY(getHeight());
+                break;
+            case BOTTOM_RIGHT:
+                setPivotX(getWidth());
+                setPivotY(getHeight());
+                break;
+        }
+    }
+
+    public void setCardFlipListener(CardFlipListener cardFlipListener) {
+        mCardFlipListener = cardFlipListener;
+    }
+
+}
diff --git a/samples/devbytes/animation/CurvedMotion/AndroidManifest.xml b/samples/devbytes/animation/CurvedMotion/AndroidManifest.xml
new file mode 100644
index 0000000..195faae
--- /dev/null
+++ b/samples/devbytes/animation/CurvedMotion/AndroidManifest.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.android.curvedmotion"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk
+        android:minSdkVersion="11"
+        android:targetSdkVersion="11" />
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/ic_launcher"
+        android:label="@string/app_name"
+        android:theme="@style/AppTheme" >
+        <activity
+            android:name="com.example.android.curvedmotion.CurvedMotion"
+            android:label="@string/app_name" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest>
\ No newline at end of file
diff --git a/samples/devbytes/animation/CurvedMotion/res/drawable-hdpi/ic_launcher.png b/samples/devbytes/animation/CurvedMotion/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..96a442e
--- /dev/null
+++ b/samples/devbytes/animation/CurvedMotion/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/CurvedMotion/res/drawable-mdpi/ic_launcher.png b/samples/devbytes/animation/CurvedMotion/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..359047d
--- /dev/null
+++ b/samples/devbytes/animation/CurvedMotion/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/CurvedMotion/res/drawable-xhdpi/ic_launcher.png b/samples/devbytes/animation/CurvedMotion/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..71c6d76
--- /dev/null
+++ b/samples/devbytes/animation/CurvedMotion/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/CurvedMotion/res/layout/activity_curved_motion.xml b/samples/devbytes/animation/CurvedMotion/res/layout/activity_curved_motion.xml
new file mode 100644
index 0000000..10adea3
--- /dev/null
+++ b/samples/devbytes/animation/CurvedMotion/res/layout/activity_curved_motion.xml
@@ -0,0 +1,33 @@
+<!-- Copyright (C) 2013 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.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:paddingBottom="@dimen/activity_vertical_margin"
+    android:paddingLeft="@dimen/activity_horizontal_margin"
+    android:paddingRight="@dimen/activity_horizontal_margin"
+    android:paddingTop="@dimen/activity_vertical_margin"
+    tools:context=".CurvedMotion" >
+
+    <Button
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentLeft="true"
+        android:layout_alignParentTop="true"
+        android:id="@+id/button"
+        android:text="Click Me!" />
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/samples/devbytes/animation/CurvedMotion/res/values-v11/styles.xml b/samples/devbytes/animation/CurvedMotion/res/values-v11/styles.xml
new file mode 100644
index 0000000..556d2da
--- /dev/null
+++ b/samples/devbytes/animation/CurvedMotion/res/values-v11/styles.xml
@@ -0,0 +1,25 @@
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <!--
+        Base application theme for API 11+. This theme completely replaces
+        AppBaseTheme from res/values/styles.xml on API 11+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+        <!-- API 11 theme customizations can go here. -->
+    </style>
+
+</resources>
\ No newline at end of file
diff --git a/samples/devbytes/animation/CurvedMotion/res/values-v14/styles.xml b/samples/devbytes/animation/CurvedMotion/res/values-v14/styles.xml
new file mode 100644
index 0000000..6e9521a
--- /dev/null
+++ b/samples/devbytes/animation/CurvedMotion/res/values-v14/styles.xml
@@ -0,0 +1,26 @@
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <!--
+        Base application theme for API 14+. This theme completely replaces
+        AppBaseTheme from BOTH res/values/styles.xml and
+        res/values-v11/styles.xml on API 14+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+        <!-- API 14 theme customizations can go here. -->
+    </style>
+
+</resources>
\ No newline at end of file
diff --git a/samples/devbytes/animation/CurvedMotion/res/values/dimens.xml b/samples/devbytes/animation/CurvedMotion/res/values/dimens.xml
new file mode 100644
index 0000000..90db76b
--- /dev/null
+++ b/samples/devbytes/animation/CurvedMotion/res/values/dimens.xml
@@ -0,0 +1,21 @@
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <!-- Default screen margins, per the Android Design guidelines. -->
+    <dimen name="activity_horizontal_margin">16dp</dimen>
+    <dimen name="activity_vertical_margin">16dp</dimen>
+
+</resources>
\ No newline at end of file
diff --git a/samples/devbytes/animation/CurvedMotion/res/values/strings.xml b/samples/devbytes/animation/CurvedMotion/res/values/strings.xml
new file mode 100644
index 0000000..a070e15
--- /dev/null
+++ b/samples/devbytes/animation/CurvedMotion/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <string name="app_name">CurvedMotion</string>
+    <string name="action_settings">Settings</string>
+    <string name="hello_world">Hello world!</string>
+
+</resources>
\ No newline at end of file
diff --git a/samples/devbytes/animation/CurvedMotion/res/values/styles.xml b/samples/devbytes/animation/CurvedMotion/res/values/styles.xml
new file mode 100644
index 0000000..27658b7
--- /dev/null
+++ b/samples/devbytes/animation/CurvedMotion/res/values/styles.xml
@@ -0,0 +1,34 @@
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <!--
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Light">
+        <!--
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        -->
+    </style>
+
+    <!-- Application theme. -->
+    <style name="AppTheme" parent="AppBaseTheme">
+        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+    </style>
+
+</resources>
\ No newline at end of file
diff --git a/samples/devbytes/animation/CurvedMotion/src/com/example/android/curvedmotion/AnimatorPath.java b/samples/devbytes/animation/CurvedMotion/src/com/example/android/curvedmotion/AnimatorPath.java
new file mode 100644
index 0000000..d030c6a
--- /dev/null
+++ b/samples/devbytes/animation/CurvedMotion/src/com/example/android/curvedmotion/AnimatorPath.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2013 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.curvedmotion;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * A simple Path object that holds information about the points along
+ * a path. The API allows you to specify a move location (which essentially
+ * jumps from the previous point in the path to the new one), a line location
+ * (which creates a line segment from the previous location) and a curve
+ * location (which creates a B�zier curve from the previous location).
+ */
+public class AnimatorPath {
+    
+    // The points in the path
+    ArrayList<PathPoint> mPoints = new ArrayList<PathPoint>();
+
+
+    /**
+     * Move from the current path point to the new one
+     * specified by x and y. This will create a discontinuity if this point is
+     * neither the first point in the path nor the same as the previous point
+     * in the path.
+     */
+    public void moveTo(float x, float y) {
+        mPoints.add(PathPoint.moveTo(x, y));
+    }
+
+    /**
+     * Create a straight line from the current path point to the new one
+     * specified by x and y.
+     */
+    public void lineTo(float x, float y) {
+        mPoints.add(PathPoint.lineTo(x, y));
+    }
+
+    /**
+     * Create a quadratic B�zier curve from the current path point to the new one
+     * specified by x and y. The curve uses the current path location as the first anchor
+     * point, the control points (c0X, c0Y) and (c1X, c1Y), and (x, y) as the end anchor.
+     */
+    public void curveTo(float c0X, float c0Y, float c1X, float c1Y, float x, float y) {
+        mPoints.add(PathPoint.curveTo(c0X, c0Y, c1X, c1Y, x, y));
+    }
+
+    /**
+     * Returns a Collection of PathPoint objects that describe all points in the path.
+     */
+    public Collection<PathPoint> getPoints() {
+        return mPoints;
+    }
+}
diff --git a/samples/devbytes/animation/CurvedMotion/src/com/example/android/curvedmotion/CurvedMotion.java b/samples/devbytes/animation/CurvedMotion/src/com/example/android/curvedmotion/CurvedMotion.java
new file mode 100644
index 0000000..357d72d
--- /dev/null
+++ b/samples/devbytes/animation/CurvedMotion/src/com/example/android/curvedmotion/CurvedMotion.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2013 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.curvedmotion;
+
+import android.animation.ObjectAnimator;
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewTreeObserver;
+import android.view.animation.DecelerateInterpolator;
+import android.widget.Button;
+import android.widget.RelativeLayout;
+import android.widget.RelativeLayout.LayoutParams;
+
+/**
+ * This app shows how to move a view in a curved path between two endpoints.
+ * The real work is done by PathEvaluator, which interpolates along a path
+ * using Bezier control and anchor points in the path.
+ *
+ * Watch the associated video for this demo on the DevBytes channel of developer.android.com
+ * or on the DevBytes playlist in the androiddevelopers channel on YouTube at
+ * https://www.youtube.com/playlist?list=PLWz5rJ2EKKc_XOgcRukSoKKjewFJZrKV0.
+ */
+public class CurvedMotion extends Activity {
+
+    private static final DecelerateInterpolator sDecelerateInterpolator =
+            new DecelerateInterpolator();
+    boolean mTopLeft = true;
+    Button mButton;
+    
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_curved_motion);
+        
+        mButton = (Button) findViewById(R.id.button);
+        mButton.setOnClickListener(new View.OnClickListener() {
+            
+            @Override
+            public void onClick(View v) {
+                // Capture current location of button
+                final int oldLeft = mButton.getLeft();
+                final int oldTop = mButton.getTop();
+                
+                // Change layout parameters of button to move it
+                moveButton();
+                
+                // Add OnPreDrawListener to catch button after layout but before drawing
+                mButton.getViewTreeObserver().addOnPreDrawListener(
+                        new ViewTreeObserver.OnPreDrawListener() {
+                            public boolean onPreDraw() {
+                                mButton.getViewTreeObserver().removeOnPreDrawListener(this);
+                                
+                                // Capture new location
+                                int left = mButton.getLeft();
+                                int top = mButton.getTop();
+                                int deltaX = left - oldLeft;
+                                int deltaY = top - oldTop;
+
+                                // Set up path to new location using a B�zier spline curve
+                                AnimatorPath path = new AnimatorPath();
+                                path.moveTo(-deltaX, -deltaY);
+                                path.curveTo(-(deltaX/2), -deltaY, 0, -deltaY/2, 0, 0);
+                                
+                                // Set up the animation
+                                final ObjectAnimator anim = ObjectAnimator.ofObject(
+                                        CurvedMotion.this, "buttonLoc", 
+                                        new PathEvaluator(), path.getPoints().toArray());
+                                anim.setInterpolator(sDecelerateInterpolator);
+                                anim.start();
+                                return true;
+                            }
+                        });
+            }
+        });
+    }
+    
+    /**
+     * Toggles button location on click between top-left and bottom-right
+     */
+    private void moveButton() {
+        LayoutParams params = (LayoutParams) mButton.getLayoutParams();
+        if (mTopLeft) {
+            params.removeRule(RelativeLayout.ALIGN_PARENT_LEFT);
+            params.removeRule(RelativeLayout.ALIGN_PARENT_TOP);
+            params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
+            params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
+        } else {
+            params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
+            params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
+            params.removeRule(RelativeLayout.ALIGN_PARENT_RIGHT);
+            params.removeRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
+        }
+        mButton.setLayoutParams(params);
+        mTopLeft = !mTopLeft;
+    }
+
+    /**
+     * We need this setter to translate between the information the animator
+     * produces (a new "PathPoint" describing the current animated location)
+     * and the information that the button requires (an xy location). The
+     * setter will be called by the ObjectAnimator given the 'buttonLoc'
+     * property string.
+     */
+    public void setButtonLoc(PathPoint newLoc) {
+        mButton.setTranslationX(newLoc.mX);
+        mButton.setTranslationY(newLoc.mY);
+    }
+
+}
diff --git a/samples/devbytes/animation/CurvedMotion/src/com/example/android/curvedmotion/PathEvaluator.java b/samples/devbytes/animation/CurvedMotion/src/com/example/android/curvedmotion/PathEvaluator.java
new file mode 100644
index 0000000..e68d4cd
--- /dev/null
+++ b/samples/devbytes/animation/CurvedMotion/src/com/example/android/curvedmotion/PathEvaluator.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2013 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.curvedmotion;
+
+import android.animation.TypeEvaluator;
+
+/**
+ * This evaluator interpolates between two PathPoint values given the value t, the
+ * proportion traveled between those points. The value of the interpolation depends
+ * on the operation specified by the endValue (the operation for the interval between
+ * PathPoints is always specified by the end point of that interval).
+ */
+public class PathEvaluator implements TypeEvaluator<PathPoint> {
+    @Override
+    public PathPoint evaluate(float t, PathPoint startValue, PathPoint endValue) {
+        float x, y;
+        if (endValue.mOperation == PathPoint.CURVE) {
+            float oneMinusT = 1 - t;
+            x = oneMinusT * oneMinusT * oneMinusT * startValue.mX +
+                    3 * oneMinusT * oneMinusT * t * endValue.mControl0X +
+                    3 * oneMinusT * t * t * endValue.mControl1X +
+                    t * t * t * endValue.mX;
+            y = oneMinusT * oneMinusT * oneMinusT * startValue.mY +
+                    3 * oneMinusT * oneMinusT * t * endValue.mControl0Y +
+                    3 * oneMinusT * t * t * endValue.mControl1Y +
+                    t * t * t * endValue.mY;
+        } else if (endValue.mOperation == PathPoint.LINE) {
+            x = startValue.mX + t * (endValue.mX - startValue.mX);
+            y = startValue.mY + t * (endValue.mY - startValue.mY);
+        } else {
+            x = endValue.mX;
+            y = endValue.mY;
+        }
+        return PathPoint.moveTo(x, y);
+    }
+}
diff --git a/samples/devbytes/animation/CurvedMotion/src/com/example/android/curvedmotion/PathPoint.java b/samples/devbytes/animation/CurvedMotion/src/com/example/android/curvedmotion/PathPoint.java
new file mode 100644
index 0000000..ba1a05e
--- /dev/null
+++ b/samples/devbytes/animation/CurvedMotion/src/com/example/android/curvedmotion/PathPoint.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2013 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.curvedmotion;
+
+/**
+ * A class that holds information about a location and how the path should get to that
+ * location from the previous path location (if any). Any PathPoint holds the information for
+ * its location as well as the instructions on how to traverse the preceding interval from the
+ * previous location.
+ */
+public class PathPoint {
+
+    /**
+     * The possible path operations that describe how to move from a preceding PathPoint to the
+     * location described by this PathPoint.
+     */
+    public static final int MOVE = 0;
+    public static final int LINE = 1;
+    public static final int CURVE = 2;
+
+    /**
+     * The location of this PathPoint
+     */
+    float mX, mY;
+    
+    /**
+     * The first control point, if any, for a PathPoint of type CURVE
+     */
+    float mControl0X, mControl0Y;
+
+    /**
+     * The second control point, if any, for a PathPoint of type CURVE
+     */
+    float mControl1X, mControl1Y;
+
+    /**
+     * The motion described by the path to get from the previous PathPoint in an AnimatorPath
+     * to the location of this PathPoint. This can be one of MOVE, LINE, or CURVE.
+     */
+    int mOperation;
+
+
+
+    /**
+     * Line/Move constructor
+     */
+    private PathPoint(int operation, float x, float y) {
+        mOperation = operation;
+        mX = x;
+        mY = y;
+    }
+
+    /**
+     * Curve constructor
+     */
+    private PathPoint(float c0X, float c0Y, float c1X, float c1Y, float x, float y) {
+        mControl0X = c0X;
+        mControl0Y = c0Y;
+        mControl1X = c1X;
+        mControl1Y = c1Y;
+        mX = x;
+        mY = y;
+        mOperation = CURVE;
+    }
+
+    /**
+     * Constructs and returns a PathPoint object that describes a line to the given xy location.
+     */
+    public static PathPoint lineTo(float x, float y) {
+        return new PathPoint(LINE, x, y);
+    }
+
+    /**
+     * Constructs and returns a PathPoint object that describes a curve to the given xy location
+     * with the control points at c0 and c1.
+     */
+    public static PathPoint curveTo(float c0X, float c0Y, float c1X, float c1Y, float x, float y) {
+        return new PathPoint(c0X,  c0Y, c1X, c1Y, x, y);
+    }
+    
+    /**
+     * Constructs and returns a PathPoint object that describes a discontinuous move to the given
+     * xy location.
+     */
+    public static PathPoint moveTo(float x, float y) {
+        return new PathPoint(MOVE, x, y);
+    }
+}
diff --git a/samples/devbytes/animation/ListViewCellInsertion/AndroidManifest.xml b/samples/devbytes/animation/ListViewCellInsertion/AndroidManifest.xml
new file mode 100644
index 0000000..230c2e7
--- /dev/null
+++ b/samples/devbytes/animation/ListViewCellInsertion/AndroidManifest.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.example.android.insertingcells"
+          android:versionCode="1"
+          android:versionName="1.0">
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-sdk android:minSdkVersion="14"
+              android:targetSdkVersion="17"/>
+    <application android:label="@string/app_name" android:icon="@drawable/ic_launcher">
+        <activity android:name=".InsertingCells"
+                  android:label="@string/app_name">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/samples/devbytes/animation/ListViewCellInsertion/res/drawable-hdpi/border.9.png b/samples/devbytes/animation/ListViewCellInsertion/res/drawable-hdpi/border.9.png
new file mode 100644
index 0000000..f76e008
--- /dev/null
+++ b/samples/devbytes/animation/ListViewCellInsertion/res/drawable-hdpi/border.9.png
Binary files differ
diff --git a/samples/devbytes/animation/ListViewCellInsertion/res/drawable-hdpi/chameleon.jpg b/samples/devbytes/animation/ListViewCellInsertion/res/drawable-hdpi/chameleon.jpg
new file mode 100644
index 0000000..686cc88
--- /dev/null
+++ b/samples/devbytes/animation/ListViewCellInsertion/res/drawable-hdpi/chameleon.jpg
Binary files differ
diff --git a/samples/devbytes/animation/ListViewCellInsertion/res/drawable-hdpi/flower.jpg b/samples/devbytes/animation/ListViewCellInsertion/res/drawable-hdpi/flower.jpg
new file mode 100644
index 0000000..8842483
--- /dev/null
+++ b/samples/devbytes/animation/ListViewCellInsertion/res/drawable-hdpi/flower.jpg
Binary files differ
diff --git a/samples/devbytes/animation/ListViewCellInsertion/res/drawable-hdpi/ic_launcher.png b/samples/devbytes/animation/ListViewCellInsertion/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..96a442e
--- /dev/null
+++ b/samples/devbytes/animation/ListViewCellInsertion/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/ListViewCellInsertion/res/drawable-hdpi/rock.jpg b/samples/devbytes/animation/ListViewCellInsertion/res/drawable-hdpi/rock.jpg
new file mode 100644
index 0000000..8ea0e85
--- /dev/null
+++ b/samples/devbytes/animation/ListViewCellInsertion/res/drawable-hdpi/rock.jpg
Binary files differ
diff --git a/samples/devbytes/animation/ListViewCellInsertion/res/drawable-ldpi/ic_launcher.png b/samples/devbytes/animation/ListViewCellInsertion/res/drawable-ldpi/ic_launcher.png
new file mode 100644
index 0000000..9923872
--- /dev/null
+++ b/samples/devbytes/animation/ListViewCellInsertion/res/drawable-ldpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/ListViewCellInsertion/res/drawable-mdpi/ic_launcher.png b/samples/devbytes/animation/ListViewCellInsertion/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..359047d
--- /dev/null
+++ b/samples/devbytes/animation/ListViewCellInsertion/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/ListViewCellInsertion/res/drawable-xhdpi/ic_launcher.png b/samples/devbytes/animation/ListViewCellInsertion/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..71c6d76
--- /dev/null
+++ b/samples/devbytes/animation/ListViewCellInsertion/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/ListViewCellInsertion/res/layout/activity_main.xml b/samples/devbytes/animation/ListViewCellInsertion/res/layout/activity_main.xml
new file mode 100644
index 0000000..e515309
--- /dev/null
+++ b/samples/devbytes/animation/ListViewCellInsertion/res/layout/activity_main.xml
@@ -0,0 +1,53 @@
+<!-- Copyright (C) 2013 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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:id="@+id/relative_layout"
+                xmlns:tools="http://schemas.android.com/tools"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:orientation="vertical"
+                tools:context=".MainActivity"
+                android:background="#111">
+
+    <LinearLayout
+            android:id="@+id/linear_layout"
+            android:layout_height="@dimen/cell_height"
+            android:layout_width="match_parent"
+            android:orientation="horizontal">
+
+        <com.example.android.insertingcells.RoundView
+                android:id="@+id/round_view"
+                android:layout_width="0dp"
+                android:layout_height="match_parent"
+                android:layout_weight="1"/>
+
+        <Button
+                android:id="@+id/add_row_button"
+                android:layout_width="0dp"
+                android:layout_height="match_parent"
+                android:text="@string/add_row"
+                android:onClick="addRow"
+                android:layout_weight="2"/>
+
+    </LinearLayout>
+
+    <com.example.android.insertingcells.InsertionListView
+            android:id="@+id/listview"
+            android:layout_below="@id/linear_layout"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"/>
+
+</RelativeLayout>
diff --git a/samples/devbytes/animation/ListViewCellInsertion/res/layout/list_view_item.xml b/samples/devbytes/animation/ListViewCellInsertion/res/layout/list_view_item.xml
new file mode 100644
index 0000000..e984b2e
--- /dev/null
+++ b/samples/devbytes/animation/ListViewCellInsertion/res/layout/list_view_item.xml
@@ -0,0 +1,40 @@
+<!-- Copyright (C) 2013 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:id="@+id/item_linear_layout"
+              android:layout_height="match_parent"
+              android:layout_width="match_parent"
+              android:orientation="horizontal"
+              android:background="@drawable/border">
+
+    <ImageView
+            android:id="@+id/image_view"
+            android:layout_height="match_parent"
+            android:layout_width="0dp"
+            android:gravity="center_vertical"
+            android:layout_weight="1"
+            android:scaleType="center"/>
+
+    <TextView
+            android:id="@+id/text_view"
+            android:layout_height="fill_parent"
+            android:layout_width="0dp"
+            android:gravity="center"
+            android:layout_weight="2"
+            android:textStyle="bold"
+            android:textSize="22sp"
+            android:textColor="#ffffff"/>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/samples/devbytes/animation/ListViewCellInsertion/res/values/dimensions.xml b/samples/devbytes/animation/ListViewCellInsertion/res/values/dimensions.xml
new file mode 100644
index 0000000..a18add3
--- /dev/null
+++ b/samples/devbytes/animation/ListViewCellInsertion/res/values/dimensions.xml
@@ -0,0 +1,21 @@
+<!-- Copyright (C) 2013 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.
+-->
+
+<resources>
+
+    <dimen name="circle_radius">50dp</dimen>
+    <dimen name="cell_height">150dp</dimen>
+
+</resources>
diff --git a/samples/devbytes/animation/ListViewCellInsertion/res/values/strings.xml b/samples/devbytes/animation/ListViewCellInsertion/res/values/strings.xml
new file mode 100644
index 0000000..cb57d69
--- /dev/null
+++ b/samples/devbytes/animation/ListViewCellInsertion/res/values/strings.xml
@@ -0,0 +1,21 @@
+<!-- Copyright (C) 2013 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.
+-->
+
+<resources>
+
+    <string name="app_name">InsertingCells</string>
+    <string name="add_row">Add Row</string>
+
+</resources>
diff --git a/samples/devbytes/animation/ListViewCellInsertion/src/com/example/android/insertingcells/CustomArrayAdapter.java b/samples/devbytes/animation/ListViewCellInsertion/src/com/example/android/insertingcells/CustomArrayAdapter.java
new file mode 100644
index 0000000..870d279
--- /dev/null
+++ b/samples/devbytes/animation/ListViewCellInsertion/src/com/example/android/insertingcells/CustomArrayAdapter.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2013 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.insertingcells;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PorterDuff.Mode;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * This custom array adapter is used to populate the ListView in this application.
+ * This adapter also maintains a map of unique stable ids for each object in the data set.
+ * Since this adapter has to support the addition of a new cell to the 1ist index, it also
+ * provides a mechanism to add a stable ID for new data that was recently inserted.
+ */
+public class CustomArrayAdapter extends ArrayAdapter<ListItemObject> {
+
+    HashMap<ListItemObject, Integer> mIdMap = new HashMap<ListItemObject, Integer>();
+    List<ListItemObject> mData;
+    Context mContext;
+    int mLayoutViewResourceId;
+    int mCounter;
+
+    public CustomArrayAdapter(Context context, int layoutViewResourceId,
+                              List <ListItemObject> data) {
+        super(context, layoutViewResourceId, data);
+        mData = data;
+        mContext = context;
+        mLayoutViewResourceId = layoutViewResourceId;
+        updateStableIds();
+    }
+
+    public long getItemId(int position) {
+        ListItemObject item = getItem(position);
+        if (mIdMap.containsKey(item)) {
+            return mIdMap.get(item);
+        }
+        return -1;
+    }
+
+    public void updateStableIds() {
+        mIdMap.clear();
+        mCounter = 0;
+        for (int i = 0; i < mData.size(); ++i) {
+            mIdMap.put(mData.get(i), mCounter++);
+        }
+    }
+
+    public void addStableIdForDataAtPosition(int position) {
+        mIdMap.put(mData.get(position), ++mCounter);
+    }
+
+    @Override
+    public boolean hasStableIds() {
+        return true;
+    }
+
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent) {
+
+        ListItemObject obj = mData.get(position);
+
+        if(convertView == null) {
+            LayoutInflater inflater = ((Activity)mContext).getLayoutInflater();
+            convertView = inflater.inflate(mLayoutViewResourceId, parent, false);
+        }
+
+        convertView.setLayoutParams(new ListView.LayoutParams(ListView.LayoutParams
+                .MATCH_PARENT, obj.getHeight()));
+
+        ImageView imgView = (ImageView)convertView.findViewById(R.id.image_view);
+        TextView textView = (TextView)convertView.findViewById(R.id.text_view);
+
+        Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(),
+                obj.getImgResource(), null);
+
+        textView.setText(obj.getTitle());
+        imgView.setImageBitmap(CustomArrayAdapter.getCroppedBitmap(bitmap));
+
+        return convertView;
+    }
+
+    /**
+     * Returns a circular cropped version of the bitmap passed in.
+     */
+    public static Bitmap getCroppedBitmap(Bitmap bitmap) {
+        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(),
+                Config.ARGB_8888);
+
+        final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
+
+        Canvas canvas = new Canvas(output);
+
+        final Paint paint = new Paint();
+        paint.setAntiAlias(true);
+
+        int halfWidth = bitmap.getWidth() / 2;
+        int halfHeight = bitmap.getHeight() / 2;
+
+        canvas.drawCircle(halfWidth, halfHeight, Math.max(halfWidth, halfHeight), paint);
+
+        paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
+
+        canvas.drawBitmap(bitmap, rect, rect, paint);
+
+        return output;
+    }
+}
\ No newline at end of file
diff --git a/samples/devbytes/animation/ListViewCellInsertion/src/com/example/android/insertingcells/InsertingCells.java b/samples/devbytes/animation/ListViewCellInsertion/src/com/example/android/insertingcells/InsertingCells.java
new file mode 100644
index 0000000..a58dbfb
--- /dev/null
+++ b/samples/devbytes/animation/ListViewCellInsertion/src/com/example/android/insertingcells/InsertingCells.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2013 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.insertingcells;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+import android.widget.RelativeLayout;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This application creates a ListView to which new elements can be added from the
+ * top. When a new element is added, it is animated from above the bounds
+ * of the list to the top. When the list is scrolled all the way to the top and a new
+ * element is added, the row animation is accompanied by an image animation that pops
+ * out of the round view and pops into the correct position in the top cell.
+ */
+public class InsertingCells extends Activity implements OnRowAdditionAnimationListener {
+
+    private ListItemObject mValues[];
+
+    private InsertionListView mListView;
+
+    private Button mButton;
+
+    private Integer mItemNum = 0;
+
+    private RoundView mRoundView;
+
+    private int mCellHeight;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_main);
+
+        mValues = new ListItemObject[] {
+                new ListItemObject("Chameleon", R.drawable.chameleon, 0),
+                new ListItemObject("Rock", R.drawable.rock, 0),
+                new ListItemObject("Flower", R.drawable.flower, 0),
+        };
+
+        mCellHeight = (int)(getResources().getDimension(R.dimen.cell_height));
+
+        List<ListItemObject> mData = new ArrayList<ListItemObject>();
+        CustomArrayAdapter mAdapter = new CustomArrayAdapter(this, R.layout.list_view_item, mData);
+        RelativeLayout mLayout = (RelativeLayout)findViewById(R.id.relative_layout);
+
+        mRoundView = (RoundView)findViewById(R.id.round_view);
+        mButton = (Button)findViewById(R.id.add_row_button);
+        mListView = (InsertionListView)findViewById(R.id.listview);
+
+        mListView.setAdapter(mAdapter);
+        mListView.setData(mData);
+        mListView.setLayout(mLayout);
+        mListView.setRowAdditionAnimationListener(this);
+    }
+
+    public void addRow(View view) {
+        mButton.setEnabled(false);
+
+        mItemNum++;
+        ListItemObject obj = mValues[mItemNum % mValues.length];
+        final ListItemObject newObj = new ListItemObject(obj.getTitle(), obj.getImgResource(),
+                mCellHeight);
+
+        boolean shouldAnimateInNewImage = mListView.shouldAnimateInNewImage();
+        if (!shouldAnimateInNewImage) {
+            mListView.addRow(newObj);
+            return;
+        }
+
+        mListView.setEnabled(false);
+        ObjectAnimator animator = mRoundView.getScalingAnimator();
+        animator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationRepeat(Animator animation) {
+                mListView.addRow(newObj);
+            }
+        });
+        animator.start();
+    }
+
+    @Override
+    public void onRowAdditionAnimationStart() {
+        mButton.setEnabled(false);
+    }
+
+    @Override
+    public void onRowAdditionAnimationEnd() {
+        mButton.setEnabled(true);
+    }
+}
diff --git a/samples/devbytes/animation/ListViewCellInsertion/src/com/example/android/insertingcells/InsertionListView.java b/samples/devbytes/animation/ListViewCellInsertion/src/com/example/android/insertingcells/InsertionListView.java
new file mode 100644
index 0000000..66866ba
--- /dev/null
+++ b/samples/devbytes/animation/ListViewCellInsertion/src/com/example/android/insertingcells/InsertionListView.java
@@ -0,0 +1,376 @@
+/*
+ * Copyright (C) 2013 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.insertingcells;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.animation.TypeEvaluator;
+import android.animation.ValueAnimator;
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.view.View;
+import android.view.ViewTreeObserver;
+import android.view.animation.OvershootInterpolator;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * This ListView displays a set of ListItemObjects. By calling addRow with a new
+ * ListItemObject, it is added to the top of the ListView and the new row is animated
+ * in. If the ListView content is at the top (the scroll offset is 0), the animation of
+ * the new row is accompanied by an extra image animation that pops into place in its
+ * corresponding item in the ListView.
+ */
+public class InsertionListView extends ListView {
+
+    private static final int NEW_ROW_DURATION = 500;
+    private static final int OVERSHOOT_INTERPOLATOR_TENSION = 5;
+
+    private OvershootInterpolator sOvershootInterpolator;
+
+    private RelativeLayout mLayout;
+
+    private Context mContext;
+
+    private OnRowAdditionAnimationListener mRowAdditionAnimationListener;
+
+    private List<ListItemObject> mData;
+    private List<BitmapDrawable> mCellBitmapDrawables;
+
+    public InsertionListView(Context context) {
+        super(context);
+        init(context);
+    }
+
+    public InsertionListView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init(context);
+    }
+
+    public InsertionListView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        init(context);
+    }
+
+    public void init(Context context) {
+        setDivider(null);
+        mContext = context;
+        mCellBitmapDrawables = new ArrayList<BitmapDrawable>();
+        sOvershootInterpolator = new OvershootInterpolator(OVERSHOOT_INTERPOLATOR_TENSION);
+    }
+
+    /**
+     * Modifies the underlying data set and adapter through the addition of the new object
+     * to the first item of the ListView. The new cell is then animated into place from
+     * above the bounds of the ListView.
+     */
+    public void addRow(ListItemObject newObj) {
+
+        final CustomArrayAdapter adapter = (CustomArrayAdapter)getAdapter();
+
+        /**
+         * Stores the starting bounds and the corresponding bitmap drawables of every
+         * cell present in the ListView before the data set change takes place.
+         */
+        final HashMap<Long, Rect> listViewItemBounds = new HashMap<Long, Rect>();
+        final HashMap<Long, BitmapDrawable> listViewItemDrawables = new HashMap<Long,
+                BitmapDrawable>();
+
+        int firstVisiblePosition = getFirstVisiblePosition();
+        for (int i = 0; i < getChildCount(); ++i) {
+            View child = getChildAt(i);
+            int position = firstVisiblePosition + i;
+            long itemID = adapter.getItemId(position);
+            Rect startRect = new Rect(child.getLeft(), child.getTop(), child.getRight(),
+                    child.getBottom());
+            listViewItemBounds.put(itemID, startRect);
+            listViewItemDrawables.put(itemID, getBitmapDrawableFromView(child));
+        }
+
+        /** Adds the new object to the data set, thereby modifying the adapter,
+         *  as well as adding a stable Id for that specified object.*/
+        mData.add(0, newObj);
+        adapter.addStableIdForDataAtPosition(0);
+        adapter.notifyDataSetChanged();
+
+        final ViewTreeObserver observer = getViewTreeObserver();
+        observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+            public boolean onPreDraw() {
+                observer.removeOnPreDrawListener(this);
+
+                ArrayList<Animator> animations = new ArrayList<Animator>();
+
+                final View newCell = getChildAt(0);
+                final ImageView imgView = (ImageView)newCell.findViewById(R.id.image_view);
+                final ImageView copyImgView = new ImageView(mContext);
+
+                int firstVisiblePosition = getFirstVisiblePosition();
+                final boolean shouldAnimateInNewRow = shouldAnimateInNewRow();
+                final boolean shouldAnimateInImage = shouldAnimateInNewImage();
+
+                if (shouldAnimateInNewRow) {
+                    /** Fades in the text of the first cell. */
+                    TextView textView = (TextView)newCell.findViewById(R.id.text_view);
+                    ObjectAnimator textAlphaAnimator = ObjectAnimator.ofFloat(textView,
+                            View.ALPHA, 0.0f, 1.0f);
+                    animations.add(textAlphaAnimator);
+
+                    /** Animates in the extra hover view corresponding to the image
+                     * in the top row of the ListView. */
+                    if (shouldAnimateInImage) {
+
+                        int width = imgView.getWidth();
+                        int height = imgView.getHeight();
+
+                        Point childLoc = getLocationOnScreen(newCell);
+                        Point layoutLoc = getLocationOnScreen(mLayout);
+
+                        ListItemObject obj = mData.get(0);
+                        Bitmap bitmap = CustomArrayAdapter.getCroppedBitmap(BitmapFactory
+                                .decodeResource(mContext.getResources(), obj.getImgResource(),
+                                        null));
+                        copyImgView.setImageBitmap(bitmap);
+
+                        imgView.setVisibility(View.INVISIBLE);
+
+                        copyImgView.setScaleType(ImageView.ScaleType.CENTER);
+
+                        ObjectAnimator imgViewTranslation = ObjectAnimator.ofFloat(copyImgView,
+                                View.Y, childLoc.y - layoutLoc.y);
+
+                        PropertyValuesHolder imgViewScaleY = PropertyValuesHolder.ofFloat
+                                (View.SCALE_Y, 0, 1.0f);
+                        PropertyValuesHolder imgViewScaleX = PropertyValuesHolder.ofFloat
+                                (View.SCALE_X, 0, 1.0f);
+                        ObjectAnimator imgViewScaleAnimator = ObjectAnimator
+                                .ofPropertyValuesHolder(copyImgView, imgViewScaleX, imgViewScaleY);
+                        imgViewScaleAnimator.setInterpolator(sOvershootInterpolator);
+                        animations.add(imgViewTranslation);
+                        animations.add(imgViewScaleAnimator);
+
+                        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams
+                                (width, height);
+
+                        mLayout.addView(copyImgView, params);
+                    }
+                }
+
+                /** Loops through all the current visible cells in the ListView and animates
+                 * all of them into their post layout positions from their original positions.*/
+                for (int i = 0; i < getChildCount(); i++) {
+                    View child = getChildAt(i);
+                    int position = firstVisiblePosition + i;
+                    long itemId = adapter.getItemId(position);
+                    Rect startRect = listViewItemBounds.get(itemId);
+                    int top = child.getTop();
+                    if (startRect != null) {
+                        /** If the cell was visible before the data set change and
+                         * after the data set change, then animate the cell between
+                         * the two positions.*/
+                        int startTop = startRect.top;
+                        int delta = startTop - top;
+                        ObjectAnimator animation = ObjectAnimator.ofFloat(child,
+                                View.TRANSLATION_Y, delta, 0);
+                        animations.add(animation);
+                    } else {
+                        /** If the cell was not visible (or present) before the data set
+                         * change but is visible after the data set change, then use its
+                         * height to determine the delta by which it should be animated.*/
+                        int childHeight = child.getHeight() + getDividerHeight();
+                        int startTop = top + (i > 0 ? childHeight : -childHeight);
+                        int delta = startTop - top;
+                        ObjectAnimator animation = ObjectAnimator.ofFloat(child,
+                                View.TRANSLATION_Y, delta, 0);
+                        animations.add(animation);
+                    }
+                    listViewItemBounds.remove(itemId);
+                    listViewItemDrawables.remove(itemId);
+                }
+
+                /**
+                 * Loops through all the cells that were visible before the data set
+                 * changed but not after, and keeps track of their corresponding
+                 * drawables. The bounds of each drawable are then animated from the
+                 * original state to the new one (off the screen). By storing all
+                 * the drawables that meet this criteria, they can be redrawn on top
+                 * of the ListView via dispatchDraw as they are animating.
+                 */
+                for (Long itemId: listViewItemBounds.keySet()) {
+                    BitmapDrawable bitmapDrawable = listViewItemDrawables.get(itemId);
+                    Rect startBounds = listViewItemBounds.get(itemId);
+                    bitmapDrawable.setBounds(startBounds);
+
+                    int childHeight = startBounds.bottom - startBounds.top + getDividerHeight();
+                    Rect endBounds = new Rect(startBounds);
+                    endBounds.offset(0, childHeight);
+
+                    ObjectAnimator animation = ObjectAnimator.ofObject(bitmapDrawable,
+                            "bounds", sBoundsEvaluator, startBounds, endBounds);
+                    animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+                        private Rect mLastBound = null;
+                        private Rect mCurrentBound = new Rect();
+                        @Override
+                        public void onAnimationUpdate(ValueAnimator valueAnimator) {
+                            Rect bounds = (Rect)valueAnimator.getAnimatedValue();
+                            mCurrentBound.set(bounds);
+                            if (mLastBound != null) {
+                                mCurrentBound.union(mLastBound);
+                            }
+                            mLastBound = bounds;
+                            invalidate(mCurrentBound);
+                        }
+                    });
+
+                    listViewItemBounds.remove(itemId);
+                    listViewItemDrawables.remove(itemId);
+
+                    mCellBitmapDrawables.add(bitmapDrawable);
+
+                    animations.add(animation);
+                }
+
+                /** Animates all the cells from their old position to their new position
+                 *  at the same time.*/
+                setEnabled(false);
+                mRowAdditionAnimationListener.onRowAdditionAnimationStart();
+                AnimatorSet set = new AnimatorSet();
+                set.setDuration(NEW_ROW_DURATION);
+                set.playTogether(animations);
+                set.addListener(new AnimatorListenerAdapter() {
+                    @Override
+                    public void onAnimationEnd(Animator animation) {
+                        mCellBitmapDrawables.clear();
+                        imgView.setVisibility(View.VISIBLE);
+                        mLayout.removeView(copyImgView);
+                        mRowAdditionAnimationListener.onRowAdditionAnimationEnd();
+                        setEnabled(true);
+                        invalidate();
+                    }
+                });
+                set.start();
+
+                listViewItemBounds.clear();
+                listViewItemDrawables.clear();
+                return true;
+            }
+        });
+    }
+
+    /**
+     * By overriding dispatchDraw, the BitmapDrawables of all the cells that were on the
+     * screen before (but not after) the layout are drawn and animated off the screen.
+     */
+    @Override
+    protected void dispatchDraw (Canvas canvas) {
+        super.dispatchDraw(canvas);
+        if (mCellBitmapDrawables.size() > 0) {
+            for (BitmapDrawable bitmapDrawable: mCellBitmapDrawables) {
+                bitmapDrawable.draw(canvas);
+            }
+        }
+    }
+
+    public boolean shouldAnimateInNewRow() {
+        int firstVisiblePosition = getFirstVisiblePosition();
+        return (firstVisiblePosition == 0);
+    }
+
+    public boolean shouldAnimateInNewImage() {
+        if (getChildCount() == 0) {
+            return true;
+        }
+        boolean shouldAnimateInNewRow = shouldAnimateInNewRow();
+        View topCell = getChildAt(0);
+        return (shouldAnimateInNewRow && topCell.getTop() == 0);
+    }
+
+    /** Returns a bitmap drawable showing a screenshot of the view passed in. */
+    private BitmapDrawable getBitmapDrawableFromView(View v) {
+        Bitmap bitmap = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888);
+        Canvas canvas = new Canvas (bitmap);
+        v.draw(canvas);
+        return new BitmapDrawable(getResources(), bitmap);
+    }
+
+    /**
+     * Returns the absolute x,y coordinates of the view relative to the top left
+     * corner of the phone screen.
+     */
+    public Point getLocationOnScreen(View v) {
+        DisplayMetrics dm = new DisplayMetrics();
+        ((Activity)getContext()).getWindowManager().getDefaultDisplay().getMetrics(dm);
+
+        int[] location = new int[2];
+        v.getLocationOnScreen(location);
+
+        return new Point(location[0], location[1]);
+    }
+
+    /** Setter for the underlying data set controlling the adapter. */
+    public void setData(List<ListItemObject> data) {
+        mData = data;
+    }
+
+    /**
+     * Setter for the parent RelativeLayout of this ListView. A reference to this
+     * ViewGroup is required in order to add the custom animated overlaying bitmap
+     * when adding a new row.
+     */
+    public void setLayout(RelativeLayout layout) {
+        mLayout = layout;
+    }
+
+    public void setRowAdditionAnimationListener(OnRowAdditionAnimationListener
+                                                        rowAdditionAnimationListener) {
+        mRowAdditionAnimationListener = rowAdditionAnimationListener;
+    }
+
+    /**
+     * This TypeEvaluator is used to animate the position of a BitmapDrawable
+     * by updating its bounds.
+     */
+    static final TypeEvaluator<Rect> sBoundsEvaluator = new TypeEvaluator<Rect>() {
+        public Rect evaluate(float fraction, Rect startValue, Rect endValue) {
+            return new Rect(interpolate(startValue.left, endValue.left, fraction),
+                    interpolate(startValue.top, endValue.top, fraction),
+                    interpolate(startValue.right, endValue.right, fraction),
+                    interpolate(startValue.bottom, endValue.bottom, fraction));
+        }
+
+        public int interpolate(int start, int end, float fraction) {
+            return (int)(start + fraction * (end - start));
+        }
+    };
+
+}
diff --git a/samples/devbytes/animation/ListViewCellInsertion/src/com/example/android/insertingcells/ListItemObject.java b/samples/devbytes/animation/ListViewCellInsertion/src/com/example/android/insertingcells/ListItemObject.java
new file mode 100644
index 0000000..8ca56f5
--- /dev/null
+++ b/samples/devbytes/animation/ListViewCellInsertion/src/com/example/android/insertingcells/ListItemObject.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2013 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.insertingcells;
+
+/**
+ * The data model for every cell in the ListView for this application. This model stores
+ * a title, an image resource and a default cell height for every item in the ListView.
+ */
+public class ListItemObject {
+
+    private String mTitle;
+    private int mImgResource;
+    private int mHeight;
+
+    public ListItemObject(String title, int imgResource, int height) {
+        super();
+        mTitle = title;
+        mImgResource = imgResource;
+        mHeight = height;
+    }
+
+    public String getTitle() {
+        return mTitle;
+    }
+
+    public int getImgResource() {
+        return mImgResource;
+    }
+
+    public int getHeight() {
+        return mHeight;
+    }
+
+}
diff --git a/samples/devbytes/animation/ListViewCellInsertion/src/com/example/android/insertingcells/OnRowAdditionAnimationListener.java b/samples/devbytes/animation/ListViewCellInsertion/src/com/example/android/insertingcells/OnRowAdditionAnimationListener.java
new file mode 100644
index 0000000..f371f3e
--- /dev/null
+++ b/samples/devbytes/animation/ListViewCellInsertion/src/com/example/android/insertingcells/OnRowAdditionAnimationListener.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2013 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.insertingcells;
+
+/**
+ * This listener is used to determine when the animation of a new row addition
+ * begins and ends. The primary use of this interface is to create a callback
+ * under which certain elements, such as the listview itself, can be disabled
+ * to prevent unpredictable behaviour during the actual cell animation.
+ */
+public interface OnRowAdditionAnimationListener {
+    public void onRowAdditionAnimationStart();
+    public void onRowAdditionAnimationEnd();
+}
diff --git a/samples/devbytes/animation/ListViewCellInsertion/src/com/example/android/insertingcells/RoundView.java b/samples/devbytes/animation/ListViewCellInsertion/src/com/example/android/insertingcells/RoundView.java
new file mode 100644
index 0000000..320c8b9
--- /dev/null
+++ b/samples/devbytes/animation/ListViewCellInsertion/src/com/example/android/insertingcells/RoundView.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2013 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.insertingcells;
+
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.view.View;
+
+/**
+ * This round view draws a circle from which the image pops out of and into
+ * the corresponding cell in the list.
+ */
+public class RoundView extends View {
+
+    private final int STROKE_WIDTH = 6;
+    private final int RADIUS = 20;
+    private final int ANIMATION_DURATION = 300;
+    private final float SCALE_FACTOR = 0.3f;
+
+    private Paint mPaint;
+
+    public RoundView(Context context) {
+        super(context);
+        init();
+    }
+
+    public RoundView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init();
+    }
+
+    public RoundView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        init();
+    }
+
+    private void init() {
+        mPaint = new Paint();
+        mPaint.setAntiAlias(true);
+        mPaint.setColor(Color.WHITE);
+        mPaint.setStyle(Paint.Style.STROKE);
+        mPaint.setStrokeWidth(STROKE_WIDTH);
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        canvas.drawCircle(canvas.getWidth() / 2, canvas.getHeight() / 2,
+                RADIUS, mPaint);
+    }
+
+    public ObjectAnimator getScalingAnimator() {
+        PropertyValuesHolder imgViewScaleY = PropertyValuesHolder.ofFloat(View
+                .SCALE_Y, SCALE_FACTOR);
+        PropertyValuesHolder imgViewScaleX = PropertyValuesHolder.ofFloat(View
+                .SCALE_X, SCALE_FACTOR);
+
+        ObjectAnimator imgViewScaleAnimator = ObjectAnimator
+                .ofPropertyValuesHolder(this, imgViewScaleX, imgViewScaleY);
+        imgViewScaleAnimator.setRepeatCount(1);
+        imgViewScaleAnimator.setRepeatMode(ValueAnimator.REVERSE);
+        imgViewScaleAnimator.setDuration(ANIMATION_DURATION);
+
+        return imgViewScaleAnimator;
+    }
+}
diff --git a/samples/devbytes/animation/ListViewDraggingAnimation/AndroidManifest.xml b/samples/devbytes/animation/ListViewDraggingAnimation/AndroidManifest.xml
new file mode 100644
index 0000000..5702dca
--- /dev/null
+++ b/samples/devbytes/animation/ListViewDraggingAnimation/AndroidManifest.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.example.android.listviewdragginganimation"
+          android:versionCode="1"
+          android:versionName="1.0">
+    <uses-sdk android:minSdkVersion="11"
+              android:targetSdkVersion="17"/>
+    <application android:label="@string/app_name" android:icon="@drawable/ic_launcher">
+        <activity android:name=".ListViewDraggingAnimation"
+                  android:label="@string/app_name">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/samples/devbytes/animation/ListViewDraggingAnimation/res/drawable-hdpi/ic_launcher.png b/samples/devbytes/animation/ListViewDraggingAnimation/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..96a442e
--- /dev/null
+++ b/samples/devbytes/animation/ListViewDraggingAnimation/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/ListViewDraggingAnimation/res/drawable-ldpi/ic_launcher.png b/samples/devbytes/animation/ListViewDraggingAnimation/res/drawable-ldpi/ic_launcher.png
new file mode 100644
index 0000000..9923872
--- /dev/null
+++ b/samples/devbytes/animation/ListViewDraggingAnimation/res/drawable-ldpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/ListViewDraggingAnimation/res/drawable-mdpi/ic_launcher.png b/samples/devbytes/animation/ListViewDraggingAnimation/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..359047d
--- /dev/null
+++ b/samples/devbytes/animation/ListViewDraggingAnimation/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/ListViewDraggingAnimation/res/drawable-xhdpi/ic_launcher.png b/samples/devbytes/animation/ListViewDraggingAnimation/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..71c6d76
--- /dev/null
+++ b/samples/devbytes/animation/ListViewDraggingAnimation/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/ListViewDraggingAnimation/res/layout/activity_list_view.xml b/samples/devbytes/animation/ListViewDraggingAnimation/res/layout/activity_list_view.xml
new file mode 100644
index 0000000..68198bc
--- /dev/null
+++ b/samples/devbytes/animation/ListViewDraggingAnimation/res/layout/activity_list_view.xml
@@ -0,0 +1,29 @@
+<!-- Copyright (C) 2013 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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/mainLayout"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context=".ListViewAnimations" >
+
+        <com.example.android.listviewdragginganimation.DynamicListView
+            android:id="@+id/listview"
+            android:background="#0000"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content" />
+
+</RelativeLayout>
diff --git a/samples/devbytes/animation/ListViewDraggingAnimation/res/layout/text_view.xml b/samples/devbytes/animation/ListViewDraggingAnimation/res/layout/text_view.xml
new file mode 100644
index 0000000..d7aeb7a
--- /dev/null
+++ b/samples/devbytes/animation/ListViewDraggingAnimation/res/layout/text_view.xml
@@ -0,0 +1,26 @@
+<!-- Copyright (C) 2013 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.
+-->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:background="#FFF"
+    android:textSize="@dimen/list_text_size"
+    android:gravity="center_vertical"
+    android:paddingLeft="15dp"
+    android:paddingRight="15dp"
+    android:minHeight="@dimen/list_item_height"
+    android:textColor="#000000"
+/>
diff --git a/samples/devbytes/animation/ListViewDraggingAnimation/res/values/dimens.xml b/samples/devbytes/animation/ListViewDraggingAnimation/res/values/dimens.xml
new file mode 100644
index 0000000..d647948
--- /dev/null
+++ b/samples/devbytes/animation/ListViewDraggingAnimation/res/values/dimens.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <dimen name="list_text_size">16sp</dimen>
+    <dimen name="list_item_height">48dip</dimen>
+
+</resources>
\ No newline at end of file
diff --git a/samples/devbytes/animation/ListViewDraggingAnimation/res/values/strings.xml b/samples/devbytes/animation/ListViewDraggingAnimation/res/values/strings.xml
new file mode 100644
index 0000000..bbe6f91
--- /dev/null
+++ b/samples/devbytes/animation/ListViewDraggingAnimation/res/values/strings.xml
@@ -0,0 +1,19 @@
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <string name="app_name">ListViewDraggingAnimation</string>
+
+</resources>
diff --git a/samples/devbytes/animation/ListViewDraggingAnimation/src/com/example/android/listviewdragginganimation/Cheeses.java b/samples/devbytes/animation/ListViewDraggingAnimation/src/com/example/android/listviewdragginganimation/Cheeses.java
new file mode 100644
index 0000000..f5422cf
--- /dev/null
+++ b/samples/devbytes/animation/ListViewDraggingAnimation/src/com/example/android/listviewdragginganimation/Cheeses.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2013 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.listviewdragginganimation;
+
+public class Cheeses {
+
+    public static final String[] sCheeseStrings = {
+            "Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi",
+            "Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu", "Airag", "Airedale",
+            "Aisy Cendre", "Allgauer Emmentaler", "Alverca", "Ambert", "American Cheese",
+            "Ami du Chambertin", "Anejo Enchilado", "Anneau du Vic-Bilh", "Anthoriro", "Appenzell",
+            "Aragon", "Ardi Gasna", "Ardrahan", "Armenian String", "Aromes au Gene de Marc",
+            "Asadero", "Asiago", "Aubisque Pyrenees", "Autun", "Avaxtskyr", "Baby Swiss",
+            "Babybel", "Baguette Laonnaise", "Bakers", "Baladi", "Balaton", "Bandal", "Banon",
+            "Barry's Bay Cheddar", "Basing", "Basket Cheese", "Bath Cheese", "Bavarian Bergkase",
+            "Baylough", "Beaufort", "Beauvoorde", "Beenleigh Blue", "Beer Cheese", "Bel Paese",
+            "Bergader", "Bergere Bleue", "Berkswell", "Beyaz Peynir", "Bierkase", "Bishop Kennedy",
+            "Blarney", "Bleu d'Auvergne", "Bleu de Gex", "Bleu de Laqueuille",
+            "Bleu de Septmoncel", "Bleu Des Causses", "Blue", "Blue Castello", "Blue Rathgore",
+            "Blue Vein (Australian)", "Blue Vein Cheeses", "Bocconcini", "Bocconcini (Australian)",
+            "Boeren Leidenkaas", "Bonchester", "Bosworth", "Bougon", "Boule Du Roves",
+            "Boulette d'Avesnes", "Boursault", "Boursin", "Bouyssou", "Bra", "Braudostur",
+            "Breakfast Cheese", "Brebis du Lavort", "Brebis du Lochois", "Brebis du Puyfaucon",
+            "Bresse Bleu", "Brick", "Brie", "Brie de Meaux", "Brie de Melun", "Brillat-Savarin",
+            "Brin", "Brin d' Amour", "Brin d'Amour", "Brinza (Burduf Brinza)",
+            "Briquette de Brebis", "Briquette du Forez", "Broccio", "Broccio Demi-Affine",
+            "Brousse du Rove", "Bruder Basil", "Brusselae Kaas (Fromage de Bruxelles)", "Bryndza",
+            "Buchette d'Anjou", "Buffalo", "Burgos", "Butte", "Butterkase", "Button (Innes)",
+            "Buxton Blue", "Cabecou", "Caboc", "Cabrales", "Cachaille", "Caciocavallo", "Caciotta",
+            "Caerphilly", "Cairnsmore", "Calenzana", "Cambazola", "Camembert de Normandie",
+            "Canadian Cheddar", "Canestrato", "Cantal", "Caprice des Dieux", "Capricorn Goat",
+            "Capriole Banon", "Carre de l'Est", "Casciotta di Urbino", "Cashel Blue", "Castellano",
+            "Castelleno", "Castelmagno", "Castelo Branco", "Castigliano", "Cathelain",
+            "Celtic Promise", "Cendre d'Olivet", "Cerney", "Chabichou", "Chabichou du Poitou",
+            "Chabis de Gatine", "Chaource", "Charolais", "Chaumes", "Cheddar",
+            "Cheddar Clothbound", "Cheshire", "Chevres", "Chevrotin des Aravis", "Chontaleno",
+            "Civray", "Coeur de Camembert au Calvados", "Coeur de Chevre", "Colby", "Cold Pack",
+            "Comte", "Coolea", "Cooleney", "Coquetdale", "Corleggy", "Cornish Pepper",
+            "Cotherstone", "Cotija", "Cottage Cheese", "Cottage Cheese (Australian)",
+            "Cougar Gold", "Coulommiers", "Coverdale", "Crayeux de Roncq", "Cream Cheese",
+            "Cream Havarti", "Crema Agria", "Crema Mexicana", "Creme Fraiche", "Crescenza",
+            "Croghan", "Crottin de Chavignol", "Crottin du Chavignol", "Crowdie", "Crowley",
+            "Cuajada", "Curd", "Cure Nantais", "Curworthy", "Cwmtawe Pecorino",
+            "Cypress Grove Chevre", "Danablu (Danish Blue)", "Danbo", "Danish Fontina",
+            "Daralagjazsky", "Dauphin", "Delice des Fiouves", "Denhany Dorset Drum", "Derby",
+            "Dessertnyj Belyj", "Devon Blue", "Devon Garland", "Dolcelatte", "Doolin",
+            "Doppelrhamstufel", "Dorset Blue Vinney", "Double Gloucester", "Double Worcester",
+            "Dreux a la Feuille", "Dry Jack", "Duddleswell", "Dunbarra", "Dunlop", "Dunsyre Blue",
+            "Duroblando", "Durrus", "Dutch Mimolette (Commissiekaas)", "Edam", "Edelpilz",
+            "Emental Grand Cru", "Emlett", "Emmental", "Epoisses de Bourgogne", "Esbareich",
+            "Esrom", "Etorki", "Evansdale Farmhouse Brie", "Evora De L'Alentejo", "Exmoor Blue",
+            "Explorateur", "Feta", "Feta (Australian)", "Figue", "Filetta", "Fin-de-Siecle",
+            "Finlandia Swiss", "Finn", "Fiore Sardo", "Fleur du Maquis", "Flor de Guia",
+            "Flower Marie", "Folded", "Folded cheese with mint", "Fondant de Brebis",
+            "Fontainebleau", "Fontal", "Fontina Val d'Aosta", "Formaggio di capra", "Fougerus",
+            "Four Herb Gouda", "Fourme d' Ambert", "Fourme de Haute Loire", "Fourme de Montbrison",
+            "Fresh Jack", "Fresh Mozzarella", "Fresh Ricotta", "Fresh Truffles", "Fribourgeois",
+            "Friesekaas", "Friesian", "Friesla", "Frinault", "Fromage a Raclette", "Fromage Corse",
+            "Fromage de Montagne de Savoie", "Fromage Frais", "Fruit Cream Cheese",
+            "Frying Cheese", "Fynbo", "Gabriel", "Galette du Paludier", "Galette Lyonnaise",
+            "Galloway Goat's Milk Gems", "Gammelost", "Gaperon a l'Ail", "Garrotxa", "Gastanberra",
+            "Geitost", "Gippsland Blue", "Gjetost", "Gloucester", "Golden Cross", "Gorgonzola",
+            "Gornyaltajski", "Gospel Green", "Gouda", "Goutu", "Gowrie", "Grabetto", "Graddost",
+            "Grafton Village Cheddar", "Grana", "Grana Padano", "Grand Vatel",
+            "Grataron d' Areches", "Gratte-Paille", "Graviera", "Greuilh", "Greve",
+            "Gris de Lille", "Gruyere", "Gubbeen", "Guerbigny", "Halloumi",
+            "Halloumy (Australian)", "Haloumi-Style Cheese", "Harbourne Blue", "Havarti",
+            "Heidi Gruyere", "Hereford Hop", "Herrgardsost", "Herriot Farmhouse", "Herve",
+            "Hipi Iti", "Hubbardston Blue Cow", "Hushallsost", "Iberico", "Idaho Goatster",
+            "Idiazabal", "Il Boschetto al Tartufo", "Ile d'Yeu", "Isle of Mull", "Jarlsberg",
+            "Jermi Tortes", "Jibneh Arabieh", "Jindi Brie", "Jubilee Blue", "Juustoleipa",
+            "Kadchgall", "Kaseri", "Kashta", "Kefalotyri", "Kenafa", "Kernhem", "Kervella Affine",
+            "Kikorangi", "King Island Cape Wickham Brie", "King River Gold", "Klosterkaese",
+            "Knockalara", "Kugelkase", "L'Aveyronnais", "L'Ecir de l'Aubrac", "La Taupiniere",
+            "La Vache Qui Rit", "Laguiole", "Lairobell", "Lajta", "Lanark Blue", "Lancashire",
+            "Langres", "Lappi", "Laruns", "Lavistown", "Le Brin", "Le Fium Orbo", "Le Lacandou",
+            "Le Roule", "Leafield", "Lebbene", "Leerdammer", "Leicester", "Leyden", "Limburger",
+            "Lincolnshire Poacher", "Lingot Saint Bousquet d'Orb", "Liptauer", "Little Rydings",
+            "Livarot", "Llanboidy", "Llanglofan Farmhouse", "Loch Arthur Farmhouse",
+            "Loddiswell Avondale", "Longhorn", "Lou Palou", "Lou Pevre", "Lyonnais", "Maasdam",
+            "Macconais", "Mahoe Aged Gouda", "Mahon", "Malvern", "Mamirolle", "Manchego",
+            "Manouri", "Manur", "Marble Cheddar", "Marbled Cheeses", "Maredsous", "Margotin",
+            "Maribo", "Maroilles", "Mascares", "Mascarpone", "Mascarpone (Australian)",
+            "Mascarpone Torta", "Matocq", "Maytag Blue", "Meira", "Menallack Farmhouse",
+            "Menonita", "Meredith Blue", "Mesost", "Metton (Cancoillotte)", "Meyer Vintage Gouda",
+            "Mihalic Peynir", "Milleens", "Mimolette", "Mine-Gabhar", "Mini Baby Bells", "Mixte",
+            "Molbo", "Monastery Cheeses", "Mondseer", "Mont D'or Lyonnais", "Montasio",
+            "Monterey Jack", "Monterey Jack Dry", "Morbier", "Morbier Cru de Montagne",
+            "Mothais a la Feuille", "Mozzarella", "Mozzarella (Australian)",
+            "Mozzarella di Bufala", "Mozzarella Fresh, in water", "Mozzarella Rolls", "Munster",
+            "Murol", "Mycella", "Myzithra", "Naboulsi", "Nantais", "Neufchatel",
+            "Neufchatel (Australian)", "Niolo", "Nokkelost", "Northumberland", "Oaxaca",
+            "Olde York", "Olivet au Foin", "Olivet Bleu", "Olivet Cendre",
+            "Orkney Extra Mature Cheddar", "Orla", "Oschtjepka", "Ossau Fermier", "Ossau-Iraty",
+            "Oszczypek", "Oxford Blue", "P'tit Berrichon", "Palet de Babligny", "Paneer", "Panela",
+            "Pannerone", "Pant ys Gawn", "Parmesan (Parmigiano)", "Parmigiano Reggiano",
+            "Pas de l'Escalette", "Passendale", "Pasteurized Processed", "Pate de Fromage",
+            "Patefine Fort", "Pave d'Affinois", "Pave d'Auge", "Pave de Chirac", "Pave du Berry",
+            "Pecorino", "Pecorino in Walnut Leaves", "Pecorino Romano", "Peekskill Pyramid",
+            "Pelardon des Cevennes", "Pelardon des Corbieres", "Penamellera", "Penbryn",
+            "Pencarreg", "Perail de Brebis", "Petit Morin", "Petit Pardou", "Petit-Suisse",
+            "Picodon de Chevre", "Picos de Europa", "Piora", "Pithtviers au Foin",
+            "Plateau de Herve", "Plymouth Cheese", "Podhalanski", "Poivre d'Ane", "Polkolbin",
+            "Pont l'Eveque", "Port Nicholson", "Port-Salut", "Postel", "Pouligny-Saint-Pierre",
+            "Pourly", "Prastost", "Pressato", "Prince-Jean", "Processed Cheddar", "Provolone",
+            "Provolone (Australian)", "Pyengana Cheddar", "Pyramide", "Quark",
+            "Quark (Australian)", "Quartirolo Lombardo", "Quatre-Vents", "Quercy Petit",
+            "Queso Blanco", "Queso Blanco con Frutas --Pina y Mango", "Queso de Murcia",
+            "Queso del Montsec", "Queso del Tietar", "Queso Fresco", "Queso Fresco (Adobera)",
+            "Queso Iberico", "Queso Jalapeno", "Queso Majorero", "Queso Media Luna",
+            "Queso Para Frier", "Queso Quesadilla", "Rabacal", "Raclette", "Ragusano", "Raschera",
+            "Reblochon", "Red Leicester", "Regal de la Dombes", "Reggianito", "Remedou",
+            "Requeson", "Richelieu", "Ricotta", "Ricotta (Australian)", "Ricotta Salata", "Ridder",
+            "Rigotte", "Rocamadour", "Rollot", "Romano", "Romans Part Dieu", "Roncal", "Roquefort",
+            "Roule", "Rouleau De Beaulieu", "Royalp Tilsit", "Rubens", "Rustinu", "Saaland Pfarr",
+            "Saanenkaese", "Saga", "Sage Derby", "Sainte Maure", "Saint-Marcellin",
+            "Saint-Nectaire", "Saint-Paulin", "Salers", "Samso", "San Simon", "Sancerre",
+            "Sap Sago", "Sardo", "Sardo Egyptian", "Sbrinz", "Scamorza", "Schabzieger", "Schloss",
+            "Selles sur Cher", "Selva", "Serat", "Seriously Strong Cheddar", "Serra da Estrela",
+            "Sharpam", "Shelburne Cheddar", "Shropshire Blue", "Siraz", "Sirene", "Smoked Gouda",
+            "Somerset Brie", "Sonoma Jack", "Sottocenare al Tartufo", "Soumaintrain",
+            "Sourire Lozerien", "Spenwood", "Sraffordshire Organic", "St. Agur Blue Cheese",
+            "Stilton", "Stinking Bishop", "String", "Sussex Slipcote", "Sveciaost", "Swaledale",
+            "Sweet Style Swiss", "Swiss", "Syrian (Armenian String)", "Tala", "Taleggio", "Tamie",
+            "Tasmania Highland Chevre Log", "Taupiniere", "Teifi", "Telemea", "Testouri",
+            "Tete de Moine", "Tetilla", "Texas Goat Cheese", "Tibet", "Tillamook Cheddar",
+            "Tilsit", "Timboon Brie", "Toma", "Tomme Brulee", "Tomme d'Abondance",
+            "Tomme de Chevre", "Tomme de Romans", "Tomme de Savoie", "Tomme des Chouans", "Tommes",
+            "Torta del Casar", "Toscanello", "Touree de L'Aubier", "Tourmalet",
+            "Trappe (Veritable)", "Trois Cornes De Vendee", "Tronchon", "Trou du Cru", "Truffe",
+            "Tupi", "Turunmaa", "Tymsboro", "Tyn Grug", "Tyning", "Ubriaco", "Ulloa",
+            "Vacherin-Fribourgeois", "Valencay", "Vasterbottenost", "Venaco", "Vendomois",
+            "Vieux Corse", "Vignotte", "Vulscombe", "Waimata Farmhouse Blue",
+            "Washed Rind Cheese (Australian)", "Waterloo", "Weichkaese", "Wellington",
+            "Wensleydale", "White Stilton", "Whitestone Farmhouse", "Wigmore", "Woodside Cabecou",
+            "Xanadu", "Xynotyro", "Yarg Cornish", "Yarra Valley Pyramid", "Yorkshire Blue",
+            "Zamorano", "Zanetti Grana Padano", "Zanetti Parmigiano Reggiano"
+    };
+
+}
diff --git a/samples/devbytes/animation/ListViewDraggingAnimation/src/com/example/android/listviewdragginganimation/DynamicListView.java b/samples/devbytes/animation/ListViewDraggingAnimation/src/com/example/android/listviewdragginganimation/DynamicListView.java
new file mode 100644
index 0000000..580fe64
--- /dev/null
+++ b/samples/devbytes/animation/ListViewDraggingAnimation/src/com/example/android/listviewdragginganimation/DynamicListView.java
@@ -0,0 +1,592 @@
+/*
+ * Copyright (C) 2013 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.listviewdragginganimation;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.animation.TypeEvaluator;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewTreeObserver;
+import android.widget.AbsListView;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.ListView;
+
+import java.util.ArrayList;
+
+/**
+ * The dynamic listview is an extension of listview that supports cell dragging
+ * and swapping.
+ *
+ * This layout is in charge of positioning the hover cell in the correct location
+ * on the screen in response to user touch events. It uses the position of the
+ * hover cell to determine when two cells should be swapped. If two cells should
+ * be swapped, all the corresponding data set and layout changes are handled here.
+ *
+ * If no cell is selected, all the touch events are passed down to the listview
+ * and behave normally. If one of the items in the listview experiences a
+ * long press event, the contents of its current visible state are captured as
+ * a bitmap and its visibility is set to INVISIBLE. A hover cell is then created and
+ * added to this layout as an overlaying BitmapDrawable above the listview. Once the
+ * hover cell is translated some distance to signify an item swap, a data set change
+ * accompanied by animation takes place. When the user releases the hover cell,
+ * it animates into its corresponding position in the listview.
+ *
+ * When the hover cell is either above or below the bounds of the listview, this
+ * listview also scrolls on its own so as to reveal additional content.
+ */
+public class DynamicListView extends ListView {
+
+    private final int SMOOTH_SCROLL_AMOUNT_AT_EDGE = 15;
+    private final int MOVE_DURATION = 150;
+    private final int LINE_THICKNESS = 15;
+
+    public ArrayList<String> mCheeseList;
+
+    private int mLastEventY = -1;
+
+    private int mDownY = -1;
+    private int mDownX = -1;
+
+    private int mTotalOffset = 0;
+
+    private boolean mCellIsMobile = false;
+    private boolean mIsMobileScrolling = false;
+    private int mSmoothScrollAmountAtEdge = 0;
+
+    private final int INVALID_ID = -1;
+    private long mAboveItemId = INVALID_ID;
+    private long mMobileItemId = INVALID_ID;
+    private long mBelowItemId = INVALID_ID;
+
+    private BitmapDrawable mHoverCell;
+    private Rect mHoverCellCurrentBounds;
+    private Rect mHoverCellOriginalBounds;
+
+    private final int INVALID_POINTER_ID = -1;
+    private int mActivePointerId = INVALID_POINTER_ID;
+
+    private boolean mIsWaitingForScrollFinish = false;
+    private int mScrollState = OnScrollListener.SCROLL_STATE_IDLE;
+
+    public DynamicListView(Context context) {
+        super(context);
+        init(context);
+    }
+
+    public DynamicListView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        init(context);
+    }
+
+    public DynamicListView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init(context);
+    }
+
+    public void init(Context context) {
+        setOnItemLongClickListener(mOnItemLongClickListener);
+        setOnScrollListener(mScrollListener);
+        DisplayMetrics metrics = context.getResources().getDisplayMetrics();
+        mSmoothScrollAmountAtEdge = (int)(SMOOTH_SCROLL_AMOUNT_AT_EDGE / metrics.density);
+    }
+
+    /**
+     * Listens for long clicks on any items in the listview. When a cell has
+     * been selected, the hover cell is created and set up.
+     */
+    private AdapterView.OnItemLongClickListener mOnItemLongClickListener =
+            new AdapterView.OnItemLongClickListener() {
+                public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int pos, long id) {
+                    mTotalOffset = 0;
+
+                    int position = pointToPosition(mDownX, mDownY);
+                    int itemNum = position - getFirstVisiblePosition();
+
+                    View selectedView = getChildAt(itemNum);
+                    mMobileItemId = getAdapter().getItemId(position);
+                    mHoverCell = getAndAddHoverView(selectedView);
+                    selectedView.setVisibility(INVISIBLE);
+
+                    mCellIsMobile = true;
+
+                    updateNeighborViewsForID(mMobileItemId);
+
+                    return true;
+                }
+            };
+
+    /**
+     * Creates the hover cell with the appropriate bitmap and of appropriate
+     * size. The hover cell's BitmapDrawable is drawn on top of the bitmap every
+     * single time an invalidate call is made.
+     */
+    private BitmapDrawable getAndAddHoverView(View v) {
+
+        int w = v.getWidth();
+        int h = v.getHeight();
+        int top = v.getTop();
+        int left = v.getLeft();
+
+        Bitmap b = getBitmapWithBorder(v);
+
+        BitmapDrawable drawable = new BitmapDrawable(getResources(), b);
+
+        mHoverCellOriginalBounds = new Rect(left, top, left + w, top + h);
+        mHoverCellCurrentBounds = new Rect(mHoverCellOriginalBounds);
+
+        drawable.setBounds(mHoverCellCurrentBounds);
+
+        return drawable;
+    }
+
+    /** Draws a black border over the screenshot of the view passed in. */
+    private Bitmap getBitmapWithBorder(View v) {
+        Bitmap bitmap = getBitmapFromView(v);
+        Canvas can = new Canvas(bitmap);
+
+        Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
+
+        Paint paint = new Paint();
+        paint.setStyle(Paint.Style.STROKE);
+        paint.setStrokeWidth(LINE_THICKNESS);
+        paint.setColor(Color.BLACK);
+
+        can.drawBitmap(bitmap, 0, 0, null);
+        can.drawRect(rect, paint);
+
+        return bitmap;
+    }
+
+    /** Returns a bitmap showing a screenshot of the view passed in. */
+    private Bitmap getBitmapFromView(View v) {
+        Bitmap bitmap = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888);
+        Canvas canvas = new Canvas (bitmap);
+        v.draw(canvas);
+        return bitmap;
+    }
+
+    /**
+     * Stores a reference to the views above and below the item currently
+     * corresponding to the hover cell. It is important to note that if this
+     * item is either at the top or bottom of the list, mAboveItemId or mBelowItemId
+     * may be invalid.
+     */
+    private void updateNeighborViewsForID(long itemID) {
+        int position = getPositionForID(itemID);
+        StableArrayAdapter adapter = ((StableArrayAdapter)getAdapter());
+        mAboveItemId = adapter.getItemId(position - 1);
+        mBelowItemId = adapter.getItemId(position + 1);
+    }
+
+    /** Retrieves the view in the list corresponding to itemID */
+    public View getViewForID (long itemID) {
+        int firstVisiblePosition = getFirstVisiblePosition();
+        StableArrayAdapter adapter = ((StableArrayAdapter)getAdapter());
+        for(int i = 0; i < getChildCount(); i++) {
+            View v = getChildAt(i);
+            int position = firstVisiblePosition + i;
+            long id = adapter.getItemId(position);
+            if (id == itemID) {
+                return v;
+            }
+        }
+        return null;
+    }
+
+    /** Retrieves the position in the list corresponding to itemID */
+    public int getPositionForID (long itemID) {
+        View v = getViewForID(itemID);
+        if (v == null) {
+            return -1;
+        } else {
+            return getPositionForView(v);
+        }
+    }
+
+    /**
+     *  dispatchDraw gets invoked when all the child views are about to be drawn.
+     *  By overriding this method, the hover cell (BitmapDrawable) can be drawn
+     *  over the listview's items whenever the listview is redrawn.
+     */
+    @Override
+    protected void dispatchDraw(Canvas canvas) {
+        super.dispatchDraw(canvas);
+        if (mHoverCell != null) {
+            mHoverCell.draw(canvas);
+        }
+    }
+
+    @Override
+    public boolean onTouchEvent (MotionEvent event) {
+
+        switch (event.getAction() & MotionEvent.ACTION_MASK) {
+            case MotionEvent.ACTION_DOWN:
+                mDownX = (int)event.getX();
+                mDownY = (int)event.getY();
+                mActivePointerId = event.getPointerId(0);
+                break;
+            case MotionEvent.ACTION_MOVE:
+                if (mActivePointerId == INVALID_POINTER_ID) {
+                    break;
+                }
+
+                int pointerIndex = event.findPointerIndex(mActivePointerId);
+
+                mLastEventY = (int) event.getY(pointerIndex);
+                int deltaY = mLastEventY - mDownY;
+
+                if (mCellIsMobile) {
+                    mHoverCellCurrentBounds.offsetTo(mHoverCellOriginalBounds.left,
+                            mHoverCellOriginalBounds.top + deltaY + mTotalOffset);
+                    mHoverCell.setBounds(mHoverCellCurrentBounds);
+                    invalidate();
+
+                    handleCellSwitch();
+
+                    mIsMobileScrolling = false;
+                    handleMobileCellScroll();
+
+                    return false;
+                }
+                break;
+            case MotionEvent.ACTION_UP:
+                touchEventsEnded();
+                break;
+            case MotionEvent.ACTION_CANCEL:
+                touchEventsCancelled();
+                break;
+            case MotionEvent.ACTION_POINTER_UP:
+                /* If a multitouch event took place and the original touch dictating
+                 * the movement of the hover cell has ended, then the dragging event
+                 * ends and the hover cell is animated to its corresponding position
+                 * in the listview. */
+                pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >>
+                        MotionEvent.ACTION_POINTER_INDEX_SHIFT;
+                final int pointerId = event.getPointerId(pointerIndex);
+                if (pointerId == mActivePointerId) {
+                    touchEventsEnded();
+                }
+                break;
+            default:
+                break;
+        }
+
+        return super.onTouchEvent(event);
+    }
+
+    /**
+     * This method determines whether the hover cell has been shifted far enough
+     * to invoke a cell swap. If so, then the respective cell swap candidate is
+     * determined and the data set is changed. Upon posting a notification of the
+     * data set change, a layout is invoked to place the cells in the right place.
+     * Using a ViewTreeObserver and a corresponding OnPreDrawListener, we can
+     * offset the cell being swapped to where it previously was and then animate it to
+     * its new position.
+     */
+    private void handleCellSwitch() {
+        final int deltaY = mLastEventY - mDownY;
+        int deltaYTotal = mHoverCellOriginalBounds.top + mTotalOffset + deltaY;
+
+        View belowView = getViewForID(mBelowItemId);
+        View mobileView = getViewForID(mMobileItemId);
+        View aboveView = getViewForID(mAboveItemId);
+
+        boolean isBelow = (belowView != null) && (deltaYTotal > belowView.getTop());
+        boolean isAbove = (aboveView != null) && (deltaYTotal < aboveView.getTop());
+
+        if (isBelow || isAbove) {
+
+            final long switchItemID = isBelow ? mBelowItemId : mAboveItemId;
+            View switchView = isBelow ? belowView : aboveView;
+            final int originalItem = getPositionForView(mobileView);
+
+            if (switchView == null) {
+                updateNeighborViewsForID(mMobileItemId);
+                return;
+            }
+
+            swapElements(mCheeseList, originalItem, getPositionForView(switchView));
+
+            ((BaseAdapter) getAdapter()).notifyDataSetChanged();
+
+            mDownY = mLastEventY;
+
+            final int switchViewStartTop = switchView.getTop();
+
+            mobileView.setVisibility(View.VISIBLE);
+            switchView.setVisibility(View.INVISIBLE);
+
+            updateNeighborViewsForID(mMobileItemId);
+
+            final ViewTreeObserver observer = getViewTreeObserver();
+            observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+                public boolean onPreDraw() {
+                    observer.removeOnPreDrawListener(this);
+
+                    View switchView = getViewForID(switchItemID);
+
+                    mTotalOffset += deltaY;
+
+                    int switchViewNewTop = switchView.getTop();
+                    int delta = switchViewStartTop - switchViewNewTop;
+
+                    switchView.setTranslationY(delta);
+
+                    ObjectAnimator animator = ObjectAnimator.ofFloat(switchView,
+                            View.TRANSLATION_Y, 0);
+                    animator.setDuration(MOVE_DURATION);
+                    animator.start();
+
+                    return true;
+                }
+            });
+        }
+    }
+
+    private void swapElements(ArrayList arrayList, int indexOne, int indexTwo) {
+        Object temp = arrayList.get(indexOne);
+        arrayList.set(indexOne, arrayList.get(indexTwo));
+        arrayList.set(indexTwo, temp);
+    }
+
+
+    /**
+     * Resets all the appropriate fields to a default state while also animating
+     * the hover cell back to its correct location.
+     */
+    private void touchEventsEnded () {
+        final View mobileView = getViewForID(mMobileItemId);
+        if (mCellIsMobile|| mIsWaitingForScrollFinish) {
+            mCellIsMobile = false;
+            mIsWaitingForScrollFinish = false;
+            mIsMobileScrolling = false;
+            mActivePointerId = INVALID_POINTER_ID;
+
+            // If the autoscroller has not completed scrolling, we need to wait for it to
+            // finish in order to determine the final location of where the hover cell
+            // should be animated to.
+            if (mScrollState != OnScrollListener.SCROLL_STATE_IDLE) {
+                mIsWaitingForScrollFinish = true;
+                return;
+            }
+
+            mHoverCellCurrentBounds.offsetTo(mHoverCellOriginalBounds.left, mobileView.getTop());
+
+            ObjectAnimator hoverViewAnimator = ObjectAnimator.ofObject(mHoverCell, "bounds",
+                    sBoundEvaluator, mHoverCellCurrentBounds);
+            hoverViewAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+                @Override
+                public void onAnimationUpdate(ValueAnimator valueAnimator) {
+                    invalidate();
+                }
+            });
+            hoverViewAnimator.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationStart(Animator animation) {
+                    setEnabled(false);
+                }
+
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    mAboveItemId = INVALID_ID;
+                    mMobileItemId = INVALID_ID;
+                    mBelowItemId = INVALID_ID;
+                    mobileView.setVisibility(VISIBLE);
+                    mHoverCell = null;
+                    setEnabled(true);
+                    invalidate();
+                }
+            });
+            hoverViewAnimator.start();
+        } else {
+            touchEventsCancelled();
+        }
+    }
+
+    /**
+     * Resets all the appropriate fields to a default state.
+     */
+    private void touchEventsCancelled () {
+        View mobileView = getViewForID(mMobileItemId);
+        if (mCellIsMobile) {
+            mAboveItemId = INVALID_ID;
+            mMobileItemId = INVALID_ID;
+            mBelowItemId = INVALID_ID;
+            mobileView.setVisibility(VISIBLE);
+            mHoverCell = null;
+            invalidate();
+        }
+        mCellIsMobile = false;
+        mIsMobileScrolling = false;
+        mActivePointerId = INVALID_POINTER_ID;
+    }
+
+    /**
+     * This TypeEvaluator is used to animate the BitmapDrawable back to its
+     * final location when the user lifts his finger by modifying the
+     * BitmapDrawable's bounds.
+     */
+    private final static TypeEvaluator<Rect> sBoundEvaluator = new TypeEvaluator<Rect>() {
+        public Rect evaluate(float fraction, Rect startValue, Rect endValue) {
+            return new Rect(interpolate(startValue.left, endValue.left, fraction),
+                    interpolate(startValue.top, endValue.top, fraction),
+                    interpolate(startValue.right, endValue.right, fraction),
+                    interpolate(startValue.bottom, endValue.bottom, fraction));
+        }
+
+        public int interpolate(int start, int end, float fraction) {
+            return (int)(start + fraction * (end - start));
+        }
+    };
+
+    /**
+     *  Determines whether this listview is in a scrolling state invoked
+     *  by the fact that the hover cell is out of the bounds of the listview;
+     */
+    private void handleMobileCellScroll() {
+        mIsMobileScrolling = handleMobileCellScroll(mHoverCellCurrentBounds);
+    }
+
+    /**
+     * This method is in charge of determining if the hover cell is above
+     * or below the bounds of the listview. If so, the listview does an appropriate
+     * upward or downward smooth scroll so as to reveal new items.
+     */
+    public boolean handleMobileCellScroll(Rect r) {
+        int offset = computeVerticalScrollOffset();
+        int height = getHeight();
+        int extent = computeVerticalScrollExtent();
+        int range = computeVerticalScrollRange();
+        int hoverViewTop = r.top;
+        int hoverHeight = r.height();
+
+        if (hoverViewTop <= 0 && offset > 0) {
+            smoothScrollBy(-mSmoothScrollAmountAtEdge, 0);
+            return true;
+        }
+
+        if (hoverViewTop + hoverHeight >= height && (offset + extent) < range) {
+            smoothScrollBy(mSmoothScrollAmountAtEdge, 0);
+            return true;
+        }
+
+        return false;
+    }
+
+    public void setCheeseList(ArrayList<String> cheeseList) {
+        mCheeseList = cheeseList;
+    }
+
+    /**
+     * This scroll listener is added to the listview in order to handle cell swapping
+     * when the cell is either at the top or bottom edge of the listview. If the hover
+     * cell is at either edge of the listview, the listview will begin scrolling. As
+     * scrolling takes place, the listview continuously checks if new cells became visible
+     * and determines whether they are potential candidates for a cell swap.
+     */
+    private AbsListView.OnScrollListener mScrollListener = new AbsListView.OnScrollListener () {
+
+        private int mPreviousFirstVisibleItem = -1;
+        private int mPreviousVisibleItemCount = -1;
+        private int mCurrentFirstVisibleItem;
+        private int mCurrentVisibleItemCount;
+        private int mCurrentScrollState;
+
+        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
+                             int totalItemCount) {
+            mCurrentFirstVisibleItem = firstVisibleItem;
+            mCurrentVisibleItemCount = visibleItemCount;
+
+            mPreviousFirstVisibleItem = (mPreviousFirstVisibleItem == -1) ? mCurrentFirstVisibleItem
+                    : mPreviousFirstVisibleItem;
+            mPreviousVisibleItemCount = (mPreviousVisibleItemCount == -1) ? mCurrentVisibleItemCount
+                    : mPreviousVisibleItemCount;
+
+            checkAndHandleFirstVisibleCellChange();
+            checkAndHandleLastVisibleCellChange();
+
+            mPreviousFirstVisibleItem = mCurrentFirstVisibleItem;
+            mPreviousVisibleItemCount = mCurrentVisibleItemCount;
+        }
+
+        @Override
+        public void onScrollStateChanged(AbsListView view, int scrollState) {
+            mCurrentScrollState = scrollState;
+            mScrollState = scrollState;
+            isScrollCompleted();
+        }
+
+        /**
+         * This method is in charge of invoking 1 of 2 actions. Firstly, if the listview
+         * is in a state of scrolling invoked by the hover cell being outside the bounds
+         * of the listview, then this scrolling event is continued. Secondly, if the hover
+         * cell has already been released, this invokes the animation for the hover cell
+         * to return to its correct position after the listview has entered an idle scroll
+         * state.
+         */
+        private void isScrollCompleted() {
+            if (mCurrentVisibleItemCount > 0 && mCurrentScrollState == SCROLL_STATE_IDLE) {
+                if (mCellIsMobile && mIsMobileScrolling) {
+                    handleMobileCellScroll();
+                } else if (mIsWaitingForScrollFinish) {
+                    touchEventsEnded();
+                }
+            }
+        }
+
+        /**
+         * Determines if the listview scrolled up enough to reveal a new cell at the
+         * top of the list. If so, then the appropriate parameters are updated.
+         */
+        public void checkAndHandleFirstVisibleCellChange() {
+            if (mCurrentFirstVisibleItem != mPreviousFirstVisibleItem) {
+                if (mCellIsMobile && mMobileItemId != INVALID_ID) {
+                    updateNeighborViewsForID(mMobileItemId);
+                    handleCellSwitch();
+                }
+            }
+        }
+
+        /**
+         * Determines if the listview scrolled down enough to reveal a new cell at the
+         * bottom of the list. If so, then the appropriate parameters are updated.
+         */
+        public void checkAndHandleLastVisibleCellChange() {
+            int currentLastVisibleItem = mCurrentFirstVisibleItem + mCurrentVisibleItemCount;
+            int previousLastVisibleItem = mPreviousFirstVisibleItem + mPreviousVisibleItemCount;
+            if (currentLastVisibleItem != previousLastVisibleItem) {
+                if (mCellIsMobile && mMobileItemId != INVALID_ID) {
+                    updateNeighborViewsForID(mMobileItemId);
+                    handleCellSwitch();
+                }
+            }
+        }
+    };
+}
\ No newline at end of file
diff --git a/samples/devbytes/animation/ListViewDraggingAnimation/src/com/example/android/listviewdragginganimation/ListViewDraggingAnimation.java b/samples/devbytes/animation/ListViewDraggingAnimation/src/com/example/android/listviewdragginganimation/ListViewDraggingAnimation.java
new file mode 100644
index 0000000..496e49d
--- /dev/null
+++ b/samples/devbytes/animation/ListViewDraggingAnimation/src/com/example/android/listviewdragginganimation/ListViewDraggingAnimation.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2013 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.listviewdragginganimation;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.ListView;
+
+import java.util.ArrayList;
+
+/**
+ * This application creates a listview where the ordering of the data set
+ * can be modified in response to user touch events.
+ *
+ * An item in the listview is selected via a long press event and is then
+ * moved around by tracking and following the movement of the user's finger.
+ * When the item is released, it animates to its new position within the listview.
+ */
+public class ListViewDraggingAnimation extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_list_view);
+
+        ArrayList<String>mCheeseList = new ArrayList<String>();
+        for (int i = 0; i < Cheeses.sCheeseStrings.length; ++i) {
+            mCheeseList.add(Cheeses.sCheeseStrings[i]);
+        }
+
+        StableArrayAdapter adapter = new StableArrayAdapter(this, R.layout.text_view, mCheeseList);
+        DynamicListView listView = (DynamicListView) findViewById(R.id.listview);
+
+        listView.setCheeseList(mCheeseList);
+        listView.setAdapter(adapter);
+        listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
+    }
+}
diff --git a/samples/devbytes/animation/ListViewDraggingAnimation/src/com/example/android/listviewdragginganimation/StableArrayAdapter.java b/samples/devbytes/animation/ListViewDraggingAnimation/src/com/example/android/listviewdragginganimation/StableArrayAdapter.java
new file mode 100644
index 0000000..9146cca
--- /dev/null
+++ b/samples/devbytes/animation/ListViewDraggingAnimation/src/com/example/android/listviewdragginganimation/StableArrayAdapter.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2013 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.listviewdragginganimation;
+
+import android.content.Context;
+import android.widget.ArrayAdapter;
+
+import java.util.HashMap;
+import java.util.List;
+
+public class StableArrayAdapter extends ArrayAdapter<String> {
+
+    final int INVALID_ID = -1;
+
+    HashMap<String, Integer> mIdMap = new HashMap<String, Integer>();
+
+    public StableArrayAdapter(Context context, int textViewResourceId, List<String> objects) {
+        super(context, textViewResourceId, objects);
+        for (int i = 0; i < objects.size(); ++i) {
+            mIdMap.put(objects.get(i), i);
+        }
+    }
+
+    @Override
+    public long getItemId(int position) {
+        if (position < 0 || position >= mIdMap.size()) {
+            return INVALID_ID;
+        }
+        String item = getItem(position);
+        return mIdMap.get(item);
+    }
+
+    @Override
+    public boolean hasStableIds() {
+        return true;
+    }
+}
diff --git a/samples/devbytes/animation/ListViewExpandingCells/AndroidManifest.xml b/samples/devbytes/animation/ListViewExpandingCells/AndroidManifest.xml
new file mode 100644
index 0000000..1633d01
--- /dev/null
+++ b/samples/devbytes/animation/ListViewExpandingCells/AndroidManifest.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.example.android.expandingcells"
+          android:versionCode="1"
+          android:versionName="1.0">
+    <uses-sdk android:minSdkVersion="16"
+              android:targetSdkVersion="17"/>
+    <application android:label="@string/app_name" android:icon="@drawable/ic_launcher">
+        <activity android:name=".ExpandingCells"
+                  android:label="@string/app_name">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/samples/devbytes/animation/ListViewExpandingCells/res/drawable-hdpi/border.9.png b/samples/devbytes/animation/ListViewExpandingCells/res/drawable-hdpi/border.9.png
new file mode 100644
index 0000000..f76e008
--- /dev/null
+++ b/samples/devbytes/animation/ListViewExpandingCells/res/drawable-hdpi/border.9.png
Binary files differ
diff --git a/samples/devbytes/animation/ListViewExpandingCells/res/drawable-hdpi/chameleon.jpg b/samples/devbytes/animation/ListViewExpandingCells/res/drawable-hdpi/chameleon.jpg
new file mode 100644
index 0000000..686cc88
--- /dev/null
+++ b/samples/devbytes/animation/ListViewExpandingCells/res/drawable-hdpi/chameleon.jpg
Binary files differ
diff --git a/samples/devbytes/animation/ListViewExpandingCells/res/drawable-hdpi/flower.jpg b/samples/devbytes/animation/ListViewExpandingCells/res/drawable-hdpi/flower.jpg
new file mode 100644
index 0000000..8842483
--- /dev/null
+++ b/samples/devbytes/animation/ListViewExpandingCells/res/drawable-hdpi/flower.jpg
Binary files differ
diff --git a/samples/devbytes/animation/ListViewExpandingCells/res/drawable-hdpi/ic_launcher.png b/samples/devbytes/animation/ListViewExpandingCells/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..96a442e
--- /dev/null
+++ b/samples/devbytes/animation/ListViewExpandingCells/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/ListViewExpandingCells/res/drawable-hdpi/rock.jpg b/samples/devbytes/animation/ListViewExpandingCells/res/drawable-hdpi/rock.jpg
new file mode 100644
index 0000000..8ea0e85
--- /dev/null
+++ b/samples/devbytes/animation/ListViewExpandingCells/res/drawable-hdpi/rock.jpg
Binary files differ
diff --git a/samples/devbytes/animation/ListViewExpandingCells/res/drawable-ldpi/ic_launcher.png b/samples/devbytes/animation/ListViewExpandingCells/res/drawable-ldpi/ic_launcher.png
new file mode 100644
index 0000000..9923872
--- /dev/null
+++ b/samples/devbytes/animation/ListViewExpandingCells/res/drawable-ldpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/ListViewExpandingCells/res/drawable-mdpi/ic_launcher.png b/samples/devbytes/animation/ListViewExpandingCells/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..359047d
--- /dev/null
+++ b/samples/devbytes/animation/ListViewExpandingCells/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/ListViewExpandingCells/res/drawable-xhdpi/ic_launcher.png b/samples/devbytes/animation/ListViewExpandingCells/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..71c6d76
--- /dev/null
+++ b/samples/devbytes/animation/ListViewExpandingCells/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/ListViewExpandingCells/res/layout/activity_main.xml b/samples/devbytes/animation/ListViewExpandingCells/res/layout/activity_main.xml
new file mode 100644
index 0000000..d904a58
--- /dev/null
+++ b/samples/devbytes/animation/ListViewExpandingCells/res/layout/activity_main.xml
@@ -0,0 +1,21 @@
+<!-- Copyright (C) 2013 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.
+-->
+<com.example.android.expandingcells.ExpandingListView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/main_list_view"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context=".MainActivity" />
diff --git a/samples/devbytes/animation/ListViewExpandingCells/res/layout/list_view_item.xml b/samples/devbytes/animation/ListViewExpandingCells/res/layout/list_view_item.xml
new file mode 100644
index 0000000..c2c2209
--- /dev/null
+++ b/samples/devbytes/animation/ListViewExpandingCells/res/layout/list_view_item.xml
@@ -0,0 +1,68 @@
+<!-- Copyright (C) 2013 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:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@drawable/border"
+    android:orientation="vertical">
+
+    <LinearLayout
+        android:id="@+id/item_linear_layout"
+        android:layout_height="wrap_content"
+        android:layout_width="match_parent"
+        android:orientation="horizontal">
+
+        <ImageView
+            android:id="@+id/image_view"
+            android:layout_height="match_parent"
+            android:layout_width="0dp"
+            android:gravity="center_vertical"
+            android:layout_weight="1"
+            android:scaleType="center"/>
+
+        <TextView
+            android:id="@+id/title_view"
+            android:layout_height="fill_parent"
+            android:layout_width="0dp"
+            android:gravity="center"
+            android:layout_weight="2"
+            android:textStyle="bold"
+            android:textSize="22sp"
+            android:textColor="#ffffff"/>
+
+    </LinearLayout>
+
+    <com.example.android.expandingcells.ExpandingLayout
+            android:id="@+id/expanding_layout"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:visibility="gone">
+
+        <TextView
+            android:id="@+id/text_view"
+            android:layout_height="match_parent"
+            android:layout_width="match_parent"
+            android:textStyle="bold"
+            android:textSize="22sp"
+            android:textColor="#ffffff"
+            android:gravity="center_horizontal"
+            android:paddingLeft="20dp"
+            android:paddingRight="20dp"
+            android:paddingBottom="20dp"/>
+
+    </com.example.android.expandingcells.ExpandingLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/samples/devbytes/animation/ListViewExpandingCells/res/values/strings.xml b/samples/devbytes/animation/ListViewExpandingCells/res/values/strings.xml
new file mode 100644
index 0000000..1fcee40
--- /dev/null
+++ b/samples/devbytes/animation/ListViewExpandingCells/res/values/strings.xml
@@ -0,0 +1,23 @@
+<!-- Copyright (C) 2013 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.
+-->
+
+<resources>
+
+    <string name="app_name">ExpandingCells</string>
+    <string name="short_lorem_ipsum">Lorem ipsum dolor sit amet, consectetur adipiscing elit</string>
+    <string name="medium_lorem_ipsum">"Pellentesque dictum sit amet sapien in faucibus. Curabitur fermentum, nulla quis placerat imperdiet, est nisi placerat arcu, non ornare erat justo at enim. Nam vitae porttitor sem. Quisque non quam nisi. Proin quis urna id elit ultrices cursus non tempus dolor"</string>
+    <string name="long_lorem_ipsum">"Mauris dapibus convallis massa, vitae ultrices est ultricies ut. Nam porttitor et metus ac bibendum. Nam at justo vitae felis lacinia ultrices laoreet ut arcu. Nam ac purus et turpis convallis mollis. Integer lorem eros, hendrerit imperdiet interdum vitae, sagittis eget ipsum. Donec dignissim tortor at felis fringilla, sed dignissim diam vulputate. Nam sit amet facilisis massa. Suspendisse posuere quam quis augue dapibus venenatis."</string>
+
+</resources>
diff --git a/samples/devbytes/animation/ListViewExpandingCells/src/com/example/android/expandingcells/CustomArrayAdapter.java b/samples/devbytes/animation/ListViewExpandingCells/src/com/example/android/expandingcells/CustomArrayAdapter.java
new file mode 100644
index 0000000..68919a2
--- /dev/null
+++ b/samples/devbytes/animation/ListViewExpandingCells/src/com/example/android/expandingcells/CustomArrayAdapter.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2013 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.expandingcells;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PorterDuff.Mode;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AbsListView;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import java.util.List;
+
+/**
+ * This is a custom array adapter used to populate the listview whose items will
+ * expand to display extra content in addition to the default display.
+ */
+public class CustomArrayAdapter extends ArrayAdapter<ExpandableListItem> {
+
+    private List<ExpandableListItem> mData;
+    private int mLayoutViewResourceId;
+
+    public CustomArrayAdapter(Context context, int layoutViewResourceId,
+                              List<ExpandableListItem> data) {
+        super(context, layoutViewResourceId, data);
+        mData = data;
+        mLayoutViewResourceId = layoutViewResourceId;
+    }
+
+    /**
+     * Populates the item in the listview cell with the appropriate data. This method
+     * sets the thumbnail image, the title and the extra text. This method also updates
+     * the layout parameters of the item's view so that the image and title are centered
+     * in the bounds of the collapsed view, and such that the extra text is not displayed
+     * in the collapsed state of the cell.
+     */
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent) {
+
+        final ExpandableListItem object = mData.get(position);
+
+        if(convertView == null) {
+            LayoutInflater inflater = ((Activity) getContext()).getLayoutInflater();
+            convertView = inflater.inflate(mLayoutViewResourceId, parent, false);
+        }
+
+        LinearLayout linearLayout = (LinearLayout)(convertView.findViewById(
+                R.id.item_linear_layout));
+        LinearLayout.LayoutParams linearLayoutParams = new LinearLayout.LayoutParams
+                (AbsListView.LayoutParams.MATCH_PARENT, object.getCollapsedHeight());
+        linearLayout.setLayoutParams(linearLayoutParams);
+
+        ImageView imgView = (ImageView)convertView.findViewById(R.id.image_view);
+        TextView titleView = (TextView)convertView.findViewById(R.id.title_view);
+        TextView textView = (TextView)convertView.findViewById(R.id.text_view);
+
+        titleView.setText(object.getTitle());
+        imgView.setImageBitmap(getCroppedBitmap(BitmapFactory.decodeResource(getContext()
+                .getResources(), object.getImgResource(), null)));
+        textView.setText(object.getText());
+
+        convertView.setLayoutParams(new ListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT,
+                AbsListView.LayoutParams.WRAP_CONTENT));
+
+        ExpandingLayout expandingLayout = (ExpandingLayout)convertView.findViewById(R.id
+                .expanding_layout);
+        expandingLayout.setExpandedHeight(object.getExpandedHeight());
+        expandingLayout.setSizeChangedListener(object);
+
+        if (!object.isExpanded()) {
+            expandingLayout.setVisibility(View.GONE);
+        } else {
+            expandingLayout.setVisibility(View.VISIBLE);
+        }
+
+        return convertView;
+    }
+
+    /**
+     * Crops a circle out of the thumbnail photo.
+     */
+    public Bitmap getCroppedBitmap(Bitmap bitmap) {
+        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(),
+                Config.ARGB_8888);
+
+        final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
+
+        Canvas canvas = new Canvas(output);
+
+        final Paint paint = new Paint();
+        paint.setAntiAlias(true);
+
+        int halfWidth = bitmap.getWidth()/2;
+        int halfHeight = bitmap.getHeight()/2;
+
+        canvas.drawCircle(halfWidth, halfHeight, Math.max(halfWidth, halfHeight), paint);
+
+        paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
+
+        canvas.drawBitmap(bitmap, rect, rect, paint);
+
+        return output;
+    }
+
+
+}
\ No newline at end of file
diff --git a/samples/devbytes/animation/ListViewExpandingCells/src/com/example/android/expandingcells/ExpandableListItem.java b/samples/devbytes/animation/ListViewExpandingCells/src/com/example/android/expandingcells/ExpandableListItem.java
new file mode 100644
index 0000000..1eb4fc0
--- /dev/null
+++ b/samples/devbytes/animation/ListViewExpandingCells/src/com/example/android/expandingcells/ExpandableListItem.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2013 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.expandingcells;
+
+/**
+ * This custom object is used to populate the list adapter. It contains a reference
+ * to an image, title, and the extra text to be displayed. Furthermore, it keeps track
+ * of the current state (collapsed/expanded) of the corresponding item in the list,
+ * as well as store the height of the cell in its collapsed state.
+ */
+public class ExpandableListItem implements OnSizeChangedListener {
+
+    private String mTitle;
+    private String mText;
+    private boolean mIsExpanded;
+    private int mImgResource;
+    private int mCollapsedHeight;
+    private int mExpandedHeight;
+
+    public ExpandableListItem(String title, int imgResource, int collapsedHeight, String text) {
+        mTitle = title;
+        mImgResource = imgResource;
+        mCollapsedHeight = collapsedHeight;
+        mIsExpanded = false;
+        mText = text;
+        mExpandedHeight = -1;
+    }
+
+    public boolean isExpanded() {
+        return mIsExpanded;
+    }
+
+    public void setExpanded(boolean isExpanded) {
+        mIsExpanded = isExpanded;
+    }
+
+    public String getTitle() {
+        return mTitle;
+    }
+
+    public int getImgResource() {
+        return mImgResource;
+    }
+
+    public int getCollapsedHeight() {
+        return mCollapsedHeight;
+    }
+
+    public void setCollapsedHeight(int collapsedHeight) {
+        mCollapsedHeight = collapsedHeight;
+    }
+
+    public String getText() {
+        return mText;
+    }
+
+    public void setText(String text) {
+        mText = text;
+    }
+
+    public int getExpandedHeight() {
+        return mExpandedHeight;
+    }
+
+    public void setExpandedHeight(int expandedHeight) {
+        mExpandedHeight = expandedHeight;
+    }
+
+    @Override
+    public void onSizeChanged(int newHeight) {
+        setExpandedHeight(newHeight);
+    }
+}
diff --git a/samples/devbytes/animation/ListViewExpandingCells/src/com/example/android/expandingcells/ExpandingCells.java b/samples/devbytes/animation/ListViewExpandingCells/src/com/example/android/expandingcells/ExpandingCells.java
new file mode 100644
index 0000000..6d6d4f1
--- /dev/null
+++ b/samples/devbytes/animation/ListViewExpandingCells/src/com/example/android/expandingcells/ExpandingCells.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2013 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.expandingcells;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This activity creates a listview whose items can be clicked to expand and show
+ * additional content.
+ *
+ * In this specific demo, each item in a listview displays an image and a corresponding
+ * title. These two items are centered in the default (collapsed) state of the listview's
+ * item. When the item is clicked, it expands to display text of some varying length.
+ * The item persists in this expanded state (even if the user scrolls away and then scrolls
+ * back to the same location) until it is clicked again, at which point the cell collapses
+ * back to its default state.
+ */
+public class ExpandingCells extends Activity {
+
+    private final int CELL_DEFAULT_HEIGHT = 200;
+    private final int NUM_OF_CELLS = 30;
+
+    private ExpandingListView mListView;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_main);
+
+        ExpandableListItem[] values = new ExpandableListItem[] {
+                new ExpandableListItem("Chameleon", R.drawable.chameleon, CELL_DEFAULT_HEIGHT,
+                        getResources().getString(R.string.short_lorem_ipsum)),
+                new ExpandableListItem("Rock", R.drawable.rock, CELL_DEFAULT_HEIGHT,
+                        getResources().getString(R.string.medium_lorem_ipsum)),
+                new ExpandableListItem("Flower", R.drawable.flower, CELL_DEFAULT_HEIGHT,
+                        getResources().getString(R.string.long_lorem_ipsum)),
+        };
+
+        List<ExpandableListItem> mData = new ArrayList<ExpandableListItem>();
+
+        for (int i = 0; i < NUM_OF_CELLS; i++) {
+            ExpandableListItem obj = values[i % values.length];
+            mData.add(new ExpandableListItem(obj.getTitle(), obj.getImgResource(),
+                    obj.getCollapsedHeight(), obj.getText()));
+        }
+
+        CustomArrayAdapter adapter = new CustomArrayAdapter(this, R.layout.list_view_item, mData);
+
+        mListView = (ExpandingListView)findViewById(R.id.main_list_view);
+        mListView.setAdapter(adapter);
+        mListView.setDivider(null);
+    }
+}
\ No newline at end of file
diff --git a/samples/devbytes/animation/ListViewExpandingCells/src/com/example/android/expandingcells/ExpandingLayout.java b/samples/devbytes/animation/ListViewExpandingCells/src/com/example/android/expandingcells/ExpandingLayout.java
new file mode 100644
index 0000000..5add667
--- /dev/null
+++ b/samples/devbytes/animation/ListViewExpandingCells/src/com/example/android/expandingcells/ExpandingLayout.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2013 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.expandingcells;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.RelativeLayout;
+
+/**
+ * This layout is used to contain the extra information that will be displayed
+ * when a certain cell is expanded. The custom relative layout is created in
+ * order to achieve a fading affect of this layout's contents as it is being
+ * expanded or collapsed as opposed to just fading the content in(out) after(before)
+ * the cell expands(collapses).
+ *
+ * During expansion, layout takes place so the full contents of this layout can
+ * be displayed. When the size changes to display the full contents of the layout,
+ * its height is stored. When the view is collapsing, this layout's height becomes 0
+ * since it is no longer in the visible part of the cell.By overriding onMeasure, and
+ * setting the height back to its max height, it is still visible during the collapse
+ * animation, and so, a fade out effect can be achieved.
+ */
+public class ExpandingLayout extends RelativeLayout {
+
+
+    private OnSizeChangedListener mSizeChangedListener;
+    private int mExpandedHeight = -1;
+
+    public ExpandingLayout(Context context) {
+        super(context);
+    }
+
+    public ExpandingLayout(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public ExpandingLayout(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {
+        if (mExpandedHeight > 0) {
+            heightMeasureSpec = MeasureSpec.makeMeasureSpec(mExpandedHeight, MeasureSpec.AT_MOST);
+        }
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+    }
+
+    protected void onSizeChanged (int w, int h, int oldw, int oldh) {
+        mExpandedHeight = h;
+        //Notifies the list data object corresponding to this layout that its size has changed.
+        mSizeChangedListener.onSizeChanged(h);
+    }
+
+    public int getExpandedHeight() {
+        return mExpandedHeight;
+    }
+
+    public void setExpandedHeight(int expandedHeight) {
+        mExpandedHeight = expandedHeight;
+    }
+
+    public void setSizeChangedListener(OnSizeChangedListener listener) {
+        mSizeChangedListener = listener;
+    }
+}
diff --git a/samples/devbytes/animation/ListViewExpandingCells/src/com/example/android/expandingcells/ExpandingListView.java b/samples/devbytes/animation/ListViewExpandingCells/src/com/example/android/expandingcells/ExpandingListView.java
new file mode 100644
index 0000000..0ba5d5f
--- /dev/null
+++ b/samples/devbytes/animation/ListViewExpandingCells/src/com/example/android/expandingcells/ExpandingListView.java
@@ -0,0 +1,540 @@
+/*
+ * Copyright (C) 2013 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.expandingcells;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewTreeObserver;
+import android.widget.AbsListView;
+import android.widget.AdapterView;
+import android.widget.ListView;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * A custom listview which supports the preview of extra content corresponding to each cell
+ * by clicking on the cell to hide and show the extra content.
+ */
+public class ExpandingListView extends ListView {
+
+    private boolean mShouldRemoveObserver = false;
+
+    private List<View> mViewsToDraw = new ArrayList<View>();
+
+    private int[] mTranslate;
+
+    public ExpandingListView(Context context) {
+        super(context);
+        init();
+    }
+
+    public ExpandingListView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init();
+    }
+
+    public ExpandingListView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        init();
+    }
+
+    private void init() {
+        setOnItemClickListener(mItemClickListener);
+    }
+
+    /**
+     * Listens for item clicks and expands or collapses the selected view depending on
+     * its current state.
+     */
+    private AdapterView.OnItemClickListener mItemClickListener = new AdapterView
+            .OnItemClickListener() {
+        @Override
+        public void onItemClick (AdapterView<?> parent, View view, int position, long id) {
+            ExpandableListItem viewObject = (ExpandableListItem)getItemAtPosition(getPositionForView
+                    (view));
+            if (!viewObject.isExpanded()) {
+                expandView(view);
+            } else {
+                collapseView(view);
+            }
+        }
+    };
+
+    /**
+     * Calculates the top and bottom bound changes of the selected item. These values are
+     * also used to move the bounds of the items around the one that is actually being
+     * expanded or collapsed.
+     *
+     * This method can be modified to achieve different user experiences depending
+     * on how you want the cells to expand or collapse. In this specific demo, the cells
+     * always try to expand downwards (leaving top bound untouched), and similarly,
+     * collapse upwards (leaving top bound untouched). If the change in bounds
+     * results in the complete disappearance of a cell, its lower bound is moved is
+     * moved to the top of the screen so as not to hide any additional content that
+     * the user has not interacted with yet. Furthermore, if the collapsed cell is
+     * partially off screen when it is first clicked, it is translated such that its
+     * full contents are visible. Lastly, this behaviour varies slightly near the bottom
+     * of the listview in order to account for the fact that the bottom bounds of the actual
+     * listview cannot be modified.
+     */
+    private int[] getTopAndBottomTranslations(int top, int bottom, int yDelta,
+                                              boolean isExpanding) {
+        int yTranslateTop = 0;
+        int yTranslateBottom = yDelta;
+
+        int height = bottom - top;
+
+        if (isExpanding) {
+            boolean isOverTop = top < 0;
+            boolean isBelowBottom = (top + height + yDelta) > getHeight();
+            if (isOverTop) {
+                yTranslateTop = top;
+                yTranslateBottom = yDelta - yTranslateTop;
+            } else if (isBelowBottom){
+                int deltaBelow = top + height + yDelta - getHeight();
+                yTranslateTop = top - deltaBelow < 0 ? top : deltaBelow;
+                yTranslateBottom = yDelta - yTranslateTop;
+            }
+        } else {
+            int offset = computeVerticalScrollOffset();
+            int range = computeVerticalScrollRange();
+            int extent = computeVerticalScrollExtent();
+            int leftoverExtent = range-offset - extent;
+
+            boolean isCollapsingBelowBottom = (yTranslateBottom > leftoverExtent);
+            boolean isCellCompletelyDisappearing = bottom - yTranslateBottom < 0;
+
+            if (isCollapsingBelowBottom) {
+                yTranslateTop = yTranslateBottom - leftoverExtent;
+                yTranslateBottom = yDelta - yTranslateTop;
+            } else if (isCellCompletelyDisappearing) {
+                yTranslateBottom = bottom;
+                yTranslateTop = yDelta - yTranslateBottom;
+            }
+        }
+
+        return new int[] {yTranslateTop, yTranslateBottom};
+    }
+
+    /**
+     * This method expands the view that was clicked and animates all the views
+     * around it to make room for the expanding view. There are several steps required
+     * to do this which are outlined below.
+     *
+     * 1. Store the current top and bottom bounds of each visible item in the listview.
+     * 2. Update the layout parameters of the selected view. In the context of this
+     *    method, the view should be originally collapsed and set to some custom height.
+     *    The layout parameters are updated so as to wrap the content of the additional
+     *    text that is to be displayed.
+     *
+     * After invoking a layout to take place, the listview will order all the items
+     * such that there is space for each view. This layout will be independent of what
+     * the bounds of the items were prior to the layout so two pre-draw passes will
+     * be made. This is necessary because after the layout takes place, some views that
+     * were visible before the layout may now be off bounds but a reference to these
+     * views is required so the animation completes as intended.
+     *
+     * 3. The first predraw pass will set the bounds of all the visible items to
+     *    their original location before the layout took place and then force another
+     *    layout. Since the bounds of the cells cannot be set directly, the method
+     *    setSelectionFromTop can be used to achieve a very similar effect.
+     * 4. The expanding view's bounds are animated to what the final values should be
+     *    from the original bounds.
+     * 5. The bounds above the expanding view are animated upwards while the bounds
+     *    below the expanding view are animated downwards.
+     * 6. The extra text is faded in as its contents become visible throughout the
+     *    animation process.
+     *
+     * It is important to note that the listview is disabled during the animation
+     * because the scrolling behaviour is unpredictable if the bounds of the items
+     * within the listview are not constant during the scroll.
+     */
+
+    private void expandView(final View view) {
+        final ExpandableListItem viewObject = (ExpandableListItem)getItemAtPosition(getPositionForView
+                (view));
+
+        /* Store the original top and bottom bounds of all the cells.*/
+        final int oldTop = view.getTop();
+        final int oldBottom = view.getBottom();
+
+        final HashMap<View, int[]> oldCoordinates = new HashMap<View, int[]>();
+
+        int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View v = getChildAt(i);
+            v.setHasTransientState(true);
+            oldCoordinates.put(v, new int[] {v.getTop(), v.getBottom()});
+        }
+
+        /* Update the layout so the extra content becomes visible.*/
+        final View expandingLayout = view.findViewById(R.id.expanding_layout);
+        expandingLayout.setVisibility(View.VISIBLE);
+
+        /* Add an onPreDraw Listener to the listview. onPreDraw will get invoked after onLayout
+        * and onMeasure have run but before anything has been drawn. This
+        * means that the final post layout properties for all the items have already been
+        * determined, but still have not been rendered onto the screen.*/
+        final ViewTreeObserver observer = getViewTreeObserver();
+        observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+
+            @Override
+            public boolean onPreDraw() {
+                /* Determine if this is the first or second pass.*/
+                if (!mShouldRemoveObserver) {
+                    mShouldRemoveObserver = true;
+
+                    /* Calculate what the parameters should be for setSelectionFromTop.
+                    * The ListView must be offset in a way, such that after the animation
+                    * takes place, all the cells that remain visible are rendered completely
+                    * by the ListView.*/
+                    int newTop = view.getTop();
+                    int newBottom = view.getBottom();
+
+                    int newHeight = newBottom - newTop;
+                    int oldHeight = oldBottom - oldTop;
+                    int delta = newHeight - oldHeight;
+
+                    mTranslate = getTopAndBottomTranslations(oldTop, oldBottom, delta, true);
+
+                    int currentTop = view.getTop();
+                    int futureTop = oldTop - mTranslate[0];
+
+                    int firstChildStartTop = getChildAt(0).getTop();
+                    int firstVisiblePosition = getFirstVisiblePosition();
+                    int deltaTop = currentTop - futureTop;
+
+                    int i;
+                    int childCount = getChildCount();
+                    for (i = 0; i < childCount; i++) {
+                        View v = getChildAt(i);
+                        int height = v.getBottom() - Math.max(0, v.getTop());
+                        if (deltaTop - height > 0) {
+                            firstVisiblePosition++;
+                            deltaTop -= height;
+                        } else {
+                            break;
+                        }
+                    }
+
+                    if (i > 0) {
+                        firstChildStartTop = 0;
+                    }
+
+                    setSelectionFromTop(firstVisiblePosition, firstChildStartTop - deltaTop);
+
+                    /* Request another layout to update the layout parameters of the cells.*/
+                    requestLayout();
+
+                    /* Return false such that the ListView does not redraw its contents on
+                     * this layout but only updates all the parameters associated with its
+                     * children.*/
+                    return false;
+                }
+
+                /* Remove the predraw listener so this method does not keep getting called. */
+                mShouldRemoveObserver = false;
+                observer.removeOnPreDrawListener(this);
+
+                int yTranslateTop = mTranslate[0];
+                int yTranslateBottom = mTranslate[1];
+
+                ArrayList <Animator> animations = new ArrayList<Animator>();
+
+                int index = indexOfChild(view);
+
+                /* Loop through all the views that were on the screen before the cell was
+                *  expanded. Some cells will still be children of the ListView while
+                *  others will not. The cells that remain children of the ListView
+                *  simply have their bounds animated appropriately. The cells that are no
+                *  longer children of the ListView also have their bounds animated, but
+                *  must also be added to a list of views which will be drawn in dispatchDraw.*/
+                for (View v: oldCoordinates.keySet()) {
+                    int[] old = oldCoordinates.get(v);
+                    v.setTop(old[0]);
+                    v.setBottom(old[1]);
+                    if (v.getParent() == null) {
+                        mViewsToDraw.add(v);
+                        int delta = old[0] < oldTop ? -yTranslateTop : yTranslateBottom;
+                        animations.add(getAnimation(v, delta, delta));
+                    } else {
+                        int i = indexOfChild(v);
+                        if (v != view) {
+                            int delta = i > index ? yTranslateBottom : -yTranslateTop;
+                            animations.add(getAnimation(v, delta, delta));
+                        }
+                        v.setHasTransientState(false);
+                    }
+                }
+
+                /* Adds animation for expanding the cell that was clicked. */
+                animations.add(getAnimation(view, -yTranslateTop, yTranslateBottom));
+
+                /* Adds an animation for fading in the extra content. */
+                animations.add(ObjectAnimator.ofFloat(view.findViewById(R.id.expanding_layout),
+                        View.ALPHA, 0, 1));
+
+                /* Disabled the ListView for the duration of the animation.*/
+                setEnabled(false);
+                setClickable(false);
+
+                /* Play all the animations created above together at the same time. */
+                AnimatorSet s = new AnimatorSet();
+                s.playTogether(animations);
+                s.addListener(new AnimatorListenerAdapter() {
+                    @Override
+                    public void onAnimationEnd(Animator animation) {
+                        viewObject.setExpanded(true);
+                        setEnabled(true);
+                        setClickable(true);
+                        if (mViewsToDraw.size() > 0) {
+                            for (View v : mViewsToDraw) {
+                                v.setHasTransientState(false);
+                            }
+                        }
+                        mViewsToDraw.clear();
+                    }
+                });
+                s.start();
+                return true;
+            }
+        });
+    }
+
+    /**
+     * By overriding dispatchDraw, we can draw the cells that disappear during the
+     * expansion process. When the cell expands, some items below or above the expanding
+     * cell may be moved off screen and are thus no longer children of the ListView's
+     * layout. By storing a reference to these views prior to the layout, and
+     * guaranteeing that these cells do not get recycled, the cells can be drawn
+     * directly onto the canvas during the animation process. After the animation
+     * completes, the references to the extra views can then be discarded.
+     */
+    @Override
+    protected void dispatchDraw(Canvas canvas) {
+        super.dispatchDraw(canvas);
+
+        if (mViewsToDraw.size() == 0) {
+            return;
+        }
+
+        for (View v: mViewsToDraw) {
+            canvas.translate(0, v.getTop());
+            v.draw(canvas);
+            canvas.translate(0, -v.getTop());
+        }
+    }
+
+    /**
+     * This method collapses the view that was clicked and animates all the views
+     * around it to close around the collapsing view. There are several steps required
+     * to do this which are outlined below.
+     *
+     * 1. Update the layout parameters of the view clicked so as to minimize its height
+     *    to the original collapsed (default) state.
+     * 2. After invoking a layout, the listview will shift all the cells so as to display
+     *    them most efficiently. Therefore, during the first predraw pass, the listview
+     *    must be offset by some amount such that given the custom bound change upon
+     *    collapse, all the cells that need to be on the screen after the layout
+     *    are rendered by the listview.
+     * 3. On the second predraw pass, all the items are first returned to their original
+     *    location (before the first layout).
+     * 4. The collapsing view's bounds are animated to what the final values should be.
+     * 5. The bounds above the collapsing view are animated downwards while the bounds
+     *    below the collapsing view are animated upwards.
+     * 6. The extra text is faded out as its contents become visible throughout the
+     *    animation process.
+     */
+
+     private void collapseView(final View view) {
+        final ExpandableListItem viewObject = (ExpandableListItem)getItemAtPosition
+                (getPositionForView(view));
+
+        /* Store the original top and bottom bounds of all the cells.*/
+        final int oldTop = view.getTop();
+        final int oldBottom = view.getBottom();
+
+        final HashMap<View, int[]> oldCoordinates = new HashMap<View, int[]>();
+
+        int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View v = getChildAt(i);
+            v.setHasTransientState(true);
+            oldCoordinates.put(v, new int [] {v.getTop(), v.getBottom()});
+        }
+
+        /* Update the layout so the extra content becomes invisible.*/
+        view.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT,
+                 viewObject.getCollapsedHeight()));
+
+         /* Add an onPreDraw listener. */
+        final ViewTreeObserver observer = getViewTreeObserver();
+        observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+
+            @Override
+            public boolean onPreDraw() {
+
+                if (!mShouldRemoveObserver) {
+                    /*Same as for expandingView, the parameters for setSelectionFromTop must
+                    * be determined such that the necessary cells of the ListView are rendered
+                    * and added to it.*/
+                    mShouldRemoveObserver = true;
+
+                    int newTop = view.getTop();
+                    int newBottom = view.getBottom();
+
+                    int newHeight = newBottom - newTop;
+                    int oldHeight = oldBottom - oldTop;
+                    int deltaHeight = oldHeight - newHeight;
+
+                    mTranslate = getTopAndBottomTranslations(oldTop, oldBottom, deltaHeight, false);
+
+                    int currentTop = view.getTop();
+                    int futureTop = oldTop + mTranslate[0];
+
+                    int firstChildStartTop = getChildAt(0).getTop();
+                    int firstVisiblePosition = getFirstVisiblePosition();
+                    int deltaTop = currentTop - futureTop;
+
+                    int i;
+                    int childCount = getChildCount();
+                    for (i = 0; i < childCount; i++) {
+                        View v = getChildAt(i);
+                        int height = v.getBottom() - Math.max(0, v.getTop());
+                        if (deltaTop - height > 0) {
+                            firstVisiblePosition++;
+                            deltaTop -= height;
+                        } else {
+                            break;
+                        }
+                    }
+
+                    if (i > 0) {
+                        firstChildStartTop = 0;
+                    }
+
+                    setSelectionFromTop(firstVisiblePosition, firstChildStartTop - deltaTop);
+
+                    requestLayout();
+
+                    return false;
+                }
+
+                mShouldRemoveObserver = false;
+                observer.removeOnPreDrawListener(this);
+
+                int yTranslateTop = mTranslate[0];
+                int yTranslateBottom = mTranslate[1];
+
+                int index = indexOfChild(view);
+                int childCount = getChildCount();
+                for (int i = 0; i < childCount; i++) {
+                    View v = getChildAt(i);
+                    int [] old = oldCoordinates.get(v);
+                    if (old != null) {
+                        /* If the cell was present in the ListView before the collapse and
+                        * after the collapse then the bounds are reset to their old values.*/
+                        v.setTop(old[0]);
+                        v.setBottom(old[1]);
+                        v.setHasTransientState(false);
+                    } else {
+                        /* If the cell is present in the ListView after the collapse but
+                         * not before the collapse then the bounds are calculated using
+                         * the bottom and top translation of the collapsing cell.*/
+                        int delta = i > index ? yTranslateBottom : -yTranslateTop;
+                        v.setTop(v.getTop() + delta);
+                        v.setBottom(v.getBottom() + delta);
+                    }
+                }
+
+                final View expandingLayout = view.findViewById (R.id.expanding_layout);
+
+                /* Animates all the cells present on the screen after the collapse. */
+                ArrayList <Animator> animations = new ArrayList<Animator>();
+                for (int i = 0; i < childCount; i++) {
+                    View v = getChildAt(i);
+                    if (v != view) {
+                        float diff = i > index ? -yTranslateBottom : yTranslateTop;
+                        animations.add(getAnimation(v, diff, diff));
+                    }
+                }
+
+
+                /* Adds animation for collapsing the cell that was clicked. */
+                animations.add(getAnimation(view, yTranslateTop, -yTranslateBottom));
+
+                /* Adds an animation for fading out the extra content. */
+                animations.add(ObjectAnimator.ofFloat(expandingLayout, View.ALPHA, 1, 0));
+
+                /* Disabled the ListView for the duration of the animation.*/
+                setEnabled(false);
+                setClickable(false);
+
+                /* Play all the animations created above together at the same time. */
+                AnimatorSet s = new AnimatorSet();
+                s.playTogether(animations);
+                s.addListener(new AnimatorListenerAdapter() {
+                    @Override
+                    public void onAnimationEnd(Animator animation) {
+                        expandingLayout.setVisibility(View.GONE);
+                        view.setLayoutParams(new AbsListView.LayoutParams(AbsListView
+                                .LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.WRAP_CONTENT));
+                        viewObject.setExpanded(false);
+                        setEnabled(true);
+                        setClickable(true);
+                        /* Note that alpha must be set back to 1 in case this view is reused
+                        * by a cell that was expanded, but not yet collapsed, so its state
+                        * should persist in an expanded state with the extra content visible.*/
+                        expandingLayout.setAlpha(1);
+                    }
+                });
+                s.start();
+
+                return true;
+            }
+        });
+    }
+
+    /**
+     * This method takes some view and the values by which its top and bottom bounds
+     * should be changed by. Given these params, an animation which will animate
+     * these bound changes is created and returned.
+     */
+    private Animator getAnimation(final View view, float translateTop, float translateBottom) {
+
+        int top = view.getTop();
+        int bottom = view.getBottom();
+
+        int endTop = (int)(top + translateTop);
+        int endBottom = (int)(bottom + translateBottom);
+
+        PropertyValuesHolder translationTop = PropertyValuesHolder.ofInt("top", top, endTop);
+        PropertyValuesHolder translationBottom = PropertyValuesHolder.ofInt("bottom", bottom,
+                endBottom);
+
+        return ObjectAnimator.ofPropertyValuesHolder(view, translationTop, translationBottom);
+    }
+}
diff --git a/samples/devbytes/animation/ListViewExpandingCells/src/com/example/android/expandingcells/OnSizeChangedListener.java b/samples/devbytes/animation/ListViewExpandingCells/src/com/example/android/expandingcells/OnSizeChangedListener.java
new file mode 100644
index 0000000..ec51950
--- /dev/null
+++ b/samples/devbytes/animation/ListViewExpandingCells/src/com/example/android/expandingcells/OnSizeChangedListener.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2013 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.expandingcells;
+
+/**
+ * A listener used to update the list data object when the corresponding expanding
+ * layout experiences a size change.
+ */
+public interface OnSizeChangedListener {
+    public void onSizeChanged(int newHeight);
+}
diff --git a/samples/devbytes/animation/ListViewItemAnimations/AndroidManifest.xml b/samples/devbytes/animation/ListViewItemAnimations/AndroidManifest.xml
new file mode 100644
index 0000000..173b188
--- /dev/null
+++ b/samples/devbytes/animation/ListViewItemAnimations/AndroidManifest.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.android.listviewitemanimations"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk
+        android:minSdkVersion="9"
+        android:targetSdkVersion="16" />
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/ic_launcher"
+        android:label="@string/app_name"
+        android:theme="@style/AppTheme" >
+        <activity
+            android:theme="@style/WithoutBackground"
+            android:name="com.example.android.listviewitemanimations.ListViewItemAnimations"
+            android:label="@string/app_name" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest>
\ No newline at end of file
diff --git a/samples/devbytes/animation/ListViewItemAnimations/res/drawable-hdpi/ic_launcher.png b/samples/devbytes/animation/ListViewItemAnimations/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..96a442e
--- /dev/null
+++ b/samples/devbytes/animation/ListViewItemAnimations/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/ListViewItemAnimations/res/drawable-mdpi/ic_launcher.png b/samples/devbytes/animation/ListViewItemAnimations/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..359047d
--- /dev/null
+++ b/samples/devbytes/animation/ListViewItemAnimations/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/ListViewItemAnimations/res/drawable-xhdpi/ic_launcher.png b/samples/devbytes/animation/ListViewItemAnimations/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..71c6d76
--- /dev/null
+++ b/samples/devbytes/animation/ListViewItemAnimations/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/ListViewItemAnimations/res/drawable-xhdpi/shadowed_background.9.png b/samples/devbytes/animation/ListViewItemAnimations/res/drawable-xhdpi/shadowed_background.9.png
new file mode 100644
index 0000000..6226b9e
--- /dev/null
+++ b/samples/devbytes/animation/ListViewItemAnimations/res/drawable-xhdpi/shadowed_background.9.png
Binary files differ
diff --git a/samples/devbytes/animation/ListViewItemAnimations/res/drawable-xhdpi/tv_background_with_divider.9.png b/samples/devbytes/animation/ListViewItemAnimations/res/drawable-xhdpi/tv_background_with_divider.9.png
new file mode 100644
index 0000000..e6e3cd5
--- /dev/null
+++ b/samples/devbytes/animation/ListViewItemAnimations/res/drawable-xhdpi/tv_background_with_divider.9.png
Binary files differ
diff --git a/samples/devbytes/animation/ListViewItemAnimations/res/layout-v9/activity_list_view_item_animations.xml b/samples/devbytes/animation/ListViewItemAnimations/res/layout-v9/activity_list_view_item_animations.xml
new file mode 100644
index 0000000..8290927
--- /dev/null
+++ b/samples/devbytes/animation/ListViewItemAnimations/res/layout-v9/activity_list_view_item_animations.xml
@@ -0,0 +1,37 @@
+<!-- Copyright (C) 2013 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"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context=".ListViewAnimations" >
+
+    <view
+        class="com.example.android.listviewitemanimations.BackgroundContainer"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:id="@+id/listViewBackground">
+
+        <ListView
+            android:id="@+id/listview"
+            android:divider="@null"
+            android:dividerHeight="0dp"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content" />
+
+    </view>
+
+</LinearLayout>
diff --git a/samples/devbytes/animation/ListViewItemAnimations/res/layout-v9/opaque_text_view.xml b/samples/devbytes/animation/ListViewItemAnimations/res/layout-v9/opaque_text_view.xml
new file mode 100644
index 0000000..aa03362
--- /dev/null
+++ b/samples/devbytes/animation/ListViewItemAnimations/res/layout-v9/opaque_text_view.xml
@@ -0,0 +1,25 @@
+<!-- Copyright (C) 2013 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.
+-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+          android:layout_width="match_parent"
+          android:layout_height="wrap_content"
+          android:background="@drawable/tv_background_with_divider"
+          android:textAppearance="?android:attr/textAppearanceListItemSmall"
+          android:paddingLeft="10dp"
+          android:paddingRight="10dp"
+          android:textSize="20dp"
+          android:gravity="center_vertical"
+          android:minHeight="48dp"
+        />
diff --git a/samples/devbytes/animation/ListViewItemAnimations/res/layout/activity_list_view_item_animations.xml b/samples/devbytes/animation/ListViewItemAnimations/res/layout/activity_list_view_item_animations.xml
new file mode 100644
index 0000000..8290927
--- /dev/null
+++ b/samples/devbytes/animation/ListViewItemAnimations/res/layout/activity_list_view_item_animations.xml
@@ -0,0 +1,37 @@
+<!-- Copyright (C) 2013 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"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context=".ListViewAnimations" >
+
+    <view
+        class="com.example.android.listviewitemanimations.BackgroundContainer"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:id="@+id/listViewBackground">
+
+        <ListView
+            android:id="@+id/listview"
+            android:divider="@null"
+            android:dividerHeight="0dp"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content" />
+
+    </view>
+
+</LinearLayout>
diff --git a/samples/devbytes/animation/ListViewItemAnimations/res/layout/opaque_text_view.xml b/samples/devbytes/animation/ListViewItemAnimations/res/layout/opaque_text_view.xml
new file mode 100644
index 0000000..c37f62d
--- /dev/null
+++ b/samples/devbytes/animation/ListViewItemAnimations/res/layout/opaque_text_view.xml
@@ -0,0 +1,24 @@
+<!-- Copyright (C) 2013 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.
+-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:background="@drawable/tv_background_with_divider"
+    android:textAppearance="?android:attr/textAppearanceListItemSmall"
+    android:gravity="center_vertical"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+    android:minHeight="?android:attr/listPreferredItemHeightSmall"
+/>
diff --git a/samples/devbytes/animation/ListViewItemAnimations/res/values-v11/styles.xml b/samples/devbytes/animation/ListViewItemAnimations/res/values-v11/styles.xml
new file mode 100644
index 0000000..556d2da
--- /dev/null
+++ b/samples/devbytes/animation/ListViewItemAnimations/res/values-v11/styles.xml
@@ -0,0 +1,25 @@
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <!--
+        Base application theme for API 11+. This theme completely replaces
+        AppBaseTheme from res/values/styles.xml on API 11+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+        <!-- API 11 theme customizations can go here. -->
+    </style>
+
+</resources>
\ No newline at end of file
diff --git a/samples/devbytes/animation/ListViewItemAnimations/res/values-v14/styles.xml b/samples/devbytes/animation/ListViewItemAnimations/res/values-v14/styles.xml
new file mode 100644
index 0000000..6e9521a
--- /dev/null
+++ b/samples/devbytes/animation/ListViewItemAnimations/res/values-v14/styles.xml
@@ -0,0 +1,26 @@
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <!--
+        Base application theme for API 14+. This theme completely replaces
+        AppBaseTheme from BOTH res/values/styles.xml and
+        res/values-v11/styles.xml on API 14+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+        <!-- API 14 theme customizations can go here. -->
+    </style>
+
+</resources>
\ No newline at end of file
diff --git a/samples/devbytes/animation/ListViewItemAnimations/res/values/dimens.xml b/samples/devbytes/animation/ListViewItemAnimations/res/values/dimens.xml
new file mode 100644
index 0000000..90db76b
--- /dev/null
+++ b/samples/devbytes/animation/ListViewItemAnimations/res/values/dimens.xml
@@ -0,0 +1,21 @@
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <!-- Default screen margins, per the Android Design guidelines. -->
+    <dimen name="activity_horizontal_margin">16dp</dimen>
+    <dimen name="activity_vertical_margin">16dp</dimen>
+
+</resources>
\ No newline at end of file
diff --git a/samples/devbytes/animation/ListViewItemAnimations/res/values/strings.xml b/samples/devbytes/animation/ListViewItemAnimations/res/values/strings.xml
new file mode 100644
index 0000000..2cc5f71
--- /dev/null
+++ b/samples/devbytes/animation/ListViewItemAnimations/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <string name="app_name">ListViewItemAnimations</string>
+    <string name="action_settings">Settings</string>
+    <string name="hello_world">Hello world!</string>
+
+</resources>
\ No newline at end of file
diff --git a/samples/devbytes/animation/ListViewItemAnimations/res/values/styles.xml b/samples/devbytes/animation/ListViewItemAnimations/res/values/styles.xml
new file mode 100644
index 0000000..ee3c56c
--- /dev/null
+++ b/samples/devbytes/animation/ListViewItemAnimations/res/values/styles.xml
@@ -0,0 +1,38 @@
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <!--
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Light">
+        <!--
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        -->
+    </style>
+
+    <!-- Application theme. -->
+    <style name="AppTheme" parent="AppBaseTheme">
+        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+    </style>
+
+    <style name="WithoutBackground" parent="AppTheme">
+        <item name="android:windowBackground">@null</item>
+    </style>
+    
+</resources>
\ No newline at end of file
diff --git a/samples/devbytes/animation/ListViewItemAnimations/src/com/example/android/listviewitemanimations/BackgroundContainer.java b/samples/devbytes/animation/ListViewItemAnimations/src/com/example/android/listviewitemanimations/BackgroundContainer.java
new file mode 100644
index 0000000..40ac39a
--- /dev/null
+++ b/samples/devbytes/animation/ListViewItemAnimations/src/com/example/android/listviewitemanimations/BackgroundContainer.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2013 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.listviewitemanimations;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.widget.FrameLayout;
+
+public class BackgroundContainer extends FrameLayout {
+
+    boolean mShowing = false;
+    Drawable mShadowedBackground;
+    int mOpenAreaTop, mOpenAreaBottom, mOpenAreaHeight;
+    boolean mUpdateBounds = false;
+    
+    public BackgroundContainer(Context context) {
+        super(context);
+        init();
+    }
+
+    public BackgroundContainer(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init();
+    }
+
+    public BackgroundContainer(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        init();
+    }
+
+    private void init() {
+        mShadowedBackground = getContext().getResources().getDrawable(R.drawable.shadowed_background);
+    }
+
+    public void showBackground(int top, int bottom) {
+        setWillNotDraw(false);
+        mOpenAreaTop = top;
+        mOpenAreaHeight = bottom;
+        mShowing = true;
+        mUpdateBounds = true;
+    }
+    
+    public void hideBackground() {
+        setWillNotDraw(true);
+        mShowing = false;
+    }
+    
+    @Override
+    protected void onDraw(Canvas canvas) {
+        if (mShowing) {
+            if (mUpdateBounds) {
+                mShadowedBackground.setBounds(0, 0, getWidth(), mOpenAreaHeight);
+            }
+            canvas.save();
+            canvas.translate(0, mOpenAreaTop);
+            mShadowedBackground.draw(canvas);
+            canvas.restore();
+        }
+    }
+
+}
diff --git a/samples/devbytes/animation/ListViewItemAnimations/src/com/example/android/listviewitemanimations/Cheeses.java b/samples/devbytes/animation/ListViewItemAnimations/src/com/example/android/listviewitemanimations/Cheeses.java
new file mode 100644
index 0000000..5241022
--- /dev/null
+++ b/samples/devbytes/animation/ListViewItemAnimations/src/com/example/android/listviewitemanimations/Cheeses.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2013 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.listviewitemanimations;
+
+public class Cheeses {
+
+    public static final String[] sCheeseStrings = {
+            "Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi",
+            "Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu", "Airag", "Airedale",
+            "Aisy Cendre", "Allgauer Emmentaler", "Alverca", "Ambert", "American Cheese",
+            "Ami du Chambertin", "Anejo Enchilado", "Anneau du Vic-Bilh", "Anthoriro", "Appenzell",
+            "Aragon", "Ardi Gasna", "Ardrahan", "Armenian String", "Aromes au Gene de Marc",
+            "Asadero", "Asiago", "Aubisque Pyrenees", "Autun", "Avaxtskyr", "Baby Swiss",
+            "Babybel", "Baguette Laonnaise", "Bakers", "Baladi", "Balaton", "Bandal", "Banon",
+            "Barry's Bay Cheddar", "Basing", "Basket Cheese", "Bath Cheese", "Bavarian Bergkase",
+            "Baylough", "Beaufort", "Beauvoorde", "Beenleigh Blue", "Beer Cheese", "Bel Paese",
+            "Bergader", "Bergere Bleue", "Berkswell", "Beyaz Peynir", "Bierkase", "Bishop Kennedy",
+            "Blarney", "Bleu d'Auvergne", "Bleu de Gex", "Bleu de Laqueuille",
+            "Bleu de Septmoncel", "Bleu Des Causses", "Blue", "Blue Castello", "Blue Rathgore",
+            "Blue Vein (Australian)", "Blue Vein Cheeses", "Bocconcini", "Bocconcini (Australian)",
+            "Boeren Leidenkaas", "Bonchester", "Bosworth", "Bougon", "Boule Du Roves",
+            "Boulette d'Avesnes", "Boursault", "Boursin", "Bouyssou", "Bra", "Braudostur",
+            "Breakfast Cheese", "Brebis du Lavort", "Brebis du Lochois", "Brebis du Puyfaucon",
+            "Bresse Bleu", "Brick", "Brie", "Brie de Meaux", "Brie de Melun", "Brillat-Savarin",
+            "Brin", "Brin d' Amour", "Brin d'Amour", "Brinza (Burduf Brinza)",
+            "Briquette de Brebis", "Briquette du Forez", "Broccio", "Broccio Demi-Affine",
+            "Brousse du Rove", "Bruder Basil", "Brusselae Kaas (Fromage de Bruxelles)", "Bryndza",
+            "Buchette d'Anjou", "Buffalo", "Burgos", "Butte", "Butterkase", "Button (Innes)",
+            "Buxton Blue", "Cabecou", "Caboc", "Cabrales", "Cachaille", "Caciocavallo", "Caciotta",
+            "Caerphilly", "Cairnsmore", "Calenzana", "Cambazola", "Camembert de Normandie",
+            "Canadian Cheddar", "Canestrato", "Cantal", "Caprice des Dieux", "Capricorn Goat",
+            "Capriole Banon", "Carre de l'Est", "Casciotta di Urbino", "Cashel Blue", "Castellano",
+            "Castelleno", "Castelmagno", "Castelo Branco", "Castigliano", "Cathelain",
+            "Celtic Promise", "Cendre d'Olivet", "Cerney", "Chabichou", "Chabichou du Poitou",
+            "Chabis de Gatine", "Chaource", "Charolais", "Chaumes", "Cheddar",
+            "Cheddar Clothbound", "Cheshire", "Chevres", "Chevrotin des Aravis", "Chontaleno",
+            "Civray", "Coeur de Camembert au Calvados", "Coeur de Chevre", "Colby", "Cold Pack",
+            "Comte", "Coolea", "Cooleney", "Coquetdale", "Corleggy", "Cornish Pepper",
+            "Cotherstone", "Cotija", "Cottage Cheese", "Cottage Cheese (Australian)",
+            "Cougar Gold", "Coulommiers", "Coverdale", "Crayeux de Roncq", "Cream Cheese",
+            "Cream Havarti", "Crema Agria", "Crema Mexicana", "Creme Fraiche", "Crescenza",
+            "Croghan", "Crottin de Chavignol", "Crottin du Chavignol", "Crowdie", "Crowley",
+            "Cuajada", "Curd", "Cure Nantais", "Curworthy", "Cwmtawe Pecorino",
+            "Cypress Grove Chevre", "Danablu (Danish Blue)", "Danbo", "Danish Fontina",
+            "Daralagjazsky", "Dauphin", "Delice des Fiouves", "Denhany Dorset Drum", "Derby",
+            "Dessertnyj Belyj", "Devon Blue", "Devon Garland", "Dolcelatte", "Doolin",
+            "Doppelrhamstufel", "Dorset Blue Vinney", "Double Gloucester", "Double Worcester",
+            "Dreux a la Feuille", "Dry Jack", "Duddleswell", "Dunbarra", "Dunlop", "Dunsyre Blue",
+            "Duroblando", "Durrus", "Dutch Mimolette (Commissiekaas)", "Edam", "Edelpilz",
+            "Emental Grand Cru", "Emlett", "Emmental", "Epoisses de Bourgogne", "Esbareich",
+            "Esrom", "Etorki", "Evansdale Farmhouse Brie", "Evora De L'Alentejo", "Exmoor Blue",
+            "Explorateur", "Feta", "Feta (Australian)", "Figue", "Filetta", "Fin-de-Siecle",
+            "Finlandia Swiss", "Finn", "Fiore Sardo", "Fleur du Maquis", "Flor de Guia",
+            "Flower Marie", "Folded", "Folded cheese with mint", "Fondant de Brebis",
+            "Fontainebleau", "Fontal", "Fontina Val d'Aosta", "Formaggio di capra", "Fougerus",
+            "Four Herb Gouda", "Fourme d' Ambert", "Fourme de Haute Loire", "Fourme de Montbrison",
+            "Fresh Jack", "Fresh Mozzarella", "Fresh Ricotta", "Fresh Truffles", "Fribourgeois",
+            "Friesekaas", "Friesian", "Friesla", "Frinault", "Fromage a Raclette", "Fromage Corse",
+            "Fromage de Montagne de Savoie", "Fromage Frais", "Fruit Cream Cheese",
+            "Frying Cheese", "Fynbo", "Gabriel", "Galette du Paludier", "Galette Lyonnaise",
+            "Galloway Goat's Milk Gems", "Gammelost", "Gaperon a l'Ail", "Garrotxa", "Gastanberra",
+            "Geitost", "Gippsland Blue", "Gjetost", "Gloucester", "Golden Cross", "Gorgonzola",
+            "Gornyaltajski", "Gospel Green", "Gouda", "Goutu", "Gowrie", "Grabetto", "Graddost",
+            "Grafton Village Cheddar", "Grana", "Grana Padano", "Grand Vatel",
+            "Grataron d' Areches", "Gratte-Paille", "Graviera", "Greuilh", "Greve",
+            "Gris de Lille", "Gruyere", "Gubbeen", "Guerbigny", "Halloumi",
+            "Halloumy (Australian)", "Haloumi-Style Cheese", "Harbourne Blue", "Havarti",
+            "Heidi Gruyere", "Hereford Hop", "Herrgardsost", "Herriot Farmhouse", "Herve",
+            "Hipi Iti", "Hubbardston Blue Cow", "Hushallsost", "Iberico", "Idaho Goatster",
+            "Idiazabal", "Il Boschetto al Tartufo", "Ile d'Yeu", "Isle of Mull", "Jarlsberg",
+            "Jermi Tortes", "Jibneh Arabieh", "Jindi Brie", "Jubilee Blue", "Juustoleipa",
+            "Kadchgall", "Kaseri", "Kashta", "Kefalotyri", "Kenafa", "Kernhem", "Kervella Affine",
+            "Kikorangi", "King Island Cape Wickham Brie", "King River Gold", "Klosterkaese",
+            "Knockalara", "Kugelkase", "L'Aveyronnais", "L'Ecir de l'Aubrac", "La Taupiniere",
+            "La Vache Qui Rit", "Laguiole", "Lairobell", "Lajta", "Lanark Blue", "Lancashire",
+            "Langres", "Lappi", "Laruns", "Lavistown", "Le Brin", "Le Fium Orbo", "Le Lacandou",
+            "Le Roule", "Leafield", "Lebbene", "Leerdammer", "Leicester", "Leyden", "Limburger",
+            "Lincolnshire Poacher", "Lingot Saint Bousquet d'Orb", "Liptauer", "Little Rydings",
+            "Livarot", "Llanboidy", "Llanglofan Farmhouse", "Loch Arthur Farmhouse",
+            "Loddiswell Avondale", "Longhorn", "Lou Palou", "Lou Pevre", "Lyonnais", "Maasdam",
+            "Macconais", "Mahoe Aged Gouda", "Mahon", "Malvern", "Mamirolle", "Manchego",
+            "Manouri", "Manur", "Marble Cheddar", "Marbled Cheeses", "Maredsous", "Margotin",
+            "Maribo", "Maroilles", "Mascares", "Mascarpone", "Mascarpone (Australian)",
+            "Mascarpone Torta", "Matocq", "Maytag Blue", "Meira", "Menallack Farmhouse",
+            "Menonita", "Meredith Blue", "Mesost", "Metton (Cancoillotte)", "Meyer Vintage Gouda",
+            "Mihalic Peynir", "Milleens", "Mimolette", "Mine-Gabhar", "Mini Baby Bells", "Mixte",
+            "Molbo", "Monastery Cheeses", "Mondseer", "Mont D'or Lyonnais", "Montasio",
+            "Monterey Jack", "Monterey Jack Dry", "Morbier", "Morbier Cru de Montagne",
+            "Mothais a la Feuille", "Mozzarella", "Mozzarella (Australian)",
+            "Mozzarella di Bufala", "Mozzarella Fresh, in water", "Mozzarella Rolls", "Munster",
+            "Murol", "Mycella", "Myzithra", "Naboulsi", "Nantais", "Neufchatel",
+            "Neufchatel (Australian)", "Niolo", "Nokkelost", "Northumberland", "Oaxaca",
+            "Olde York", "Olivet au Foin", "Olivet Bleu", "Olivet Cendre",
+            "Orkney Extra Mature Cheddar", "Orla", "Oschtjepka", "Ossau Fermier", "Ossau-Iraty",
+            "Oszczypek", "Oxford Blue", "P'tit Berrichon", "Palet de Babligny", "Paneer", "Panela",
+            "Pannerone", "Pant ys Gawn", "Parmesan (Parmigiano)", "Parmigiano Reggiano",
+            "Pas de l'Escalette", "Passendale", "Pasteurized Processed", "Pate de Fromage",
+            "Patefine Fort", "Pave d'Affinois", "Pave d'Auge", "Pave de Chirac", "Pave du Berry",
+            "Pecorino", "Pecorino in Walnut Leaves", "Pecorino Romano", "Peekskill Pyramid",
+            "Pelardon des Cevennes", "Pelardon des Corbieres", "Penamellera", "Penbryn",
+            "Pencarreg", "Perail de Brebis", "Petit Morin", "Petit Pardou", "Petit-Suisse",
+            "Picodon de Chevre", "Picos de Europa", "Piora", "Pithtviers au Foin",
+            "Plateau de Herve", "Plymouth Cheese", "Podhalanski", "Poivre d'Ane", "Polkolbin",
+            "Pont l'Eveque", "Port Nicholson", "Port-Salut", "Postel", "Pouligny-Saint-Pierre",
+            "Pourly", "Prastost", "Pressato", "Prince-Jean", "Processed Cheddar", "Provolone",
+            "Provolone (Australian)", "Pyengana Cheddar", "Pyramide", "Quark",
+            "Quark (Australian)", "Quartirolo Lombardo", "Quatre-Vents", "Quercy Petit",
+            "Queso Blanco", "Queso Blanco con Frutas --Pina y Mango", "Queso de Murcia",
+            "Queso del Montsec", "Queso del Tietar", "Queso Fresco", "Queso Fresco (Adobera)",
+            "Queso Iberico", "Queso Jalapeno", "Queso Majorero", "Queso Media Luna",
+            "Queso Para Frier", "Queso Quesadilla", "Rabacal", "Raclette", "Ragusano", "Raschera",
+            "Reblochon", "Red Leicester", "Regal de la Dombes", "Reggianito", "Remedou",
+            "Requeson", "Richelieu", "Ricotta", "Ricotta (Australian)", "Ricotta Salata", "Ridder",
+            "Rigotte", "Rocamadour", "Rollot", "Romano", "Romans Part Dieu", "Roncal", "Roquefort",
+            "Roule", "Rouleau De Beaulieu", "Royalp Tilsit", "Rubens", "Rustinu", "Saaland Pfarr",
+            "Saanenkaese", "Saga", "Sage Derby", "Sainte Maure", "Saint-Marcellin",
+            "Saint-Nectaire", "Saint-Paulin", "Salers", "Samso", "San Simon", "Sancerre",
+            "Sap Sago", "Sardo", "Sardo Egyptian", "Sbrinz", "Scamorza", "Schabzieger", "Schloss",
+            "Selles sur Cher", "Selva", "Serat", "Seriously Strong Cheddar", "Serra da Estrela",
+            "Sharpam", "Shelburne Cheddar", "Shropshire Blue", "Siraz", "Sirene", "Smoked Gouda",
+            "Somerset Brie", "Sonoma Jack", "Sottocenare al Tartufo", "Soumaintrain",
+            "Sourire Lozerien", "Spenwood", "Sraffordshire Organic", "St. Agur Blue Cheese",
+            "Stilton", "Stinking Bishop", "String", "Sussex Slipcote", "Sveciaost", "Swaledale",
+            "Sweet Style Swiss", "Swiss", "Syrian (Armenian String)", "Tala", "Taleggio", "Tamie",
+            "Tasmania Highland Chevre Log", "Taupiniere", "Teifi", "Telemea", "Testouri",
+            "Tete de Moine", "Tetilla", "Texas Goat Cheese", "Tibet", "Tillamook Cheddar",
+            "Tilsit", "Timboon Brie", "Toma", "Tomme Brulee", "Tomme d'Abondance",
+            "Tomme de Chevre", "Tomme de Romans", "Tomme de Savoie", "Tomme des Chouans", "Tommes",
+            "Torta del Casar", "Toscanello", "Touree de L'Aubier", "Tourmalet",
+            "Trappe (Veritable)", "Trois Cornes De Vendee", "Tronchon", "Trou du Cru", "Truffe",
+            "Tupi", "Turunmaa", "Tymsboro", "Tyn Grug", "Tyning", "Ubriaco", "Ulloa",
+            "Vacherin-Fribourgeois", "Valencay", "Vasterbottenost", "Venaco", "Vendomois",
+            "Vieux Corse", "Vignotte", "Vulscombe", "Waimata Farmhouse Blue",
+            "Washed Rind Cheese (Australian)", "Waterloo", "Weichkaese", "Wellington",
+            "Wensleydale", "White Stilton", "Whitestone Farmhouse", "Wigmore", "Woodside Cabecou",
+            "Xanadu", "Xynotyro", "Yarg Cornish", "Yarra Valley Pyramid", "Yorkshire Blue",
+            "Zamorano", "Zanetti Grana Padano", "Zanetti Parmigiano Reggiano"
+    };
+
+}
diff --git a/samples/devbytes/animation/ListViewItemAnimations/src/com/example/android/listviewitemanimations/ListViewItemAnimations.java b/samples/devbytes/animation/ListViewItemAnimations/src/com/example/android/listviewitemanimations/ListViewItemAnimations.java
new file mode 100644
index 0000000..68a7651
--- /dev/null
+++ b/samples/devbytes/animation/ListViewItemAnimations/src/com/example/android/listviewitemanimations/ListViewItemAnimations.java
@@ -0,0 +1,402 @@
+/*
+ * Copyright (C) 2013 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.listviewitemanimations;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewTreeObserver;
+import android.view.animation.AlphaAnimation;
+import android.view.animation.Animation;
+import android.view.animation.Animation.AnimationListener;
+import android.view.animation.AnimationSet;
+import android.view.animation.TranslateAnimation;
+import android.widget.ListView;
+
+/**
+ * This example shows how to use a swipe effect to remove items from a ListView,
+ * and how to use animations to complete the swipe as well as to animate the other
+ * items in the list into their final places. This code works on runtimes back to Gingerbread
+ * (Android 2.3), by using the android.view.animation classes on earlier releases.
+ *
+ * Watch the associated video for this demo on the DevBytes channel of developer.android.com
+ * or on the DevBytes playlist in the androiddevelopers channel on YouTube at
+ * https://www.youtube.com/playlist?list=PLWz5rJ2EKKc_XOgcRukSoKKjewFJZrKV0.
+ */
+public class ListViewItemAnimations extends Activity {
+
+    final ArrayList<View> mCheckedViews = new ArrayList<View>();
+    StableArrayAdapter mAdapter;
+    ListView mListView;
+    BackgroundContainer mBackgroundContainer;
+    boolean mSwiping = false;
+    boolean mItemPressed = false;
+    HashMap<Long, Integer> mItemIdTopMap = new HashMap<Long, Integer>();
+    boolean mAnimating = false;
+    float mCurrentX = 0;
+    float mCurrentAlpha = 1;
+
+    private static final int SWIPE_DURATION = 250;
+    private static final int MOVE_DURATION = 150;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_list_view_item_animations);
+        
+        mBackgroundContainer = (BackgroundContainer) findViewById(R.id.listViewBackground);
+        mListView = (ListView) findViewById(R.id.listview);
+        final ArrayList<String> cheeseList = new ArrayList<String>();
+        for (int i = 0; i < Cheeses.sCheeseStrings.length; ++i) {
+            cheeseList.add(Cheeses.sCheeseStrings[i]);
+        }
+        mAdapter = new StableArrayAdapter(this,R.layout.opaque_text_view, cheeseList,
+                mTouchListener);
+        mListView.setAdapter(mAdapter);
+    }
+    
+    /**
+     * Returns true if the current runtime is Honeycomb or later
+     */
+    private boolean isRuntimePostGingerbread() {
+        return android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB;
+    }
+
+    private View.OnTouchListener mTouchListener = new View.OnTouchListener() {
+        
+        float mDownX;
+        private int mSwipeSlop = -1;
+        
+        @SuppressLint("NewApi")
+        @Override
+        public boolean onTouch(final View v, MotionEvent event) {
+            if (mSwipeSlop < 0) {
+                mSwipeSlop = ViewConfiguration.get(ListViewItemAnimations.this).
+                        getScaledTouchSlop();
+            }
+            switch (event.getAction()) {
+            case MotionEvent.ACTION_DOWN:
+                if (mAnimating) {
+                    // Multi-item swipes not handled
+                    return true;
+                }
+                mItemPressed = true;
+                mDownX = event.getX();
+                break;
+            case MotionEvent.ACTION_CANCEL:
+                setSwipePosition(v, 0);
+                mItemPressed = false;
+                break;
+            case MotionEvent.ACTION_MOVE:
+                {
+                    if (mAnimating) {
+                        return true;
+                    }
+                    float x = event.getX();
+                    if (isRuntimePostGingerbread()) {
+                        x += v.getTranslationX();
+                    }
+                    float deltaX = x - mDownX;
+                    float deltaXAbs = Math.abs(deltaX);
+                    if (!mSwiping) {
+                        if (deltaXAbs > mSwipeSlop) {
+                            mSwiping = true;
+                            mListView.requestDisallowInterceptTouchEvent(true);
+                            mBackgroundContainer.showBackground(v.getTop(), v.getHeight());
+                        }
+                    }
+                    if (mSwiping) {
+                        setSwipePosition(v, deltaX);
+                    }
+                }
+                break;
+            case MotionEvent.ACTION_UP:
+                {
+                    if (mAnimating) {
+                        return true;
+                    }
+                    // User let go - figure out whether to animate the view out, or back into place
+                    if (mSwiping) {
+                        float x = event.getX();
+                        if (isRuntimePostGingerbread()) {
+                            x += v.getTranslationX();
+                        }
+                        float deltaX = x - mDownX;
+                        float deltaXAbs = Math.abs(deltaX);
+                        float fractionCovered;
+                        float endX;
+                        final boolean remove;
+                        if (deltaXAbs > v.getWidth() / 4) {
+                            // Greater than a quarter of the width - animate it out
+                            fractionCovered = deltaXAbs / v.getWidth();
+                            endX = deltaX < 0 ? -v.getWidth() : v.getWidth();
+                            remove = true;
+                        } else {
+                            // Not far enough - animate it back
+                            fractionCovered = 1 - (deltaXAbs / v.getWidth());
+                            endX = 0;
+                            remove = false;
+                        }
+                        // Animate position and alpha
+                        long duration = (int) ((1 - fractionCovered) * SWIPE_DURATION);
+                        animateSwipe(v, endX, duration, remove);
+                    } else {
+                        mItemPressed = false;
+                    }
+                }
+                break;
+            default: 
+                return false;
+            }
+            return true;
+        }
+    };
+
+    /**
+     * Animates a swipe of the item either back into place or out of the listview container.
+     * NOTE: This is a simplified version of swipe behavior, for the purposes of this demo
+     * about animation. A real version should use velocity (via the VelocityTracker class)
+     * to send the item off or back at an appropriate speed.
+     */
+    @SuppressLint("NewApi")
+    private void animateSwipe(final View view, float endX, long duration, final boolean remove) {
+        mAnimating = true;
+        mListView.setEnabled(false);
+        if (isRuntimePostGingerbread()) {
+            view.animate().setDuration(duration).
+                    alpha(remove ? 0 : 1).translationX(endX).
+                    setListener(new AnimatorListenerAdapter() {
+                        @Override
+                        public void onAnimationEnd(Animator animation) {
+                            // Restore animated values
+                            view.setAlpha(1);
+                            view.setTranslationX(0);
+                            if (remove) {
+                                animateOtherViews(mListView, view);
+                            } else {
+                                mBackgroundContainer.hideBackground();
+                                mSwiping = false;
+                                mAnimating = false;
+                                mListView.setEnabled(true);
+                            }
+                            mItemPressed = false;
+                        }
+                    });
+        } else {
+            TranslateAnimation swipeAnim = new TranslateAnimation(mCurrentX, endX, 0, 0);
+            AlphaAnimation alphaAnim = new AlphaAnimation(mCurrentAlpha, remove ? 0 : 1);
+            AnimationSet set = new AnimationSet(true);
+            set.addAnimation(swipeAnim);
+            set.addAnimation(alphaAnim);
+            set.setDuration(duration);
+            view.startAnimation(set);
+            setAnimationEndAction(set, new Runnable() {
+                @Override
+                public void run() {
+                    if (remove) {
+                        animateOtherViews(mListView, view);
+                    } else {
+                        mBackgroundContainer.hideBackground();
+                        mSwiping = false;
+                        mAnimating = false;
+                        mListView.setEnabled(true);
+                    }
+                    mItemPressed = false;
+                }
+            });
+        }
+            
+    }
+        
+    /**
+     * Sets the horizontal position and translucency of the view being swiped.
+     */
+    @SuppressLint("NewApi")
+    private void setSwipePosition(View view, float deltaX) {
+        float fraction = Math.abs(deltaX) / view.getWidth();
+        if (isRuntimePostGingerbread()) {
+            view.setTranslationX(deltaX);
+            view.setAlpha(1 - fraction);
+        } else {
+            // Hello, Gingerbread!
+            TranslateAnimation swipeAnim = new TranslateAnimation(deltaX, deltaX, 0, 0);
+            mCurrentX = deltaX;
+            mCurrentAlpha = (1 - fraction);
+            AlphaAnimation alphaAnim = new AlphaAnimation(mCurrentAlpha, mCurrentAlpha);
+            AnimationSet set = new AnimationSet(true);
+            set.addAnimation(swipeAnim);
+            set.addAnimation(alphaAnim);
+            set.setFillAfter(true);
+            set.setFillEnabled(true);
+            view.startAnimation(set);
+        }
+    }
+
+    /**
+     * This method animates all other views in the ListView container (not including ignoreView)
+     * into their final positions. It is called after ignoreView has been removed from the
+     * adapter, but before layout has been run. The approach here is to figure out where
+     * everything is now, then allow layout to run, then figure out where everything is after
+     * layout, and then to run animations between all of those start/end positions.
+     */
+    private void animateOtherViews(final ListView listview, View viewToRemove) {
+        int firstVisiblePosition = listview.getFirstVisiblePosition();
+        for (int i = 0; i < listview.getChildCount(); ++i) {
+            View child = listview.getChildAt(i);
+            int position = firstVisiblePosition + i;
+            long itemId = mAdapter.getItemId(position);
+            if (child != viewToRemove) {
+                mItemIdTopMap.put(itemId, child.getTop());
+            }
+        }
+        // Delete the item from the adapter
+        int position = mListView.getPositionForView(viewToRemove);
+        mAdapter.remove(mAdapter.getItem(position));
+        
+        // After layout runs, capture position of all itemIDs, compare to pre-layout
+        // positions, and animate changes
+        final ViewTreeObserver observer = listview.getViewTreeObserver();
+        observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+            public boolean onPreDraw() {
+                observer.removeOnPreDrawListener(this);
+                boolean firstAnimation = true;
+                int firstVisiblePosition = listview.getFirstVisiblePosition();
+                for (int i = 0; i < listview.getChildCount(); ++i) {
+                    final View child = listview.getChildAt(i);
+                    int position = firstVisiblePosition + i;
+                    long itemId = mAdapter.getItemId(position);
+                    Integer startTop = mItemIdTopMap.get(itemId);
+                    int top = child.getTop();
+                    if (startTop == null) {
+                        // Animate new views along with the others. The catch is that they did not
+                        // exist in the start state, so we must calculate their starting position
+                        // based on whether they're coming in from the bottom (i > 0) or top.
+                        int childHeight = child.getHeight() + listview.getDividerHeight();
+                        startTop = top + (i > 0 ? childHeight : -childHeight);
+                    }
+                    int delta = startTop - top;
+                    if (delta != 0) {
+                        Runnable endAction = firstAnimation ?
+                            new Runnable() {
+                                public void run() {
+                                    mBackgroundContainer.hideBackground();
+                                    mSwiping = false;
+                                    mAnimating = false;
+                                    mListView.setEnabled(true);
+                                }
+                            } :
+                            null;
+                        firstAnimation = false;
+                        moveView(child, 0, 0, delta, 0, endAction);
+                    }
+                }
+                mItemIdTopMap.clear();
+                return true;
+            }
+        });
+    }
+    
+    /**
+     * Animate a view between start and end X/Y locations, using either old (pre-3.0) or
+     * new animation APIs.
+     */
+    @SuppressLint("NewApi")
+    private void moveView(View view, float startX, float endX, float startY, float endY,
+            Runnable endAction) {
+        final Runnable finalEndAction = endAction;
+        if (isRuntimePostGingerbread()) {
+            view.animate().setDuration(MOVE_DURATION);
+            if (startX != endX) {
+                ObjectAnimator anim = ObjectAnimator.ofFloat(view, View.TRANSLATION_X, startX, endX);
+                anim.setDuration(MOVE_DURATION);
+                anim.start();
+                setAnimatorEndAction(anim, endAction);
+                endAction = null;
+            }
+            if (startY != endY) {
+                ObjectAnimator anim = ObjectAnimator.ofFloat(view, View.TRANSLATION_Y, startY, endY);
+                anim.setDuration(MOVE_DURATION);
+                anim.start();
+                setAnimatorEndAction(anim, endAction);
+            }
+        } else {
+            TranslateAnimation translator = new TranslateAnimation(startX, endX, startY, endY);
+            translator.setDuration(MOVE_DURATION);
+            view.startAnimation(translator);
+            if (endAction != null) {
+                view.getAnimation().setAnimationListener(new AnimationListenerAdapter() {
+                    @Override
+                    public void onAnimationEnd(Animation animation) {
+                        finalEndAction.run();
+                    }
+                });
+            }
+        }
+    }
+    
+    @SuppressLint("NewApi")
+    private void setAnimatorEndAction(Animator animator, final Runnable endAction) {
+        if (endAction != null) {
+            animator.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    endAction.run();
+                }
+            });
+        }
+    }
+
+    private void setAnimationEndAction(Animation animation, final Runnable endAction) {
+        if (endAction != null) {
+            animation.setAnimationListener(new AnimationListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animation animation) {
+                    endAction.run();
+                }
+            });
+        }
+    }
+
+    /**
+     * Utility, to avoid having to implement every method in AnimationListener in
+     * every implementation class
+     */
+    static class AnimationListenerAdapter implements AnimationListener {
+
+        @Override
+        public void onAnimationEnd(Animation animation) {
+        }
+
+        @Override
+        public void onAnimationRepeat(Animation animation) {
+        }
+
+        @Override
+        public void onAnimationStart(Animation animation) {
+        }
+    }
+
+}
diff --git a/samples/devbytes/animation/ListViewItemAnimations/src/com/example/android/listviewitemanimations/StableArrayAdapter.java b/samples/devbytes/animation/ListViewItemAnimations/src/com/example/android/listviewitemanimations/StableArrayAdapter.java
new file mode 100644
index 0000000..4bddc5e
--- /dev/null
+++ b/samples/devbytes/animation/ListViewItemAnimations/src/com/example/android/listviewitemanimations/StableArrayAdapter.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2013 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.listviewitemanimations;
+
+import java.util.HashMap;
+import java.util.List;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+
+public class StableArrayAdapter extends ArrayAdapter<String> {
+
+    HashMap<String, Integer> mIdMap = new HashMap<String, Integer>();
+    View.OnTouchListener mTouchListener;
+
+    public StableArrayAdapter(Context context, int textViewResourceId,
+            List<String> objects, View.OnTouchListener listener) {
+        super(context, textViewResourceId, objects);
+        mTouchListener = listener;
+        for (int i = 0; i < objects.size(); ++i) {
+            mIdMap.put(objects.get(i), i);
+        }
+    }
+
+    @Override
+    public long getItemId(int position) {
+        String item = getItem(position);
+        return mIdMap.get(item);
+    }
+
+    @Override
+    public boolean hasStableIds() {
+        return true;
+    }
+
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent) {
+        View view = super.getView(position, convertView, parent);
+        if (view != convertView) {
+            // Add touch listener to every new view to track swipe motion
+            view.setOnTouchListener(mTouchListener);
+        }
+        return view;
+    }
+
+}
diff --git a/samples/devbytes/animation/ListViewRemovalAnimation/AndroidManifest.xml b/samples/devbytes/animation/ListViewRemovalAnimation/AndroidManifest.xml
new file mode 100644
index 0000000..f030747
--- /dev/null
+++ b/samples/devbytes/animation/ListViewRemovalAnimation/AndroidManifest.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.android.listviewremovalanimation"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk
+        android:minSdkVersion="16"
+        android:targetSdkVersion="16" />
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/ic_launcher"
+        android:label="@string/app_name"
+        android:theme="@style/AppTheme" >
+        <activity
+            android:theme="@style/WithoutBackground"
+            android:name="com.example.android.listviewremovalanimation.ListViewRemovalAnimation"
+            android:label="@string/app_name" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest>
diff --git a/samples/devbytes/animation/ListViewRemovalAnimation/res/drawable-hdpi/ic_launcher.png b/samples/devbytes/animation/ListViewRemovalAnimation/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..96a442e
--- /dev/null
+++ b/samples/devbytes/animation/ListViewRemovalAnimation/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/ListViewRemovalAnimation/res/drawable-mdpi/ic_launcher.png b/samples/devbytes/animation/ListViewRemovalAnimation/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..359047d
--- /dev/null
+++ b/samples/devbytes/animation/ListViewRemovalAnimation/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/ListViewRemovalAnimation/res/drawable-xhdpi/ic_launcher.png b/samples/devbytes/animation/ListViewRemovalAnimation/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..71c6d76
--- /dev/null
+++ b/samples/devbytes/animation/ListViewRemovalAnimation/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/ListViewRemovalAnimation/res/drawable-xhdpi/shadowed_background.9.png b/samples/devbytes/animation/ListViewRemovalAnimation/res/drawable-xhdpi/shadowed_background.9.png
new file mode 100644
index 0000000..f905bbc
--- /dev/null
+++ b/samples/devbytes/animation/ListViewRemovalAnimation/res/drawable-xhdpi/shadowed_background.9.png
Binary files differ
diff --git a/samples/devbytes/animation/ListViewRemovalAnimation/res/drawable-xhdpi/tv_background_with_divider.9.png b/samples/devbytes/animation/ListViewRemovalAnimation/res/drawable-xhdpi/tv_background_with_divider.9.png
new file mode 100644
index 0000000..e6e3cd5
--- /dev/null
+++ b/samples/devbytes/animation/ListViewRemovalAnimation/res/drawable-xhdpi/tv_background_with_divider.9.png
Binary files differ
diff --git a/samples/devbytes/animation/ListViewRemovalAnimation/res/layout/activity_list_view_deletion.xml b/samples/devbytes/animation/ListViewRemovalAnimation/res/layout/activity_list_view_deletion.xml
new file mode 100644
index 0000000..26aa123
--- /dev/null
+++ b/samples/devbytes/animation/ListViewRemovalAnimation/res/layout/activity_list_view_deletion.xml
@@ -0,0 +1,37 @@
+<!-- Copyright (C) 2013 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"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context=".ListViewAnimations" >
+
+    <view
+        class="com.example.android.listviewremovalanimation.BackgroundContainer"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:id="@+id/listViewBackground">
+
+        <ListView
+            android:id="@+id/listview"
+            android:divider="@null"
+            android:dividerHeight="0dp"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content" />
+
+    </view>
+
+</LinearLayout>
diff --git a/samples/devbytes/animation/ListViewRemovalAnimation/res/layout/opaque_text_view.xml b/samples/devbytes/animation/ListViewRemovalAnimation/res/layout/opaque_text_view.xml
new file mode 100644
index 0000000..c37f62d
--- /dev/null
+++ b/samples/devbytes/animation/ListViewRemovalAnimation/res/layout/opaque_text_view.xml
@@ -0,0 +1,24 @@
+<!-- Copyright (C) 2013 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.
+-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:background="@drawable/tv_background_with_divider"
+    android:textAppearance="?android:attr/textAppearanceListItemSmall"
+    android:gravity="center_vertical"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+    android:minHeight="?android:attr/listPreferredItemHeightSmall"
+/>
diff --git a/samples/devbytes/animation/ListViewRemovalAnimation/res/values-v11/styles.xml b/samples/devbytes/animation/ListViewRemovalAnimation/res/values-v11/styles.xml
new file mode 100644
index 0000000..139d283
--- /dev/null
+++ b/samples/devbytes/animation/ListViewRemovalAnimation/res/values-v11/styles.xml
@@ -0,0 +1,25 @@
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <!--
+        Base application theme for API 11+. This theme completely replaces
+        AppBaseTheme from res/values/styles.xml on API 11+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+        <!-- API 11 theme customizations can go here. -->
+    </style>
+
+</resources>
diff --git a/samples/devbytes/animation/ListViewRemovalAnimation/res/values-v14/styles.xml b/samples/devbytes/animation/ListViewRemovalAnimation/res/values-v14/styles.xml
new file mode 100644
index 0000000..8ac4522
--- /dev/null
+++ b/samples/devbytes/animation/ListViewRemovalAnimation/res/values-v14/styles.xml
@@ -0,0 +1,26 @@
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <!--
+        Base application theme for API 14+. This theme completely replaces
+        AppBaseTheme from BOTH res/values/styles.xml and
+        res/values-v11/styles.xml on API 14+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+        <!-- API 14 theme customizations can go here. -->
+    </style>
+
+</resources>
diff --git a/samples/devbytes/animation/ListViewRemovalAnimation/res/values/strings.xml b/samples/devbytes/animation/ListViewRemovalAnimation/res/values/strings.xml
new file mode 100644
index 0000000..7125618
--- /dev/null
+++ b/samples/devbytes/animation/ListViewRemovalAnimation/res/values/strings.xml
@@ -0,0 +1,21 @@
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <string name="app_name">ListViewRemovalAnimation</string>
+    <string name="use_positions">Use Positions</string>
+    <string name="delete_selected">Delete Selected</string>
+
+</resources>
diff --git a/samples/devbytes/animation/ListViewRemovalAnimation/res/values/styles.xml b/samples/devbytes/animation/ListViewRemovalAnimation/res/values/styles.xml
new file mode 100644
index 0000000..c7f2e79
--- /dev/null
+++ b/samples/devbytes/animation/ListViewRemovalAnimation/res/values/styles.xml
@@ -0,0 +1,37 @@
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <!--
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Light">
+        <!--
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        -->
+    </style>
+
+    <!-- Application theme. -->
+    <style name="AppTheme" parent="AppBaseTheme">
+        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+    </style>
+
+    <style name="WithoutBackground" parent="AppTheme">
+        <item name="android:windowBackground">@null</item>
+    </style>
+</resources>
diff --git a/samples/devbytes/animation/ListViewRemovalAnimation/src/com/example/android/listviewremovalanimation/BackgroundContainer.java b/samples/devbytes/animation/ListViewRemovalAnimation/src/com/example/android/listviewremovalanimation/BackgroundContainer.java
new file mode 100644
index 0000000..1d0e806
--- /dev/null
+++ b/samples/devbytes/animation/ListViewRemovalAnimation/src/com/example/android/listviewremovalanimation/BackgroundContainer.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2013 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.listviewremovalanimation;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.widget.FrameLayout;
+
+public class BackgroundContainer extends FrameLayout {
+
+    boolean mShowing = false;
+    Drawable mShadowedBackground;
+    int mOpenAreaTop, mOpenAreaBottom, mOpenAreaHeight;
+    boolean mUpdateBounds = false;
+    
+    public BackgroundContainer(Context context) {
+        super(context);
+        init();
+    }
+
+    public BackgroundContainer(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init();
+    }
+
+    public BackgroundContainer(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        init();
+    }
+
+    private void init() {
+        mShadowedBackground =
+                getContext().getResources().getDrawable(R.drawable.shadowed_background);
+    }
+
+    public void showBackground(int top, int bottom) {
+        setWillNotDraw(false);
+        mOpenAreaTop = top;
+        mOpenAreaHeight = bottom;
+        mShowing = true;
+        mUpdateBounds = true;
+    }
+    
+    public void hideBackground() {
+        setWillNotDraw(true);
+        mShowing = false;
+    }
+    
+    @Override
+    protected void onDraw(Canvas canvas) {
+        if (mShowing) {
+            	if (mUpdateBounds) {
+                mShadowedBackground.setBounds(0, 0, getWidth(), mOpenAreaHeight);
+            	}
+            canvas.save();
+            canvas.translate(0, mOpenAreaTop);
+            mShadowedBackground.draw(canvas);
+            canvas.restore();
+        }
+    }
+
+}
diff --git a/samples/devbytes/animation/ListViewRemovalAnimation/src/com/example/android/listviewremovalanimation/Cheeses.java b/samples/devbytes/animation/ListViewRemovalAnimation/src/com/example/android/listviewremovalanimation/Cheeses.java
new file mode 100644
index 0000000..4f4b88b
--- /dev/null
+++ b/samples/devbytes/animation/ListViewRemovalAnimation/src/com/example/android/listviewremovalanimation/Cheeses.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2013 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.listviewremovalanimation;
+
+public class Cheeses {
+
+    public static final String[] sCheeseStrings = {
+            "Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi",
+            "Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu", "Airag", "Airedale",
+            "Aisy Cendre", "Allgauer Emmentaler", "Alverca", "Ambert", "American Cheese",
+            "Ami du Chambertin", "Anejo Enchilado", "Anneau du Vic-Bilh", "Anthoriro", "Appenzell",
+            "Aragon", "Ardi Gasna", "Ardrahan", "Armenian String", "Aromes au Gene de Marc",
+            "Asadero", "Asiago", "Aubisque Pyrenees", "Autun", "Avaxtskyr", "Baby Swiss",
+            "Babybel", "Baguette Laonnaise", "Bakers", "Baladi", "Balaton", "Bandal", "Banon",
+            "Barry's Bay Cheddar", "Basing", "Basket Cheese", "Bath Cheese", "Bavarian Bergkase",
+            "Baylough", "Beaufort", "Beauvoorde", "Beenleigh Blue", "Beer Cheese", "Bel Paese",
+            "Bergader", "Bergere Bleue", "Berkswell", "Beyaz Peynir", "Bierkase", "Bishop Kennedy",
+            "Blarney", "Bleu d'Auvergne", "Bleu de Gex", "Bleu de Laqueuille",
+            "Bleu de Septmoncel", "Bleu Des Causses", "Blue", "Blue Castello", "Blue Rathgore",
+            "Blue Vein (Australian)", "Blue Vein Cheeses", "Bocconcini", "Bocconcini (Australian)",
+            "Boeren Leidenkaas", "Bonchester", "Bosworth", "Bougon", "Boule Du Roves",
+            "Boulette d'Avesnes", "Boursault", "Boursin", "Bouyssou", "Bra", "Braudostur",
+            "Breakfast Cheese", "Brebis du Lavort", "Brebis du Lochois", "Brebis du Puyfaucon",
+            "Bresse Bleu", "Brick", "Brie", "Brie de Meaux", "Brie de Melun", "Brillat-Savarin",
+            "Brin", "Brin d' Amour", "Brin d'Amour", "Brinza (Burduf Brinza)",
+            "Briquette de Brebis", "Briquette du Forez", "Broccio", "Broccio Demi-Affine",
+            "Brousse du Rove", "Bruder Basil", "Brusselae Kaas (Fromage de Bruxelles)", "Bryndza",
+            "Buchette d'Anjou", "Buffalo", "Burgos", "Butte", "Butterkase", "Button (Innes)",
+            "Buxton Blue", "Cabecou", "Caboc", "Cabrales", "Cachaille", "Caciocavallo", "Caciotta",
+            "Caerphilly", "Cairnsmore", "Calenzana", "Cambazola", "Camembert de Normandie",
+            "Canadian Cheddar", "Canestrato", "Cantal", "Caprice des Dieux", "Capricorn Goat",
+            "Capriole Banon", "Carre de l'Est", "Casciotta di Urbino", "Cashel Blue", "Castellano",
+            "Castelleno", "Castelmagno", "Castelo Branco", "Castigliano", "Cathelain",
+            "Celtic Promise", "Cendre d'Olivet", "Cerney", "Chabichou", "Chabichou du Poitou",
+            "Chabis de Gatine", "Chaource", "Charolais", "Chaumes", "Cheddar",
+            "Cheddar Clothbound", "Cheshire", "Chevres", "Chevrotin des Aravis", "Chontaleno",
+            "Civray", "Coeur de Camembert au Calvados", "Coeur de Chevre", "Colby", "Cold Pack",
+            "Comte", "Coolea", "Cooleney", "Coquetdale", "Corleggy", "Cornish Pepper",
+            "Cotherstone", "Cotija", "Cottage Cheese", "Cottage Cheese (Australian)",
+            "Cougar Gold", "Coulommiers", "Coverdale", "Crayeux de Roncq", "Cream Cheese",
+            "Cream Havarti", "Crema Agria", "Crema Mexicana", "Creme Fraiche", "Crescenza",
+            "Croghan", "Crottin de Chavignol", "Crottin du Chavignol", "Crowdie", "Crowley",
+            "Cuajada", "Curd", "Cure Nantais", "Curworthy", "Cwmtawe Pecorino",
+            "Cypress Grove Chevre", "Danablu (Danish Blue)", "Danbo", "Danish Fontina",
+            "Daralagjazsky", "Dauphin", "Delice des Fiouves", "Denhany Dorset Drum", "Derby",
+            "Dessertnyj Belyj", "Devon Blue", "Devon Garland", "Dolcelatte", "Doolin",
+            "Doppelrhamstufel", "Dorset Blue Vinney", "Double Gloucester", "Double Worcester",
+            "Dreux a la Feuille", "Dry Jack", "Duddleswell", "Dunbarra", "Dunlop", "Dunsyre Blue",
+            "Duroblando", "Durrus", "Dutch Mimolette (Commissiekaas)", "Edam", "Edelpilz",
+            "Emental Grand Cru", "Emlett", "Emmental", "Epoisses de Bourgogne", "Esbareich",
+            "Esrom", "Etorki", "Evansdale Farmhouse Brie", "Evora De L'Alentejo", "Exmoor Blue",
+            "Explorateur", "Feta", "Feta (Australian)", "Figue", "Filetta", "Fin-de-Siecle",
+            "Finlandia Swiss", "Finn", "Fiore Sardo", "Fleur du Maquis", "Flor de Guia",
+            "Flower Marie", "Folded", "Folded cheese with mint", "Fondant de Brebis",
+            "Fontainebleau", "Fontal", "Fontina Val d'Aosta", "Formaggio di capra", "Fougerus",
+            "Four Herb Gouda", "Fourme d' Ambert", "Fourme de Haute Loire", "Fourme de Montbrison",
+            "Fresh Jack", "Fresh Mozzarella", "Fresh Ricotta", "Fresh Truffles", "Fribourgeois",
+            "Friesekaas", "Friesian", "Friesla", "Frinault", "Fromage a Raclette", "Fromage Corse",
+            "Fromage de Montagne de Savoie", "Fromage Frais", "Fruit Cream Cheese",
+            "Frying Cheese", "Fynbo", "Gabriel", "Galette du Paludier", "Galette Lyonnaise",
+            "Galloway Goat's Milk Gems", "Gammelost", "Gaperon a l'Ail", "Garrotxa", "Gastanberra",
+            "Geitost", "Gippsland Blue", "Gjetost", "Gloucester", "Golden Cross", "Gorgonzola",
+            "Gornyaltajski", "Gospel Green", "Gouda", "Goutu", "Gowrie", "Grabetto", "Graddost",
+            "Grafton Village Cheddar", "Grana", "Grana Padano", "Grand Vatel",
+            "Grataron d' Areches", "Gratte-Paille", "Graviera", "Greuilh", "Greve",
+            "Gris de Lille", "Gruyere", "Gubbeen", "Guerbigny", "Halloumi",
+            "Halloumy (Australian)", "Haloumi-Style Cheese", "Harbourne Blue", "Havarti",
+            "Heidi Gruyere", "Hereford Hop", "Herrgardsost", "Herriot Farmhouse", "Herve",
+            "Hipi Iti", "Hubbardston Blue Cow", "Hushallsost", "Iberico", "Idaho Goatster",
+            "Idiazabal", "Il Boschetto al Tartufo", "Ile d'Yeu", "Isle of Mull", "Jarlsberg",
+            "Jermi Tortes", "Jibneh Arabieh", "Jindi Brie", "Jubilee Blue", "Juustoleipa",
+            "Kadchgall", "Kaseri", "Kashta", "Kefalotyri", "Kenafa", "Kernhem", "Kervella Affine",
+            "Kikorangi", "King Island Cape Wickham Brie", "King River Gold", "Klosterkaese",
+            "Knockalara", "Kugelkase", "L'Aveyronnais", "L'Ecir de l'Aubrac", "La Taupiniere",
+            "La Vache Qui Rit", "Laguiole", "Lairobell", "Lajta", "Lanark Blue", "Lancashire",
+            "Langres", "Lappi", "Laruns", "Lavistown", "Le Brin", "Le Fium Orbo", "Le Lacandou",
+            "Le Roule", "Leafield", "Lebbene", "Leerdammer", "Leicester", "Leyden", "Limburger",
+            "Lincolnshire Poacher", "Lingot Saint Bousquet d'Orb", "Liptauer", "Little Rydings",
+            "Livarot", "Llanboidy", "Llanglofan Farmhouse", "Loch Arthur Farmhouse",
+            "Loddiswell Avondale", "Longhorn", "Lou Palou", "Lou Pevre", "Lyonnais", "Maasdam",
+            "Macconais", "Mahoe Aged Gouda", "Mahon", "Malvern", "Mamirolle", "Manchego",
+            "Manouri", "Manur", "Marble Cheddar", "Marbled Cheeses", "Maredsous", "Margotin",
+            "Maribo", "Maroilles", "Mascares", "Mascarpone", "Mascarpone (Australian)",
+            "Mascarpone Torta", "Matocq", "Maytag Blue", "Meira", "Menallack Farmhouse",
+            "Menonita", "Meredith Blue", "Mesost", "Metton (Cancoillotte)", "Meyer Vintage Gouda",
+            "Mihalic Peynir", "Milleens", "Mimolette", "Mine-Gabhar", "Mini Baby Bells", "Mixte",
+            "Molbo", "Monastery Cheeses", "Mondseer", "Mont D'or Lyonnais", "Montasio",
+            "Monterey Jack", "Monterey Jack Dry", "Morbier", "Morbier Cru de Montagne",
+            "Mothais a la Feuille", "Mozzarella", "Mozzarella (Australian)",
+            "Mozzarella di Bufala", "Mozzarella Fresh, in water", "Mozzarella Rolls", "Munster",
+            "Murol", "Mycella", "Myzithra", "Naboulsi", "Nantais", "Neufchatel",
+            "Neufchatel (Australian)", "Niolo", "Nokkelost", "Northumberland", "Oaxaca",
+            "Olde York", "Olivet au Foin", "Olivet Bleu", "Olivet Cendre",
+            "Orkney Extra Mature Cheddar", "Orla", "Oschtjepka", "Ossau Fermier", "Ossau-Iraty",
+            "Oszczypek", "Oxford Blue", "P'tit Berrichon", "Palet de Babligny", "Paneer", "Panela",
+            "Pannerone", "Pant ys Gawn", "Parmesan (Parmigiano)", "Parmigiano Reggiano",
+            "Pas de l'Escalette", "Passendale", "Pasteurized Processed", "Pate de Fromage",
+            "Patefine Fort", "Pave d'Affinois", "Pave d'Auge", "Pave de Chirac", "Pave du Berry",
+            "Pecorino", "Pecorino in Walnut Leaves", "Pecorino Romano", "Peekskill Pyramid",
+            "Pelardon des Cevennes", "Pelardon des Corbieres", "Penamellera", "Penbryn",
+            "Pencarreg", "Perail de Brebis", "Petit Morin", "Petit Pardou", "Petit-Suisse",
+            "Picodon de Chevre", "Picos de Europa", "Piora", "Pithtviers au Foin",
+            "Plateau de Herve", "Plymouth Cheese", "Podhalanski", "Poivre d'Ane", "Polkolbin",
+            "Pont l'Eveque", "Port Nicholson", "Port-Salut", "Postel", "Pouligny-Saint-Pierre",
+            "Pourly", "Prastost", "Pressato", "Prince-Jean", "Processed Cheddar", "Provolone",
+            "Provolone (Australian)", "Pyengana Cheddar", "Pyramide", "Quark",
+            "Quark (Australian)", "Quartirolo Lombardo", "Quatre-Vents", "Quercy Petit",
+            "Queso Blanco", "Queso Blanco con Frutas --Pina y Mango", "Queso de Murcia",
+            "Queso del Montsec", "Queso del Tietar", "Queso Fresco", "Queso Fresco (Adobera)",
+            "Queso Iberico", "Queso Jalapeno", "Queso Majorero", "Queso Media Luna",
+            "Queso Para Frier", "Queso Quesadilla", "Rabacal", "Raclette", "Ragusano", "Raschera",
+            "Reblochon", "Red Leicester", "Regal de la Dombes", "Reggianito", "Remedou",
+            "Requeson", "Richelieu", "Ricotta", "Ricotta (Australian)", "Ricotta Salata", "Ridder",
+            "Rigotte", "Rocamadour", "Rollot", "Romano", "Romans Part Dieu", "Roncal", "Roquefort",
+            "Roule", "Rouleau De Beaulieu", "Royalp Tilsit", "Rubens", "Rustinu", "Saaland Pfarr",
+            "Saanenkaese", "Saga", "Sage Derby", "Sainte Maure", "Saint-Marcellin",
+            "Saint-Nectaire", "Saint-Paulin", "Salers", "Samso", "San Simon", "Sancerre",
+            "Sap Sago", "Sardo", "Sardo Egyptian", "Sbrinz", "Scamorza", "Schabzieger", "Schloss",
+            "Selles sur Cher", "Selva", "Serat", "Seriously Strong Cheddar", "Serra da Estrela",
+            "Sharpam", "Shelburne Cheddar", "Shropshire Blue", "Siraz", "Sirene", "Smoked Gouda",
+            "Somerset Brie", "Sonoma Jack", "Sottocenare al Tartufo", "Soumaintrain",
+            "Sourire Lozerien", "Spenwood", "Sraffordshire Organic", "St. Agur Blue Cheese",
+            "Stilton", "Stinking Bishop", "String", "Sussex Slipcote", "Sveciaost", "Swaledale",
+            "Sweet Style Swiss", "Swiss", "Syrian (Armenian String)", "Tala", "Taleggio", "Tamie",
+            "Tasmania Highland Chevre Log", "Taupiniere", "Teifi", "Telemea", "Testouri",
+            "Tete de Moine", "Tetilla", "Texas Goat Cheese", "Tibet", "Tillamook Cheddar",
+            "Tilsit", "Timboon Brie", "Toma", "Tomme Brulee", "Tomme d'Abondance",
+            "Tomme de Chevre", "Tomme de Romans", "Tomme de Savoie", "Tomme des Chouans", "Tommes",
+            "Torta del Casar", "Toscanello", "Touree de L'Aubier", "Tourmalet",
+            "Trappe (Veritable)", "Trois Cornes De Vendee", "Tronchon", "Trou du Cru", "Truffe",
+            "Tupi", "Turunmaa", "Tymsboro", "Tyn Grug", "Tyning", "Ubriaco", "Ulloa",
+            "Vacherin-Fribourgeois", "Valencay", "Vasterbottenost", "Venaco", "Vendomois",
+            "Vieux Corse", "Vignotte", "Vulscombe", "Waimata Farmhouse Blue",
+            "Washed Rind Cheese (Australian)", "Waterloo", "Weichkaese", "Wellington",
+            "Wensleydale", "White Stilton", "Whitestone Farmhouse", "Wigmore", "Woodside Cabecou",
+            "Xanadu", "Xynotyro", "Yarg Cornish", "Yarra Valley Pyramid", "Yorkshire Blue",
+            "Zamorano", "Zanetti Grana Padano", "Zanetti Parmigiano Reggiano"
+    };
+
+}
diff --git a/samples/devbytes/animation/ListViewRemovalAnimation/src/com/example/android/listviewremovalanimation/ListViewRemovalAnimation.java b/samples/devbytes/animation/ListViewRemovalAnimation/src/com/example/android/listviewremovalanimation/ListViewRemovalAnimation.java
new file mode 100644
index 0000000..1e3ee8c
--- /dev/null
+++ b/samples/devbytes/animation/ListViewRemovalAnimation/src/com/example/android/listviewremovalanimation/ListViewRemovalAnimation.java
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2013 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.listviewremovalanimation;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewTreeObserver;
+import android.widget.ListView;
+
+/**
+ * This example shows how to use a swipe effect to remove items from a ListView,
+ * and how to use animations to complete the swipe as well as to animate the other
+ * items in the list into their final places.
+ *
+ * Watch the associated video for this demo on the DevBytes channel of developer.android.com
+ * or on YouTube at https://www.youtube.com/watch?v=NewCSg2JKLk.
+ */
+public class ListViewRemovalAnimation extends Activity {
+
+    StableArrayAdapter mAdapter;
+    ListView mListView;
+    BackgroundContainer mBackgroundContainer;
+    boolean mSwiping = false;
+    boolean mItemPressed = false;
+    HashMap<Long, Integer> mItemIdTopMap = new HashMap<Long, Integer>();
+
+    private static final int SWIPE_DURATION = 250;
+    private static final int MOVE_DURATION = 150;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_list_view_deletion);
+        
+        mBackgroundContainer = (BackgroundContainer) findViewById(R.id.listViewBackground);
+        mListView = (ListView) findViewById(R.id.listview);
+        android.util.Log.d("Debug", "d=" + mListView.getDivider());
+        final ArrayList<String> cheeseList = new ArrayList<String>();
+        for (int i = 0; i < Cheeses.sCheeseStrings.length; ++i) {
+            cheeseList.add(Cheeses.sCheeseStrings[i]);
+        }
+        mAdapter = new StableArrayAdapter(this,R.layout.opaque_text_view, cheeseList,
+                mTouchListener);
+        mListView.setAdapter(mAdapter);
+    }
+
+    /**
+     * Handle touch events to fade/move dragged items as they are swiped out
+     */
+    private View.OnTouchListener mTouchListener = new View.OnTouchListener() {
+        
+        float mDownX;
+        private int mSwipeSlop = -1;
+        
+        @Override
+        public boolean onTouch(final View v, MotionEvent event) {
+            if (mSwipeSlop < 0) {
+                mSwipeSlop = ViewConfiguration.get(ListViewRemovalAnimation.this).
+                        getScaledTouchSlop();
+            }
+            switch (event.getAction()) {
+            case MotionEvent.ACTION_DOWN:
+                if (mItemPressed) {
+                    // Multi-item swipes not handled
+                    return false;
+                }
+                mItemPressed = true;
+                mDownX = event.getX();
+                break;
+            case MotionEvent.ACTION_CANCEL:
+                v.setAlpha(1);
+                v.setTranslationX(0);
+                mItemPressed = false;
+                break;
+            case MotionEvent.ACTION_MOVE:
+                {
+                    float x = event.getX() + v.getTranslationX();
+                    float deltaX = x - mDownX;
+                    float deltaXAbs = Math.abs(deltaX);
+                    if (!mSwiping) {
+                        if (deltaXAbs > mSwipeSlop) {
+                            mSwiping = true;
+                            mListView.requestDisallowInterceptTouchEvent(true);
+                            mBackgroundContainer.showBackground(v.getTop(), v.getHeight());
+                        }
+                    }
+                    if (mSwiping) {
+                        v.setTranslationX((x - mDownX));
+                        v.setAlpha(1 - deltaXAbs / v.getWidth());
+                    }
+                }
+                break;
+            case MotionEvent.ACTION_UP:
+                {
+                    // User let go - figure out whether to animate the view out, or back into place
+                    if (mSwiping) {
+                        float x = event.getX() + v.getTranslationX();
+                        float deltaX = x - mDownX;
+                        float deltaXAbs = Math.abs(deltaX);
+                        float fractionCovered;
+                        float endX;
+                        float endAlpha;
+                        final boolean remove;
+                        if (deltaXAbs > v.getWidth() / 4) {
+                            // Greater than a quarter of the width - animate it out
+                            fractionCovered = deltaXAbs / v.getWidth();
+                            endX = deltaX < 0 ? -v.getWidth() : v.getWidth();
+                            endAlpha = 0;
+                            remove = true;
+                        } else {
+                            // Not far enough - animate it back
+                            fractionCovered = 1 - (deltaXAbs / v.getWidth());
+                            endX = 0;
+                            endAlpha = 1;
+                            remove = false;
+                        }
+                        // Animate position and alpha of swiped item
+                        // NOTE: This is a simplified version of swipe behavior, for the
+                        // purposes of this demo about animation. A real version should use
+                        // velocity (via the VelocityTracker class) to send the item off or
+                        // back at an appropriate speed.
+                        long duration = (int) ((1 - fractionCovered) * SWIPE_DURATION);
+                        mListView.setEnabled(false);
+                        v.animate().setDuration(duration).
+                                alpha(endAlpha).translationX(endX).
+                                withEndAction(new Runnable() {
+                                    @Override
+                                    public void run() {
+                                        // Restore animated values
+                                        v.setAlpha(1);
+                                        v.setTranslationX(0);
+                                        if (remove) {
+                                            animateRemoval(mListView, v);
+                                        } else {
+                                            mBackgroundContainer.hideBackground();
+                                            mSwiping = false;
+                                            mListView.setEnabled(true);
+                                        }
+                                    }
+                                });
+                    }
+                }
+                mItemPressed = false;
+                break;
+            default: 
+                return false;
+            }
+            return true;
+        }
+    };
+
+    /**
+     * This method animates all other views in the ListView container (not including ignoreView)
+     * into their final positions. It is called after ignoreView has been removed from the
+     * adapter, but before layout has been run. The approach here is to figure out where
+     * everything is now, then allow layout to run, then figure out where everything is after
+     * layout, and then to run animations between all of those start/end positions.
+     */
+    private void animateRemoval(final ListView listview, View viewToRemove) {
+        int firstVisiblePosition = listview.getFirstVisiblePosition();
+        for (int i = 0; i < listview.getChildCount(); ++i) {
+            View child = listview.getChildAt(i);
+            if (child != viewToRemove) {
+                int position = firstVisiblePosition + i;
+                long itemId = mAdapter.getItemId(position);
+                mItemIdTopMap.put(itemId, child.getTop());
+            }
+        }
+        // Delete the item from the adapter
+        int position = mListView.getPositionForView(viewToRemove);
+        mAdapter.remove(mAdapter.getItem(position));
+
+        final ViewTreeObserver observer = listview.getViewTreeObserver();
+        observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+            public boolean onPreDraw() {
+                observer.removeOnPreDrawListener(this);
+                boolean firstAnimation = true;
+                int firstVisiblePosition = listview.getFirstVisiblePosition();
+                for (int i = 0; i < listview.getChildCount(); ++i) {
+                    final View child = listview.getChildAt(i);
+                    int position = firstVisiblePosition + i;
+                    long itemId = mAdapter.getItemId(position);
+                    Integer startTop = mItemIdTopMap.get(itemId);
+                    int top = child.getTop();
+                    if (startTop != null) {
+                        if (startTop != top) {
+                            int delta = startTop - top;
+                            child.setTranslationY(delta);
+                            child.animate().setDuration(MOVE_DURATION).translationY(0);
+                            if (firstAnimation) {
+                                child.animate().withEndAction(new Runnable() {
+                                    public void run() {
+                                        mBackgroundContainer.hideBackground();
+                                        mSwiping = false;
+                                        mListView.setEnabled(true);
+                                    }
+                                });
+                                firstAnimation = false;
+                            }
+                        }
+                    } else {
+                        // Animate new views along with the others. The catch is that they did not
+                        // exist in the start state, so we must calculate their starting position
+                        // based on neighboring views.
+                        int childHeight = child.getHeight() + listview.getDividerHeight();
+                        startTop = top + (i > 0 ? childHeight : -childHeight);
+                        int delta = startTop - top;
+                        child.setTranslationY(delta);
+                        child.animate().setDuration(MOVE_DURATION).translationY(0);
+                        if (firstAnimation) {
+                            child.animate().withEndAction(new Runnable() {
+                                public void run() {
+                                    mBackgroundContainer.hideBackground();
+                                    mSwiping = false;
+                                    mListView.setEnabled(true);
+                                }
+                            });
+                            firstAnimation = false;
+                        }
+                    }
+                }
+                mItemIdTopMap.clear();
+                return true;
+            }
+        });
+    }
+
+}
diff --git a/samples/devbytes/animation/ListViewRemovalAnimation/src/com/example/android/listviewremovalanimation/StableArrayAdapter.java b/samples/devbytes/animation/ListViewRemovalAnimation/src/com/example/android/listviewremovalanimation/StableArrayAdapter.java
new file mode 100644
index 0000000..948676e
--- /dev/null
+++ b/samples/devbytes/animation/ListViewRemovalAnimation/src/com/example/android/listviewremovalanimation/StableArrayAdapter.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2013 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.listviewremovalanimation;
+
+import java.util.HashMap;
+import java.util.List;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+
+public class StableArrayAdapter extends ArrayAdapter<String> {
+
+    HashMap<String, Integer> mIdMap = new HashMap<String, Integer>();
+    View.OnTouchListener mTouchListener;
+
+    public StableArrayAdapter(Context context, int textViewResourceId,
+            List<String> objects, View.OnTouchListener listener) {
+        super(context, textViewResourceId, objects);
+        mTouchListener = listener;
+        for (int i = 0; i < objects.size(); ++i) {
+            mIdMap.put(objects.get(i), i);
+        }
+    }
+
+    @Override
+    public long getItemId(int position) {
+        String item = getItem(position);
+        return mIdMap.get(item);
+    }
+
+    @Override
+    public boolean hasStableIds() {
+        return true;
+    }
+
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent) {
+        View view = super.getView(position, convertView, parent);
+        if (view != convertView) {
+            // Add touch listener to every new view to track swipe motion
+            view.setOnTouchListener(mTouchListener);
+        }
+        return view;
+    }
+
+}
diff --git a/samples/devbytes/animation/LiveButton/AndroidManifest.xml b/samples/devbytes/animation/LiveButton/AndroidManifest.xml
new file mode 100644
index 0000000..280c2f8
--- /dev/null
+++ b/samples/devbytes/animation/LiveButton/AndroidManifest.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.android.livebutton"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk
+        android:minSdkVersion="14"
+        android:targetSdkVersion="17" />
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/ic_launcher"
+        android:label="@string/app_name"
+        android:theme="@style/AppTheme" >
+        <activity
+            android:name="com.example.android.livebutton.LiveButton"
+            android:label="@string/app_name" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest>
\ No newline at end of file
diff --git a/samples/devbytes/animation/LiveButton/res/drawable-hdpi/ic_launcher.png b/samples/devbytes/animation/LiveButton/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..96a442e
--- /dev/null
+++ b/samples/devbytes/animation/LiveButton/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/LiveButton/res/drawable-mdpi/ic_launcher.png b/samples/devbytes/animation/LiveButton/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..359047d
--- /dev/null
+++ b/samples/devbytes/animation/LiveButton/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/LiveButton/res/drawable-xhdpi/ic_launcher.png b/samples/devbytes/animation/LiveButton/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..71c6d76
--- /dev/null
+++ b/samples/devbytes/animation/LiveButton/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/LiveButton/res/layout/activity_overshoot.xml b/samples/devbytes/animation/LiveButton/res/layout/activity_overshoot.xml
new file mode 100644
index 0000000..6900650
--- /dev/null
+++ b/samples/devbytes/animation/LiveButton/res/layout/activity_overshoot.xml
@@ -0,0 +1,29 @@
+<!-- Copyright (C) 2013 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.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context=".LiveButton" >
+
+    <Button
+        android:id="@+id/clickMe"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerHorizontal="true"
+        android:layout_centerVertical="true"
+        android:text="Click me!" />
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/samples/devbytes/animation/LiveButton/res/values-v14/styles.xml b/samples/devbytes/animation/LiveButton/res/values-v14/styles.xml
new file mode 100644
index 0000000..6e9521a
--- /dev/null
+++ b/samples/devbytes/animation/LiveButton/res/values-v14/styles.xml
@@ -0,0 +1,26 @@
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <!--
+        Base application theme for API 14+. This theme completely replaces
+        AppBaseTheme from BOTH res/values/styles.xml and
+        res/values-v11/styles.xml on API 14+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+        <!-- API 14 theme customizations can go here. -->
+    </style>
+
+</resources>
\ No newline at end of file
diff --git a/samples/devbytes/animation/LiveButton/res/values/strings.xml b/samples/devbytes/animation/LiveButton/res/values/strings.xml
new file mode 100644
index 0000000..5c5ff17
--- /dev/null
+++ b/samples/devbytes/animation/LiveButton/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <string name="app_name">LiveButton</string>
+    <string name="hello_world">Hello world!</string>
+    <string name="menu_settings">Settings</string>
+
+</resources>
\ No newline at end of file
diff --git a/samples/devbytes/animation/LiveButton/res/values/styles.xml b/samples/devbytes/animation/LiveButton/res/values/styles.xml
new file mode 100644
index 0000000..27658b7
--- /dev/null
+++ b/samples/devbytes/animation/LiveButton/res/values/styles.xml
@@ -0,0 +1,34 @@
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <!--
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Light">
+        <!--
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        -->
+    </style>
+
+    <!-- Application theme. -->
+    <style name="AppTheme" parent="AppBaseTheme">
+        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+    </style>
+
+</resources>
\ No newline at end of file
diff --git a/samples/devbytes/animation/LiveButton/src/com/example/android/livebutton/LiveButton.java b/samples/devbytes/animation/LiveButton/src/com/example/android/livebutton/LiveButton.java
new file mode 100644
index 0000000..d9f8d5e
--- /dev/null
+++ b/samples/devbytes/animation/LiveButton/src/com/example/android/livebutton/LiveButton.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2013 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.livebutton;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.OvershootInterpolator;
+import android.widget.Button;
+
+/**
+ * This app shows a simple application of anticipation and follow-through techniques as
+ * the button animates into its pressed state and animates back out of it, overshooting
+ * end state before resolving.
+ *
+ * Watch the associated video for this demo on the DevBytes channel of developer.android.com
+ * or on the DevBytes playlist in the androiddevelopers channel on YouTube at
+ * https://www.youtube.com/playlist?list=PLWz5rJ2EKKc_XOgcRukSoKKjewFJZrKV0.
+ */
+public class LiveButton extends Activity {
+    
+    DecelerateInterpolator sDecelerator = new DecelerateInterpolator();
+    OvershootInterpolator sOvershooter = new OvershootInterpolator(10f);
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_overshoot);
+        
+        final Button clickMeButton = (Button) findViewById(R.id.clickMe);
+        clickMeButton.animate().setDuration(200);
+        
+        clickMeButton.setOnTouchListener(new View.OnTouchListener() {
+            
+            @Override
+            public boolean onTouch(View arg0, MotionEvent arg1) {
+                if (arg1.getAction() == MotionEvent.ACTION_DOWN) {
+                    clickMeButton.animate().setInterpolator(sDecelerator).
+                            scaleX(.7f).scaleY(.7f);
+                } else if (arg1.getAction() == MotionEvent.ACTION_UP) {
+                    clickMeButton.animate().setInterpolator(sOvershooter).
+                            scaleX(1f).scaleY(1f);
+                }
+                return false;
+            }
+        });
+        
+    }
+}
diff --git a/samples/devbytes/animation/MultiPropertyAnimations/AndroidManifest.xml b/samples/devbytes/animation/MultiPropertyAnimations/AndroidManifest.xml
new file mode 100644
index 0000000..6a7a593
--- /dev/null
+++ b/samples/devbytes/animation/MultiPropertyAnimations/AndroidManifest.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.android.multipropertyanimations"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk
+        android:minSdkVersion="14"
+        android:targetSdkVersion="17" />
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/ic_launcher"
+        android:label="@string/app_name"
+        android:theme="@style/AppTheme" >
+        <activity
+            android:name="com.example.android.multipropertyanimations.MultiPropertyAnimations"
+            android:label="@string/app_name" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest>
\ No newline at end of file
diff --git a/samples/devbytes/animation/MultiPropertyAnimations/res/drawable-hdpi/ic_launcher.png b/samples/devbytes/animation/MultiPropertyAnimations/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..96a442e
--- /dev/null
+++ b/samples/devbytes/animation/MultiPropertyAnimations/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/MultiPropertyAnimations/res/drawable-mdpi/ic_launcher.png b/samples/devbytes/animation/MultiPropertyAnimations/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..359047d
--- /dev/null
+++ b/samples/devbytes/animation/MultiPropertyAnimations/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/MultiPropertyAnimations/res/drawable-xhdpi/ic_launcher.png b/samples/devbytes/animation/MultiPropertyAnimations/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..71c6d76
--- /dev/null
+++ b/samples/devbytes/animation/MultiPropertyAnimations/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/MultiPropertyAnimations/res/layout/activity_multi_property_animations.xml b/samples/devbytes/animation/MultiPropertyAnimations/res/layout/activity_multi_property_animations.xml
new file mode 100644
index 0000000..f4826b6
--- /dev/null
+++ b/samples/devbytes/animation/MultiPropertyAnimations/res/layout/activity_multi_property_animations.xml
@@ -0,0 +1,46 @@
+<!-- Copyright (C) 2013 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"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    tools:context=".MultiPropertyAnimations" >
+
+    <Button
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:onClick="runValueAnimator"
+        android:text="Animate Me!" />
+
+    <Button
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:onClick="runViewPropertyAnimator"
+        android:text="Animate Me!" />
+
+    <Button
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:onClick="runObjectAnimators"
+        android:text="Animate Me!" />
+
+    <Button
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:onClick="runObjectAnimator"
+        android:text="Animate Me!" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/samples/devbytes/animation/MultiPropertyAnimations/res/values-v14/styles.xml b/samples/devbytes/animation/MultiPropertyAnimations/res/values-v14/styles.xml
new file mode 100644
index 0000000..6e9521a
--- /dev/null
+++ b/samples/devbytes/animation/MultiPropertyAnimations/res/values-v14/styles.xml
@@ -0,0 +1,26 @@
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <!--
+        Base application theme for API 14+. This theme completely replaces
+        AppBaseTheme from BOTH res/values/styles.xml and
+        res/values-v11/styles.xml on API 14+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+        <!-- API 14 theme customizations can go here. -->
+    </style>
+
+</resources>
\ No newline at end of file
diff --git a/samples/devbytes/animation/MultiPropertyAnimations/res/values/dimens.xml b/samples/devbytes/animation/MultiPropertyAnimations/res/values/dimens.xml
new file mode 100644
index 0000000..90db76b
--- /dev/null
+++ b/samples/devbytes/animation/MultiPropertyAnimations/res/values/dimens.xml
@@ -0,0 +1,21 @@
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <!-- Default screen margins, per the Android Design guidelines. -->
+    <dimen name="activity_horizontal_margin">16dp</dimen>
+    <dimen name="activity_vertical_margin">16dp</dimen>
+
+</resources>
\ No newline at end of file
diff --git a/samples/devbytes/animation/MultiPropertyAnimations/res/values/strings.xml b/samples/devbytes/animation/MultiPropertyAnimations/res/values/strings.xml
new file mode 100644
index 0000000..5487857
--- /dev/null
+++ b/samples/devbytes/animation/MultiPropertyAnimations/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <string name="app_name">MultiPropertyAnimations</string>
+    <string name="action_settings">Settings</string>
+    <string name="hello_world">Hello world!</string>
+
+</resources>
\ No newline at end of file
diff --git a/samples/devbytes/animation/MultiPropertyAnimations/res/values/styles.xml b/samples/devbytes/animation/MultiPropertyAnimations/res/values/styles.xml
new file mode 100644
index 0000000..27658b7
--- /dev/null
+++ b/samples/devbytes/animation/MultiPropertyAnimations/res/values/styles.xml
@@ -0,0 +1,34 @@
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <!--
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Light">
+        <!--
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        -->
+    </style>
+
+    <!-- Application theme. -->
+    <style name="AppTheme" parent="AppBaseTheme">
+        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+    </style>
+
+</resources>
\ No newline at end of file
diff --git a/samples/devbytes/animation/MultiPropertyAnimations/src/com/example/android/multipropertyanimations/MultiPropertyAnimations.java b/samples/devbytes/animation/MultiPropertyAnimations/src/com/example/android/multipropertyanimations/MultiPropertyAnimations.java
new file mode 100644
index 0000000..e1c8054
--- /dev/null
+++ b/samples/devbytes/animation/MultiPropertyAnimations/src/com/example/android/multipropertyanimations/MultiPropertyAnimations.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2013 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.multipropertyanimations;
+
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+
+/**
+ * This example shows various ways of animating multiple properties in parallel.
+ *
+ * Watch the associated video for this demo on the DevBytes channel of developer.android.com
+ * or on the DevBytes playlist in the androiddevelopers channel on YouTube at
+ * https://www.youtube.com/playlist?list=PLWz5rJ2EKKc_XOgcRukSoKKjewFJZrKV0.
+ */
+public class MultiPropertyAnimations extends Activity {
+
+    private static final float TX_START = 0;
+    private static final float TY_START = 0;
+    private static final float TX_END = 400;
+    private static final float TY_END = 200;
+    
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_multi_property_animations);
+    }
+
+    /**
+     * A very manual approach to animation uses a ValueAnimator to animate a fractional
+     * value and then turns that value into the final property values which are then set
+     * directly on the target object.
+     */
+    public void runValueAnimator(final View view) {
+        ValueAnimator anim = ValueAnimator.ofFloat(0, 400);
+        anim.addUpdateListener(new AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animator) {
+                float fraction = animator.getAnimatedFraction();
+                view.setTranslationX(TX_START + fraction * (TX_END - TX_START));
+                view.setTranslationY(TY_START + fraction * (TY_END - TY_START));
+            }
+        });
+        anim.start();
+    }
+
+    /**
+     * ViewPropertyAnimator is the cleanest and most efficient way of animating
+     * View properties, even when there are multiple properties to be animated
+     * in parallel.
+     */
+    public void runViewPropertyAnimator(View view) {
+        view.animate().translationX(TX_END).translationY(TY_END);
+    }
+
+    /**
+     * Multiple ObjectAnimator objects can be created and run in parallel.
+     */
+    public void runObjectAnimators(View view) {
+        ObjectAnimator.ofFloat(view, View.TRANSLATION_X, TX_END).start();
+        ObjectAnimator.ofFloat(view, View.TRANSLATION_Y, TY_END).start();
+        // Optional: use an AnimatorSet to run these in parallel
+    }
+    
+    /**
+     * Using PropertyValuesHolder objects enables the use of a single ObjectAnimator
+     * per target, even when there are multiple properties being animated on that target.
+     */
+    public void runObjectAnimator(View view) {
+        PropertyValuesHolder pvhTX = PropertyValuesHolder.ofFloat(View.TRANSLATION_X, TX_END);
+        PropertyValuesHolder pvhTY = PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, TY_END);
+        ObjectAnimator.ofPropertyValuesHolder(view, pvhTX, pvhTY).start();
+    }
+}
diff --git a/samples/devbytes/animation/SlidingFragments/AndroidManifest.xml b/samples/devbytes/animation/SlidingFragments/AndroidManifest.xml
new file mode 100644
index 0000000..2e71b6c
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Copyright (C) 2013 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.example.android.slidingfragments"
+          android:versionCode="1"
+          android:versionName="1.0">
+    <uses-sdk android:minSdkVersion="14"
+              android:targetSdkVersion="17"/>
+    <application android:label="@string/app_name" android:icon="@drawable/ic_launcher">
+        <activity android:name=".SlidingFragments"
+                  android:label="@string/app_name">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/samples/devbytes/animation/SlidingFragments/res/animator/slide_fragment_in.xml b/samples/devbytes/animation/SlidingFragments/res/animator/slide_fragment_in.xml
new file mode 100644
index 0000000..7fe333b
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/res/animator/slide_fragment_in.xml
@@ -0,0 +1,22 @@
+<!-- Copyright (C) 2013 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.
+-->
+
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:valueFrom="0"
+    android:valueTo="@dimen/slide_up_down_fraction"
+    android:propertyName="yFraction"
+    android:valueType="floatType"
+    android:duration="@integer/slide_up_down_duration">
+</objectAnimator>
\ No newline at end of file
diff --git a/samples/devbytes/animation/SlidingFragments/res/animator/slide_fragment_out.xml b/samples/devbytes/animation/SlidingFragments/res/animator/slide_fragment_out.xml
new file mode 100644
index 0000000..4d4134a
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/res/animator/slide_fragment_out.xml
@@ -0,0 +1,22 @@
+<!-- Copyright (C) 2013 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.
+-->
+
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:valueFrom="@dimen/slide_up_down_fraction"
+    android:valueTo="0"
+    android:propertyName="yFraction"
+    android:valueType="floatType"
+    android:duration="@integer/slide_up_down_duration" >
+</objectAnimator>
\ No newline at end of file
diff --git a/samples/devbytes/animation/SlidingFragments/res/drawable-hdpi/golden_gate.jpg b/samples/devbytes/animation/SlidingFragments/res/drawable-hdpi/golden_gate.jpg
new file mode 100644
index 0000000..9a3d3fd
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/res/drawable-hdpi/golden_gate.jpg
Binary files differ
diff --git a/samples/devbytes/animation/SlidingFragments/res/drawable-hdpi/ic_launcher.png b/samples/devbytes/animation/SlidingFragments/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..96a442e
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/SlidingFragments/res/drawable-ldpi/ic_launcher.png b/samples/devbytes/animation/SlidingFragments/res/drawable-ldpi/ic_launcher.png
new file mode 100644
index 0000000..9923872
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/res/drawable-ldpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/SlidingFragments/res/drawable-mdpi/ic_launcher.png b/samples/devbytes/animation/SlidingFragments/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..359047d
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/SlidingFragments/res/drawable-xhdpi/ic_launcher.png b/samples/devbytes/animation/SlidingFragments/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..71c6d76
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/SlidingFragments/res/layout/image_fragment.xml b/samples/devbytes/animation/SlidingFragments/res/layout/image_fragment.xml
new file mode 100644
index 0000000..eb555fe
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/res/layout/image_fragment.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2013 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.
+-->
+
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:src="@drawable/golden_gate" >
+</ImageView>
\ No newline at end of file
diff --git a/samples/devbytes/animation/SlidingFragments/res/layout/sliding_fragments_layout.xml b/samples/devbytes/animation/SlidingFragments/res/layout/sliding_fragments_layout.xml
new file mode 100644
index 0000000..a789a77
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/res/layout/sliding_fragments_layout.xml
@@ -0,0 +1,31 @@
+<!-- Copyright (C) 2013 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.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:id="@+id/move_to_back_container">
+
+    <fragment class="com.example.android.slidingfragments.ImageFragment"
+        android:id="@+id/move_fragment"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+    <View android:id="@+id/dark_hover_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="@color/black" />
+
+</FrameLayout>
\ No newline at end of file
diff --git a/samples/devbytes/animation/SlidingFragments/res/layout/text_fragment.xml b/samples/devbytes/animation/SlidingFragments/res/layout/text_fragment.xml
new file mode 100644
index 0000000..652acaa
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/res/layout/text_fragment.xml
@@ -0,0 +1,104 @@
+<!-- Copyright (C) 2013 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.
+-->
+
+<com.example.android.slidingfragments.FractionalLinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_marginLeft="@dimen/slide_fragment_horizontal_margin"
+    android:layout_marginRight="@dimen/slide_fragment_horizontal_margin"
+    android:orientation="vertical"
+    android:background="@color/white">
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/bridge"
+        android:textColor="#000000"
+        android:textStyle="bold"
+        android:textSize="26sp"
+        android:layout_marginBottom="@dimen/text_vertical_margin"
+        android:layout_marginLeft="@dimen/text_horizontal_margin"
+        android:layout_marginRight="@dimen/text_horizontal_margin" />
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/summary"
+        android:textSize="18sp"
+        android:textColor="#000000"
+        android:layout_marginBottom="@dimen/text_vertical_margin"
+        android:layout_marginLeft="@dimen/text_horizontal_margin"
+        android:layout_marginRight="@dimen/text_horizontal_margin" />
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/length"
+        android:textColor="#000000"
+        android:layout_marginLeft="@dimen/text_horizontal_margin"
+        android:layout_marginRight="@dimen/text_horizontal_margin" />
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/span"
+        android:textColor="#000000"
+        android:layout_marginLeft="@dimen/text_horizontal_margin"
+        android:layout_marginRight="@dimen/text_horizontal_margin" />
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/construction"
+        android:textColor="#000000"
+        android:layout_marginLeft="@dimen/text_horizontal_margin"
+        android:layout_marginRight="@dimen/text_horizontal_margin" />
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/height"
+        android:textColor="#000000"
+        android:layout_marginLeft="@dimen/text_horizontal_margin"
+        android:layout_marginRight="@dimen/text_horizontal_margin" />
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/elevation"
+        android:textColor="#000000"
+        android:layout_marginLeft="@dimen/text_horizontal_margin"
+        android:layout_marginRight="@dimen/text_horizontal_margin" />
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/address"
+        android:textColor="#000000"
+        android:layout_marginLeft="@dimen/text_horizontal_margin"
+        android:layout_marginRight="@dimen/text_horizontal_margin" />
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/photo_credits"
+        android:textColor="#000000"
+        android:textSize="10sp"
+        android:layout_marginTop="@dimen/text_vertical_margin"
+        android:layout_marginLeft="@dimen/text_horizontal_margin"
+        android:layout_marginRight="@dimen/text_horizontal_margin" />
+
+</com.example.android.slidingfragments.FractionalLinearLayout>
\ No newline at end of file
diff --git a/samples/devbytes/animation/SlidingFragments/res/values/colors.xml b/samples/devbytes/animation/SlidingFragments/res/values/colors.xml
new file mode 100644
index 0000000..f5eb07a
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/res/values/colors.xml
@@ -0,0 +1,23 @@
+<!-- Copyright (C) 2013 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.
+-->
+
+<resources>
+
+    <color name="red">#ff0000</color>
+    <color name="black">#000000</color>
+    <color name="white">#ffffff</color>
+    <color name="green">#00ff00</color>
+
+</resources>
\ No newline at end of file
diff --git a/samples/devbytes/animation/SlidingFragments/res/values/dimens.xml b/samples/devbytes/animation/SlidingFragments/res/values/dimens.xml
new file mode 100644
index 0000000..2b378c1
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/res/values/dimens.xml
@@ -0,0 +1,22 @@
+<!-- Copyright (C) 2013 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.
+-->
+
+<resources>
+
+    <dimen name="slide_fragment_horizontal_margin">50dp</dimen>
+    <dimen name="text_vertical_margin">18dp</dimen>
+    <dimen name="text_horizontal_margin">10dp</dimen>
+
+</resources>
diff --git a/samples/devbytes/animation/SlidingFragments/res/values/integers.xml b/samples/devbytes/animation/SlidingFragments/res/values/integers.xml
new file mode 100644
index 0000000..57c19ac
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/res/values/integers.xml
@@ -0,0 +1,22 @@
+<!-- Copyright (C) 2013 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.
+-->
+
+<resources>
+
+    <integer name="slide_up_down_duration">200</integer>
+    <integer name="half_slide_up_down_duration">150</integer>
+    <integer name="slide_up_down_final_value">150</integer>
+
+</resources>
\ No newline at end of file
diff --git a/samples/devbytes/animation/SlidingFragments/res/values/items.xml b/samples/devbytes/animation/SlidingFragments/res/values/items.xml
new file mode 100644
index 0000000..2b7f0b5
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/res/values/items.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2013 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.
+-->
+
+<resources>
+
+    <item name="slide_up_down_fraction" type="dimen" format="float">0.67</item>
+
+</resources>
\ No newline at end of file
diff --git a/samples/devbytes/animation/SlidingFragments/res/values/strings.xml b/samples/devbytes/animation/SlidingFragments/res/values/strings.xml
new file mode 100644
index 0000000..dbc41da
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/res/values/strings.xml
@@ -0,0 +1,29 @@
+<!-- Copyright (C) 2013 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.
+-->
+
+<resources>
+
+    <string name="app_name">SlidingFragments</string>
+    <string name="photo_credits"><b>Golden Gate Sunset</b> by <b>Romain Guy</b></string>
+    <string name="address"><b>Address:</b> Golden Gate Bridge, San Francisco, CA 94129</string>
+    <string name="elevation"><b>Elevation:</b>  220\' (67 m)</string>
+    <string name="height"><b>Height:</b>  746\' (227 m)</string>
+    <string name="construction"><b>Construction started:</b>  1933</string>
+    <string name="span"><b>Longest span:</b>  4,200\' (1,280 m)</string>
+    <string name="length"><b>Total length:</b>  8,980\' (2,737 m)</string>
+    <string name="summary">"The Golden Gate Bridge is a suspension bridge spanning the Golden Gate, the opening of the San Francisco Bay into the Pacific Ocean."</string>
+    <string name="bridge">Golden Gate Bridge</string>
+
+</resources>
diff --git a/samples/devbytes/animation/SlidingFragments/src/com/example/android/slidingfragments/FractionalLinearLayout.java b/samples/devbytes/animation/SlidingFragments/src/com/example/android/slidingfragments/FractionalLinearLayout.java
new file mode 100644
index 0000000..55f7269
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/src/com/example/android/slidingfragments/FractionalLinearLayout.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2013 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.slidingfragments;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.LinearLayout;
+
+/**
+ * In order to animate the fragment containing text on/off the screen,
+ * it is required that we know the height of the device being used. However,
+ * this can only be determined at runtime, so we cannot specify the required
+ * translation in an xml file. Since FragmentTransaction's setCustomAnimations
+ * method requires an ID of an animation defined via an xml file, this linear
+ * layout was built as a workaround. This custom linear layout is created to specify
+ * the location of the fragment's layout as a fraction of the device's height. By
+ * animating yFraction from 0 to 1, we can animate the fragment from the top of
+ * the screen to the bottom of the screen, regardless of the device's specific size.
+ */
+public class FractionalLinearLayout extends LinearLayout {
+
+    private float mYFraction;
+    private int mScreenHeight;
+
+    public FractionalLinearLayout(Context context) {
+        super(context);
+    }
+
+    public FractionalLinearLayout(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onSizeChanged (int w, int h, int oldw, int oldh) {
+        super.onSizeChanged(w, h, oldw, oldh);
+        mScreenHeight = h;
+        setY(mScreenHeight);
+    }
+
+    public float getYFraction() {
+        return mYFraction;
+    }
+
+    public void setYFraction(float yFraction) {
+        mYFraction = yFraction;
+        setY((mScreenHeight > 0) ? (mScreenHeight - yFraction * mScreenHeight) : 0);
+    }
+}
diff --git a/samples/devbytes/animation/SlidingFragments/src/com/example/android/slidingfragments/ImageFragment.java b/samples/devbytes/animation/SlidingFragments/src/com/example/android/slidingfragments/ImageFragment.java
new file mode 100644
index 0000000..e306c98
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/src/com/example/android/slidingfragments/ImageFragment.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2013 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.slidingfragments;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class ImageFragment extends Fragment {
+
+    View.OnClickListener clickListener;
+
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                             Bundle savedInstanceState) {
+        View view = inflater.inflate(R.layout.image_fragment, container, false);
+        view.setOnClickListener(clickListener);
+        return view;
+    }
+
+    public void setClickListener(View.OnClickListener clickListener) {
+        this.clickListener = clickListener;
+    }
+}
diff --git a/samples/devbytes/animation/SlidingFragments/src/com/example/android/slidingfragments/OnTextFragmentAnimationEndListener.java b/samples/devbytes/animation/SlidingFragments/src/com/example/android/slidingfragments/OnTextFragmentAnimationEndListener.java
new file mode 100644
index 0000000..692a7cb
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/src/com/example/android/slidingfragments/OnTextFragmentAnimationEndListener.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2013 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.slidingfragments;
+
+/**
+ * This interface is used to inform the main activity when the entry
+ * animation of the text fragment has completed in order to avoid the
+ * start of a new animation before the current one has completed.
+ */
+public interface OnTextFragmentAnimationEndListener {
+    public void onAnimationEnd();
+}
diff --git a/samples/devbytes/animation/SlidingFragments/src/com/example/android/slidingfragments/SlidingFragments.java b/samples/devbytes/animation/SlidingFragments/src/com/example/android/slidingfragments/SlidingFragments.java
new file mode 100644
index 0000000..9bfd8d4
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/src/com/example/android/slidingfragments/SlidingFragments.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2013 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.slidingfragments;
+
+import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.app.Activity;
+import android.app.FragmentManager;
+import android.app.FragmentTransaction;
+import android.os.Bundle;
+import android.view.View;
+
+/**
+ * This application shows a simple technique to animate and overlay two fragments
+ * on top of each other in order to provide a more immersive experience,
+ * as opposed to only having full screen transitions. When additional content
+ * (text) related to the currently displayed content (image) is to be shown,
+ * the currently visible content can be moved into the background instead of
+ * being removed from the screen entirely. This effect can therefore
+ * provide a more natural way of displaying additional information to the user
+ * using a different fragment.
+ *
+ * In this specific demo, tapping on the screen toggles between the two
+ * animated states of the fragment. When the animation is called,
+ * the fragment with an image animates into the background while the fragment
+ * containing text slides up on top of it. When the animation is toggled once
+ * more, the text fragment slides back down and the image fragment regains
+ * focus.
+ */
+public class SlidingFragments extends Activity implements
+        OnTextFragmentAnimationEndListener, FragmentManager.OnBackStackChangedListener {
+
+    ImageFragment mImageFragment;
+    TextFragment mTextFragment;
+    View mDarkHoverView;
+
+    boolean mDidSlideOut = false;
+    boolean mIsAnimating = false;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.sliding_fragments_layout);
+
+        mDarkHoverView = findViewById(R.id.dark_hover_view);
+        mDarkHoverView.setAlpha(0);
+
+        mImageFragment = (ImageFragment) getFragmentManager().findFragmentById(R.id.move_fragment);
+        mTextFragment = new TextFragment();
+
+        getFragmentManager().addOnBackStackChangedListener(this);
+
+        mImageFragment.setClickListener(mClickListener);
+        mTextFragment.setClickListener(mClickListener);
+        mTextFragment.setOnTextFragmentAnimationEnd(this);
+        mDarkHoverView.setOnClickListener(mClickListener);
+
+    }
+
+    View.OnClickListener mClickListener = new View.OnClickListener () {
+        @Override
+        public void onClick(View view) {
+            switchFragments();
+        }
+    };
+
+    /**
+     * This method is used to toggle between the two fragment states by
+     * calling the appropriate animations between them. The entry and exit
+     * animations of the text fragment are specified in R.animator resource
+     * files. The entry and exit animations of the image fragment are
+     * specified in the slideBack and slideForward methods below. The reason
+     * for separating the animation logic in this way is because the translucent
+     * dark hover view must fade in at the same time as the image fragment
+     * animates into the background, which would be difficult to time
+     * properly given that the setCustomAnimations method can only modify the
+     * two fragments in the transaction.
+     */
+    private void switchFragments () {
+        if (mIsAnimating) {
+            return;
+        }
+        mIsAnimating = true;
+        if (mDidSlideOut) {
+            mDidSlideOut = false;
+            getFragmentManager().popBackStack();
+        } else {
+            mDidSlideOut = true;
+
+            AnimatorListener listener = new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator arg0) {
+                    FragmentTransaction transaction = getFragmentManager().beginTransaction();
+                    transaction.setCustomAnimations(R.animator.slide_fragment_in, 0, 0,
+                            R.animator.slide_fragment_out);
+                    transaction.add(R.id.move_to_back_container, mTextFragment);
+                    transaction.addToBackStack(null);
+                    transaction.commit();
+                }
+            };
+            slideBack (listener);
+        }
+    }
+
+    @Override
+    public void onBackStackChanged() {
+        if (!mDidSlideOut) {
+            slideForward(null);
+        }
+
+    }
+
+    /**
+     * This method animates the image fragment into the background by both
+     * scaling and rotating the fragment's view, as well as adding a
+     * translucent dark hover view to inform the user that it is inactive.
+     */
+    public void slideBack(AnimatorListener listener)
+    {
+        View movingFragmentView = mImageFragment.getView();
+
+        PropertyValuesHolder rotateX =  PropertyValuesHolder.ofFloat("rotationX", 40f);
+        PropertyValuesHolder scaleX =  PropertyValuesHolder.ofFloat("scaleX", 0.8f);
+        PropertyValuesHolder scaleY =  PropertyValuesHolder.ofFloat("scaleY", 0.8f);
+        ObjectAnimator movingFragmentAnimator = ObjectAnimator.
+                ofPropertyValuesHolder(movingFragmentView, rotateX, scaleX, scaleY);
+
+        ObjectAnimator darkHoverViewAnimator = ObjectAnimator.
+                ofFloat(mDarkHoverView, "alpha", 0.0f, 0.5f);
+
+        ObjectAnimator movingFragmentRotator = ObjectAnimator.
+                ofFloat(movingFragmentView, "rotationX", 0);
+        movingFragmentRotator.setStartDelay(getResources().
+                getInteger(R.integer.half_slide_up_down_duration));
+
+        AnimatorSet s = new AnimatorSet();
+        s.playTogether(movingFragmentAnimator, darkHoverViewAnimator, movingFragmentRotator);
+        s.addListener(listener);
+        s.start();
+    }
+
+    /**
+     * This method animates the image fragment into the foreground by both
+     * scaling and rotating the fragment's view, while also removing the
+     * previously added translucent dark hover view. Upon the completion of
+     * this animation, the image fragment regains focus since this method is
+     * called from the onBackStackChanged method.
+     */
+    public void slideForward(AnimatorListener listener)
+    {
+        View movingFragmentView = mImageFragment.getView();
+
+        PropertyValuesHolder rotateX =  PropertyValuesHolder.ofFloat("rotationX", 40f);
+        PropertyValuesHolder scaleX =  PropertyValuesHolder.ofFloat("scaleX", 1.0f);
+        PropertyValuesHolder scaleY =  PropertyValuesHolder.ofFloat("scaleY", 1.0f);
+        ObjectAnimator movingFragmentAnimator = ObjectAnimator.
+                ofPropertyValuesHolder(movingFragmentView, rotateX, scaleX, scaleY);
+
+        ObjectAnimator darkHoverViewAnimator = ObjectAnimator.
+                ofFloat(mDarkHoverView, "alpha", 0.5f, 0.0f);
+
+        ObjectAnimator movingFragmentRotator = ObjectAnimator.
+                ofFloat(movingFragmentView, "rotationX", 0);
+        movingFragmentRotator.setStartDelay(
+                getResources().getInteger(R.integer.half_slide_up_down_duration));
+
+        AnimatorSet s = new AnimatorSet();
+        s.playTogether(movingFragmentAnimator, movingFragmentRotator, darkHoverViewAnimator);
+        s.setStartDelay(getResources().getInteger(R.integer.slide_up_down_duration));
+        s.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mIsAnimating = false;
+            }
+        });
+        s.start();
+    }
+
+    public void onAnimationEnd() {
+        mIsAnimating = false;
+    }
+}
diff --git a/samples/devbytes/animation/SlidingFragments/src/com/example/android/slidingfragments/TextFragment.java b/samples/devbytes/animation/SlidingFragments/src/com/example/android/slidingfragments/TextFragment.java
new file mode 100644
index 0000000..f1f245c
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/src/com/example/android/slidingfragments/TextFragment.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2013 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.slidingfragments;
+
+import android.animation.Animator;
+import android.animation.AnimatorInflater;
+import android.animation.AnimatorListenerAdapter;
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class TextFragment extends Fragment {
+
+    View.OnClickListener clickListener;
+    OnTextFragmentAnimationEndListener mListener;
+
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                             Bundle savedInstanceState) {
+        View view = inflater.inflate(R.layout.text_fragment, container, false);
+        view.setOnClickListener(clickListener);
+        return view;
+    }
+
+    public void setClickListener(View.OnClickListener clickListener) {
+        this.clickListener = clickListener;
+    }
+
+    @Override
+    public Animator onCreateAnimator(int transit, boolean enter, int nextAnim)
+    {
+        int id = enter ? R.animator.slide_fragment_in : R.animator.slide_fragment_out;
+        final Animator anim = AnimatorInflater.loadAnimator(getActivity(), id);
+        if (enter) {
+            anim.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    mListener.onAnimationEnd();
+                }
+            });
+        }
+        return anim;
+    }
+
+    public void setOnTextFragmentAnimationEnd(OnTextFragmentAnimationEndListener listener)
+    {
+        mListener = listener;
+    }
+
+}
diff --git a/samples/devbytes/animation/SquashAndStretch/AndroidManifest.xml b/samples/devbytes/animation/SquashAndStretch/AndroidManifest.xml
new file mode 100644
index 0000000..82e9b1b
--- /dev/null
+++ b/samples/devbytes/animation/SquashAndStretch/AndroidManifest.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.squashandstretch"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk
+        android:minSdkVersion="14"
+        android:targetSdkVersion="17" />
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/ic_launcher"
+        android:label="@string/app_name"
+        android:theme="@style/AppTheme" >
+        <activity
+            android:name="com.example.squashandstretch.SquashAndStretch"
+            android:label="@string/app_name" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest>
\ No newline at end of file
diff --git a/samples/devbytes/animation/SquashAndStretch/res/drawable-hdpi/ic_launcher.png b/samples/devbytes/animation/SquashAndStretch/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..96a442e
--- /dev/null
+++ b/samples/devbytes/animation/SquashAndStretch/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/SquashAndStretch/res/drawable-mdpi/ic_launcher.png b/samples/devbytes/animation/SquashAndStretch/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..359047d
--- /dev/null
+++ b/samples/devbytes/animation/SquashAndStretch/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/SquashAndStretch/res/drawable-xhdpi/ic_launcher.png b/samples/devbytes/animation/SquashAndStretch/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..71c6d76
--- /dev/null
+++ b/samples/devbytes/animation/SquashAndStretch/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/SquashAndStretch/res/layout/main.xml b/samples/devbytes/animation/SquashAndStretch/res/layout/main.xml
new file mode 100644
index 0000000..ea6793d
--- /dev/null
+++ b/samples/devbytes/animation/SquashAndStretch/res/layout/main.xml
@@ -0,0 +1,31 @@
+<!-- Copyright (C) 2013 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.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:id="@+id/container"
+    tools:context=".SquashAndStretch" >
+
+    <Button
+        android:id="@+id/button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentTop="true"
+        android:layout_centerHorizontal="true"
+        android:onClick="onButtonClick"
+        android:text="Click Me!" />
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/samples/devbytes/animation/SquashAndStretch/res/menu/main.xml b/samples/devbytes/animation/SquashAndStretch/res/menu/main.xml
new file mode 100644
index 0000000..aab540e
--- /dev/null
+++ b/samples/devbytes/animation/SquashAndStretch/res/menu/main.xml
@@ -0,0 +1,24 @@
+<!-- Copyright (C) 2013 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.
+-->
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <item
+        android:id="@+id/menu_slow"
+        android:orderInCategory="100"
+        android:showAsAction="never"
+        android:title="@string/menu_slow_animations"
+        android:checkable="true"/>
+
+</menu>
\ No newline at end of file
diff --git a/samples/devbytes/animation/SquashAndStretch/res/values-v14/styles.xml b/samples/devbytes/animation/SquashAndStretch/res/values-v14/styles.xml
new file mode 100644
index 0000000..6e9521a
--- /dev/null
+++ b/samples/devbytes/animation/SquashAndStretch/res/values-v14/styles.xml
@@ -0,0 +1,26 @@
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <!--
+        Base application theme for API 14+. This theme completely replaces
+        AppBaseTheme from BOTH res/values/styles.xml and
+        res/values-v11/styles.xml on API 14+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+        <!-- API 14 theme customizations can go here. -->
+    </style>
+
+</resources>
\ No newline at end of file
diff --git a/samples/devbytes/animation/SquashAndStretch/res/values/strings.xml b/samples/devbytes/animation/SquashAndStretch/res/values/strings.xml
new file mode 100644
index 0000000..3fb1b96
--- /dev/null
+++ b/samples/devbytes/animation/SquashAndStretch/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <string name="app_name">SquashAndStretch</string>
+    <string name="hello_world">Hello world!</string>
+    <string name="menu_slow_animations">Slow</string>
+
+</resources>
\ No newline at end of file
diff --git a/samples/devbytes/animation/SquashAndStretch/res/values/styles.xml b/samples/devbytes/animation/SquashAndStretch/res/values/styles.xml
new file mode 100644
index 0000000..27658b7
--- /dev/null
+++ b/samples/devbytes/animation/SquashAndStretch/res/values/styles.xml
@@ -0,0 +1,34 @@
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <!--
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Light">
+        <!--
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        -->
+    </style>
+
+    <!-- Application theme. -->
+    <style name="AppTheme" parent="AppBaseTheme">
+        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+    </style>
+
+</resources>
\ No newline at end of file
diff --git a/samples/devbytes/animation/SquashAndStretch/src/com/example/squashandstretch/SquashAndStretch.java b/samples/devbytes/animation/SquashAndStretch/src/com/example/squashandstretch/SquashAndStretch.java
new file mode 100644
index 0000000..328dd50
--- /dev/null
+++ b/samples/devbytes/animation/SquashAndStretch/src/com/example/squashandstretch/SquashAndStretch.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2013 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.squashandstretch;
+
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.animation.ValueAnimator;
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+
+/**
+ * This example shows how to add some life to a view during animation by deforming the shape.
+ * As the button "falls", it stretches along the line of travel. When it hits the bottom, it
+ * squashes, like a real object when hitting a surface. Then the button reverses these actions
+ * to bounce back up to the start.
+ *
+ * Watch the associated video for this demo on the DevBytes channel of developer.android.com
+ * or on the DevBytes playlist in the androiddevelopers channel on YouTube at
+ * https://www.youtube.com/playlist?list=PLWz5rJ2EKKc_XOgcRukSoKKjewFJZrKV0.
+ */
+public class SquashAndStretch extends Activity {
+
+    private static final AccelerateInterpolator sAccelerator = new AccelerateInterpolator();
+    private static final DecelerateInterpolator sDecelerator = new DecelerateInterpolator();
+
+    ViewGroup mContainer = null;
+    private static final long BASE_DURATION = 300;
+    private long sAnimatorScale = 1;
+    
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+        
+        mContainer = (ViewGroup) findViewById(R.id.container);
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        getMenuInflater().inflate(R.menu.main, menu);
+        return true;
+    }
+    
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        if (item.getItemId() == R.id.menu_slow) {
+            sAnimatorScale = item.isChecked() ? 1 : 5;
+            item.setChecked(!item.isChecked());
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
+    public void onButtonClick(View view) {
+        long animationDuration = (long) (BASE_DURATION * sAnimatorScale);
+
+        // Scale around bottom/middle to simplify squash against the window bottom
+        view.setPivotX(view.getWidth() / 2);
+        view.setPivotY(view.getHeight());
+        
+        // Animate the button down, accelerating, while also stretching in Y and squashing in X
+        PropertyValuesHolder pvhTY = PropertyValuesHolder.ofFloat(View.TRANSLATION_Y,
+                mContainer.getHeight() - view.getHeight());
+        PropertyValuesHolder pvhSX = PropertyValuesHolder.ofFloat(View.SCALE_X, .7f);
+        PropertyValuesHolder pvhSY = PropertyValuesHolder.ofFloat(View.SCALE_Y, 1.2f);
+        ObjectAnimator downAnim = ObjectAnimator.ofPropertyValuesHolder(
+                view, pvhTY, pvhSX, pvhSY);
+        downAnim.setInterpolator(sAccelerator);
+        downAnim.setDuration((long) (animationDuration * 2));
+
+        // Stretch in X, squash in Y, then reverse
+        pvhSX = PropertyValuesHolder.ofFloat(View.SCALE_X, 2);
+        pvhSY = PropertyValuesHolder.ofFloat(View.SCALE_Y, .5f);
+        ObjectAnimator stretchAnim =
+                ObjectAnimator.ofPropertyValuesHolder(view, pvhSX, pvhSY);
+        stretchAnim.setRepeatCount(1);
+        stretchAnim.setRepeatMode(ValueAnimator.REVERSE);
+        stretchAnim.setInterpolator(sDecelerator);
+        stretchAnim.setDuration(animationDuration);
+        
+        // Animate back to the start
+        pvhTY = PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, 0);
+        pvhSX = PropertyValuesHolder.ofFloat(View.SCALE_X, 1);
+        pvhSY = PropertyValuesHolder.ofFloat(View.SCALE_Y, 1);
+        ObjectAnimator upAnim =
+                ObjectAnimator.ofPropertyValuesHolder(view, pvhTY, pvhSX, pvhSY);
+        upAnim.setDuration((long) (animationDuration * 2));
+        upAnim.setInterpolator(sDecelerator);
+
+        AnimatorSet set = new AnimatorSet();
+        set.playSequentially(downAnim, stretchAnim, upAnim);
+        set.start();
+    }
+}
diff --git a/samples/devbytes/animation/ToonGame/AndroidManifest.xml b/samples/devbytes/animation/ToonGame/AndroidManifest.xml
new file mode 100644
index 0000000..505b7ce
--- /dev/null
+++ b/samples/devbytes/animation/ToonGame/AndroidManifest.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.android.toongame"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk
+        android:minSdkVersion="16"
+        android:targetSdkVersion="17" />
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/ic_launcher"
+        android:label="@string/app_name"
+        android:theme="@style/AppTheme" >
+        <activity
+            android:name="com.example.android.toongame.ToonGame"
+            android:label="@string/app_name" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <activity
+            android:name="com.example.android.toongame.PlayerSetupActivity"
+            android:windowSoftInputMode="adjustResize"
+            android:label="@string/app_name" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+            </intent-filter>
+        </activity>
+        </application>
+
+</manifest>
\ No newline at end of file
diff --git a/samples/devbytes/animation/ToonGame/res/drawable-hdpi/ic_launcher.png b/samples/devbytes/animation/ToonGame/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..96a442e
--- /dev/null
+++ b/samples/devbytes/animation/ToonGame/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/ToonGame/res/drawable-mdpi/blue_oval.xml b/samples/devbytes/animation/ToonGame/res/drawable-mdpi/blue_oval.xml
new file mode 100644
index 0000000..2ffe16a
--- /dev/null
+++ b/samples/devbytes/animation/ToonGame/res/drawable-mdpi/blue_oval.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="oval">
+    
+    <solid android:color="#00f"/>
+
+</shape>
\ No newline at end of file
diff --git a/samples/devbytes/animation/ToonGame/res/drawable-mdpi/cyan_oval.xml b/samples/devbytes/animation/ToonGame/res/drawable-mdpi/cyan_oval.xml
new file mode 100644
index 0000000..53ea6ac
--- /dev/null
+++ b/samples/devbytes/animation/ToonGame/res/drawable-mdpi/cyan_oval.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="oval">
+    
+    <solid android:color="#0ff"/>
+
+</shape>
\ No newline at end of file
diff --git a/samples/devbytes/animation/ToonGame/res/drawable-mdpi/green_button.xml b/samples/devbytes/animation/ToonGame/res/drawable-mdpi/green_button.xml
new file mode 100644
index 0000000..3ed5b67
--- /dev/null
+++ b/samples/devbytes/animation/ToonGame/res/drawable-mdpi/green_button.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android" >
+    <item android:drawable="@drawable/green_down" android:state_pressed="true"/>
+    <item android:drawable="@drawable/green_up"/>
+</selector>
\ No newline at end of file
diff --git a/samples/devbytes/animation/ToonGame/res/drawable-mdpi/green_down.9.png b/samples/devbytes/animation/ToonGame/res/drawable-mdpi/green_down.9.png
new file mode 100644
index 0000000..db974ba
--- /dev/null
+++ b/samples/devbytes/animation/ToonGame/res/drawable-mdpi/green_down.9.png
Binary files differ
diff --git a/samples/devbytes/animation/ToonGame/res/drawable-mdpi/green_oval.xml b/samples/devbytes/animation/ToonGame/res/drawable-mdpi/green_oval.xml
new file mode 100644
index 0000000..03b83c3
--- /dev/null
+++ b/samples/devbytes/animation/ToonGame/res/drawable-mdpi/green_oval.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="oval">
+    
+    <solid android:color="#0f0"/>
+
+</shape>
\ No newline at end of file
diff --git a/samples/devbytes/animation/ToonGame/res/drawable-mdpi/green_up.9.png b/samples/devbytes/animation/ToonGame/res/drawable-mdpi/green_up.9.png
new file mode 100644
index 0000000..0c2f5c8
--- /dev/null
+++ b/samples/devbytes/animation/ToonGame/res/drawable-mdpi/green_up.9.png
Binary files differ
diff --git a/samples/devbytes/animation/ToonGame/res/drawable-mdpi/ic_launcher.png b/samples/devbytes/animation/ToonGame/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..359047d
--- /dev/null
+++ b/samples/devbytes/animation/ToonGame/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/ToonGame/res/drawable-mdpi/magenta_oval.xml b/samples/devbytes/animation/ToonGame/res/drawable-mdpi/magenta_oval.xml
new file mode 100644
index 0000000..675b0dc
--- /dev/null
+++ b/samples/devbytes/animation/ToonGame/res/drawable-mdpi/magenta_oval.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="oval">
+    
+    <solid android:color="#f0f"/>
+
+</shape>
\ No newline at end of file
diff --git a/samples/devbytes/animation/ToonGame/res/drawable-mdpi/red_oval.xml b/samples/devbytes/animation/ToonGame/res/drawable-mdpi/red_oval.xml
new file mode 100644
index 0000000..f2276a6
--- /dev/null
+++ b/samples/devbytes/animation/ToonGame/res/drawable-mdpi/red_oval.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="oval">
+    
+    <solid android:color="#f00"/>
+
+</shape>
\ No newline at end of file
diff --git a/samples/devbytes/animation/ToonGame/res/drawable-mdpi/yellow_oval.xml b/samples/devbytes/animation/ToonGame/res/drawable-mdpi/yellow_oval.xml
new file mode 100644
index 0000000..d03f684
--- /dev/null
+++ b/samples/devbytes/animation/ToonGame/res/drawable-mdpi/yellow_oval.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="oval">
+    
+    <solid android:color="#ff0"/>
+
+</shape>
\ No newline at end of file
diff --git a/samples/devbytes/animation/ToonGame/res/drawable-xhdpi/ic_launcher.png b/samples/devbytes/animation/ToonGame/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..71c6d76
--- /dev/null
+++ b/samples/devbytes/animation/ToonGame/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/animation/ToonGame/res/layout/activity_toon_game.xml b/samples/devbytes/animation/ToonGame/res/layout/activity_toon_game.xml
new file mode 100644
index 0000000..d65301b
--- /dev/null
+++ b/samples/devbytes/animation/ToonGame/res/layout/activity_toon_game.xml
@@ -0,0 +1,47 @@
+<!-- Copyright (C) 2013 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.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:id="@+id/container"
+    tools:context=".ToonGame" >
+
+    <Button
+        android:id="@+id/startButton"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textSize="64dip"
+        android:layout_centerHorizontal="true"
+        android:layout_centerVertical="true"
+        android:textColor="#00c"
+        android:text="Play!"
+        android:background="@drawable/green_button"
+        android:visibility="invisible"
+        android:onClick="play"
+        android:textStyle="bold" />
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_above="@+id/startButton"
+        android:layout_centerHorizontal="true"
+        android:layout_marginBottom="39dp"
+        android:text="@string/welcome"
+        android:textColor="@android:color/holo_blue_bright"
+        android:textSize="64dip"
+        android:textStyle="bold" />
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/samples/devbytes/animation/ToonGame/res/layout/player_setup_layout.xml b/samples/devbytes/animation/ToonGame/res/layout/player_setup_layout.xml
new file mode 100644
index 0000000..c55d39b
--- /dev/null
+++ b/samples/devbytes/animation/ToonGame/res/layout/player_setup_layout.xml
@@ -0,0 +1,187 @@
+<!-- Copyright (C) 2013 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.
+-->
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" >
+
+    <RelativeLayout 
+        android:id="@+id/container"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:clipChildren="false">
+    
+        <view
+            android:id="@+id/nameTV"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentTop="true"
+            android:layout_centerHorizontal="true"
+            android:layout_marginTop="120dp"
+            class="com.example.android.toongame.SkewableTextView"
+            android:text="Name?"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:textSize="@dimen/bigText" />
+    
+        <view
+            class="com.example.android.toongame.SkewableTextView"
+            android:id="@+id/ageTV"
+            android:visibility="gone"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentTop="true"
+            android:layout_centerHorizontal="true"
+            android:layout_marginTop="120dp"
+            android:text="Difficulty?"
+            android:textAppearance="?android:attr/textAppearanceLarge"
+            android:textSize="@dimen/bigText" />
+    
+        <view
+            class="com.example.android.toongame.SkewableTextView"
+            android:id="@+id/creditTV"
+            android:visibility="gone"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentTop="true"
+            android:layout_centerHorizontal="true"
+            android:layout_marginTop="120dp"
+            android:gravity="center"
+            android:text="Parent's Credit Card Number?"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:textSize="64sp" />
+
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerHorizontal="true"
+            android:layout_alignParentBottom="true"
+            android:visibility="gone"
+            android:id="@+id/nameButtons"
+            android:layout_marginBottom="132dp" >
+            
+            <Button
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_margin="10dip"
+                android:padding="15dip"
+                android:background="@drawable/green_oval"
+                android:text="Bob"
+                android:textSize="36sp"
+                android:textColor="#fff"
+                android:textStyle="bold"
+                android:onClick="selectName"
+                android:id="@+id/bobButton"/>
+
+            <Button
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_margin="10dip"
+                android:padding="15dip"
+                android:background="@drawable/blue_oval"
+                android:text="Jane"
+                android:textSize="36sp"
+                android:textColor="#fff"
+                android:textStyle="bold"
+                android:onClick="selectName"
+                android:id="@+id/janeButton"/>
+
+            <Button
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_margin="10dip"
+                android:padding="15dip"
+                android:background="@drawable/magenta_oval"
+                android:text="Pat"
+                android:textSize="36sp"
+                android:textColor="#fff"
+                android:textStyle="bold"
+                 android:onClick="selectName"
+                android:id="@+id/patButton"/>
+
+        </LinearLayout>
+
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerHorizontal="true"
+            android:layout_alignParentBottom="true"
+            android:visibility="gone"
+            android:gravity="center"
+            android:orientation="vertical"
+            android:id="@+id/difficultyButtons"
+            android:layout_marginBottom="50dp" >
+            
+            <Button
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_margin="10dip"
+                android:padding="15dip"
+                android:background="@drawable/green_oval"
+                android:text="Easy"
+                android:textSize="36sp"
+                android:textColor="#fff"
+                android:textStyle="bold"
+                android:onClick="selectDifficulty"
+                android:id="@+id/easyButton"/>
+
+            <Button
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_margin="10dip"
+                android:padding="15dip"
+                android:background="@drawable/blue_oval"
+                android:text="Hard"
+                android:textSize="36sp"
+                android:textColor="#fff"
+                android:textStyle="bold"
+                android:onClick="selectDifficulty"
+                android:id="@+id/hardButton"/>
+
+            <Button
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_margin="10dip"
+                android:padding="15dip"
+                android:background="@drawable/red_oval"
+                android:text="Mega Hard"
+                android:textSize="36sp"
+                android:textColor="#000"
+                android:textStyle="bold|italic"
+                android:onClick="selectDifficulty"
+                android:id="@+id/megaHardButton"/>
+
+        </LinearLayout>
+        
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerHorizontal="true"
+            android:layout_alignParentBottom="true"
+            android:visibility="gone"
+            android:id="@+id/creditButtons1"
+            android:layout_marginBottom="132dp" />
+        
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerHorizontal="true"
+            android:layout_alignParentBottom="true"
+            android:visibility="gone"
+            android:id="@+id/creditButtons2"
+            android:layout_marginBottom="70dp" />
+        
+        
+    </RelativeLayout>
+</FrameLayout>
\ No newline at end of file
diff --git a/samples/devbytes/animation/ToonGame/res/values/dimens.xml b/samples/devbytes/animation/ToonGame/res/values/dimens.xml
new file mode 100644
index 0000000..fc229f6
--- /dev/null
+++ b/samples/devbytes/animation/ToonGame/res/values/dimens.xml
@@ -0,0 +1,22 @@
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <!-- Default screen margins, per the Android Design guidelines. -->
+    <dimen name="activity_horizontal_margin">16dp</dimen>
+    <dimen name="activity_vertical_margin">16dp</dimen>
+    <dimen name="bigText">64dip</dimen>
+
+</resources>
\ No newline at end of file
diff --git a/samples/devbytes/animation/ToonGame/res/values/strings.xml b/samples/devbytes/animation/ToonGame/res/values/strings.xml
new file mode 100644
index 0000000..fb256e6
--- /dev/null
+++ b/samples/devbytes/animation/ToonGame/res/values/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <string name="app_name">ToonGame</string>
+    <string name="action_settings">Settings</string>
+    <string name="hello_world">Hello world!</string>
+    <string name="welcome">Welcome!</string>
+
+</resources>
\ No newline at end of file
diff --git a/samples/devbytes/animation/ToonGame/res/values/styles.xml b/samples/devbytes/animation/ToonGame/res/values/styles.xml
new file mode 100644
index 0000000..9d91d6a
--- /dev/null
+++ b/samples/devbytes/animation/ToonGame/res/values/styles.xml
@@ -0,0 +1,34 @@
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <!--
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Light">
+        <!--
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        -->
+    </style>
+
+    <!-- Application theme. -->
+    <style name="AppTheme" parent="AppBaseTheme">
+        <item name="android:windowNoTitle">true</item>
+    </style>
+
+</resources>
\ No newline at end of file
diff --git a/samples/devbytes/animation/ToonGame/src/com/example/android/toongame/PlayerSetupActivity.java b/samples/devbytes/animation/ToonGame/src/com/example/android/toongame/PlayerSetupActivity.java
new file mode 100644
index 0000000..fce11c3
--- /dev/null
+++ b/samples/devbytes/animation/ToonGame/src/com/example/android/toongame/PlayerSetupActivity.java
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2013 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.toongame;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.animation.TimeInterpolator;
+import android.animation.ValueAnimator;
+import android.app.Activity;
+import android.content.res.ColorStateList;
+import android.graphics.Color;
+import android.graphics.Typeface;
+import android.graphics.drawable.ShapeDrawable;
+import android.graphics.drawable.shapes.OvalShape;
+import android.os.Bundle;
+import android.util.TypedValue;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.LinearInterpolator;
+import android.view.animation.OvershootInterpolator;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.RelativeLayout;
+
+/**
+ * This activity, launched from the ToonGame activity, takes the user between three
+ * different setup screens where they choose a name, choose a difficulty rating, and
+ * enter important financial information. All of the screens are meant to be
+ * simple, engaging, and fun.
+ */
+public class PlayerSetupActivity extends Activity {
+
+    private static final AccelerateInterpolator sAccelerator = new AccelerateInterpolator();
+    private static final LinearInterpolator sLinearInterpolator = new LinearInterpolator();
+    ViewGroup mContainer;
+    EditText mEditText;
+    
+    private static final int NAME_STATE = 0;
+    private static final int DIFFICULTY_STATE = 1;
+    private static final int CREDIT_STATE = 2;
+    private int mEntryState = NAME_STATE;
+
+    SkewableTextView mNameTV, mDifficultyTV, mCreditTV;
+    
+    ViewGroup mNameButtons, mDifficultyButtons, mCreditButtons1, mCreditButtons2;
+    
+    Button mBobButton, mJaneButton, mPatButton;
+    
+    private static final TimeInterpolator sOvershooter = new OvershootInterpolator();
+    private static final DecelerateInterpolator sDecelerator = new DecelerateInterpolator();
+    
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.player_setup_layout);
+        overridePendingTransition(0, 0);
+        
+        mContainer = (ViewGroup) findViewById(R.id.container);
+        mContainer.getViewTreeObserver().addOnPreDrawListener(mPreDrawListener);
+        
+        mNameTV = (SkewableTextView) findViewById(R.id.nameTV);
+        mDifficultyTV = (SkewableTextView) findViewById(R.id.ageTV);
+        mCreditTV = (SkewableTextView) findViewById(R.id.creditTV);
+        
+        mBobButton = setupButton(R.id.bobButton);
+        setupButton(R.id.janeButton);
+        setupButton(R.id.patButton);
+        setupButton(R.id.easyButton);
+        setupButton(R.id.hardButton);
+        setupButton(R.id.megaHardButton);
+        
+        mNameButtons = (ViewGroup) findViewById(R.id.nameButtons);
+        mDifficultyButtons = (ViewGroup) findViewById(R.id.difficultyButtons);
+        mCreditButtons1 = (ViewGroup) findViewById(R.id.creditButtons1);
+        mCreditButtons2 = (ViewGroup) findViewById(R.id.creditButtons2);
+    }
+    
+    @Override
+    public void finish() {
+        super.finish();
+        overridePendingTransition(0, 0);
+    }
+
+    private Button setupButton(int resourceId) {
+        Button button = (Button) findViewById(resourceId);
+        button.setOnTouchListener(mButtonPressListener);
+        return button;
+    }
+    
+    private View.OnTouchListener mButtonPressListener =
+            new View.OnTouchListener() {
+                public boolean onTouch(View v, MotionEvent event) {
+                    switch (event.getAction()) {
+                    case MotionEvent.ACTION_DOWN:
+                        v.animate().setDuration(ToonGame.SHORT_DURATION).
+                                scaleX(.8f).scaleY(.8f).setInterpolator(sDecelerator);
+                        break;
+                    case MotionEvent.ACTION_UP:
+                        v.animate().setDuration(ToonGame.SHORT_DURATION).
+                                scaleX(1).scaleY(1).setInterpolator(sAccelerator);
+                        break;
+                    default:
+                        break;
+                    }
+                    return false;
+                }
+            };
+
+    public void buttonClick(View clickedView, int alignmentRule) {
+        ViewGroup parent = (ViewGroup) clickedView.getParent();
+        for (int i = 0; i < parent.getChildCount(); ++i) {
+            Button child = (Button) parent.getChildAt(i);
+            if (child != clickedView) {
+                child.animate().alpha(0);
+            } else {
+                final Button buttonCopy = new Button(this);
+                child.setVisibility(View.INVISIBLE);
+                buttonCopy.setBackground(child.getBackground());
+                buttonCopy.setText(((Button) child).getText());
+                RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
+                        RelativeLayout.LayoutParams.WRAP_CONTENT,
+                        RelativeLayout.LayoutParams.WRAP_CONTENT);
+                params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
+                params.addRule(alignmentRule);
+                params.setMargins(25, 50, 25, 50);
+                buttonCopy.setLayoutParams(params);
+                buttonCopy.setPadding(child.getPaddingLeft(), child.getPaddingTop(),
+                        child.getPaddingRight(), child.getPaddingBottom());
+                buttonCopy.setTextSize(TypedValue.COMPLEX_UNIT_PX, child.getTextSize());
+                buttonCopy.setTypeface(child.getTypeface(), Typeface.BOLD);
+                ColorStateList colors = child.getTextColors();
+                buttonCopy.setTextColor(colors.getDefaultColor());
+                final int[] oldLocationInWindow = new int[2];
+                child.getLocationInWindow(oldLocationInWindow);
+                mContainer.addView(buttonCopy);
+                buttonCopy.getViewTreeObserver().addOnPreDrawListener(
+                        new ViewTreeObserver.OnPreDrawListener() {
+                    
+                    @Override
+                    public boolean onPreDraw() {
+                        buttonCopy.getViewTreeObserver().removeOnPreDrawListener(this);
+                        int[] locationInWindow = new int[2];
+                        buttonCopy.getLocationInWindow(locationInWindow);
+                        float deltaX = oldLocationInWindow[0] - locationInWindow[0];
+                        float deltaY = oldLocationInWindow[1] - locationInWindow[1];
+    
+                        buttonCopy.setTranslationX(deltaX);
+                        buttonCopy.setTranslationY(deltaY);
+                        
+                        PropertyValuesHolder pvhSX =
+                                PropertyValuesHolder.ofFloat(View.SCALE_X, 3);
+                        PropertyValuesHolder pvhSY =
+                                PropertyValuesHolder.ofFloat(View.SCALE_Y, 3);
+                        ObjectAnimator bounceAnim = ObjectAnimator.ofPropertyValuesHolder(
+                                buttonCopy, pvhSX, pvhSY);
+                        bounceAnim.setRepeatCount(1);
+                        bounceAnim.setRepeatMode(ValueAnimator.REVERSE);
+                        bounceAnim.setInterpolator(sDecelerator);
+                        bounceAnim.setDuration(300);
+                        
+                        PropertyValuesHolder pvhTX =
+                                PropertyValuesHolder.ofFloat(View.TRANSLATION_X, 0);
+                        PropertyValuesHolder pvhTY =
+                                PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, 0);
+                        ObjectAnimator moveAnim = ObjectAnimator.ofPropertyValuesHolder(
+                                buttonCopy, pvhTX, pvhTY);
+                        moveAnim.setDuration(600);
+                        bounceAnim.start();
+                        moveAnim.start();
+                        moveAnim.addListener(new AnimatorListenerAdapter() {
+                            public void onAnimationEnd(Animator animation) {
+                                switch (mEntryState) {
+                                case (NAME_STATE) :
+                                {
+                                    Runnable runnable = new Runnable() {
+                                        public void run() {
+                                            mDifficultyButtons.setVisibility(View.VISIBLE);
+                                            mNameButtons.setVisibility(View.GONE);
+                                            popChildrenIn(mDifficultyButtons, null);
+                                        }
+                                    };
+                                    slideToNext(mNameTV, mDifficultyTV, runnable);
+                                    mEntryState = DIFFICULTY_STATE;
+                                    break;
+                                }
+                                case (DIFFICULTY_STATE) :
+                                {
+                                    mDifficultyButtons.setVisibility(View.GONE);
+                                    for (int i = 0; i < 5; ++i) {
+                                        mCreditButtons1.addView(setupNumberButton(i));
+                                    }
+                                    for (int i = 5; i < 10; ++i) {
+                                        mCreditButtons2.addView(setupNumberButton(i));
+                                    }
+                                    Runnable runnable = new Runnable() {
+                                        public void run() {
+                                            mCreditButtons1.setVisibility(View.VISIBLE);
+                                            Runnable runnable = new Runnable() {
+                                                public void run() {
+                                                    mCreditButtons2.setVisibility(View.VISIBLE);
+                                                    popChildrenIn(mCreditButtons2, null);
+                                                }
+                                            };
+                                            popChildrenIn(mCreditButtons1, runnable);
+                                        }
+                                    };
+                                    slideToNext(mDifficultyTV, mCreditTV, runnable);
+                                    mEntryState = CREDIT_STATE;
+                                }
+                                    break;
+                                }
+                            }
+                        });
+                        return true;
+                    }
+                });
+            }
+        }
+    }
+    
+    public void selectDifficulty(View clickedView) {
+        buttonClick(clickedView, RelativeLayout.ALIGN_PARENT_RIGHT);
+    }
+    
+    public void selectName(View clickedView) {
+        buttonClick(clickedView, RelativeLayout.ALIGN_PARENT_LEFT);
+    }
+    
+    private Button setupNumberButton(int number) {
+        Button button = new Button(PlayerSetupActivity.this);
+        button.setTextSize(15);
+        button.setTextColor(Color.WHITE);
+        button.setTypeface(mBobButton.getTypeface(), Typeface.BOLD);
+        button.setText(Integer.toString(number));
+        button.setPadding(0, 0, 0, 0);
+        
+        OvalShape oval = new OvalShape();
+        ShapeDrawable drawable = new ShapeDrawable(oval);
+        drawable.getPaint().setColor(0xFF << 24 | (int) (50 + 150 * Math.random()) << 16 |
+                (int) (50 + 150 * Math.random()) << 8 |  (int) (50 + 150 * Math.random()));
+        button.setBackground(drawable);
+
+        button.setOnTouchListener(mButtonPressListener);
+
+        return button;
+    }
+
+    ViewTreeObserver.OnPreDrawListener mPreDrawListener =
+            new ViewTreeObserver.OnPreDrawListener() {
+        
+        @Override
+        public boolean onPreDraw() {
+            mContainer.getViewTreeObserver().removeOnPreDrawListener(this);
+            mContainer.setScaleX(0);
+            mContainer.setScaleY(0);
+            mContainer.animate().scaleX(1).scaleY(1).setInterpolator(new OvershootInterpolator());
+            mContainer.animate().setDuration(ToonGame.LONG_DURATION).withEndAction(new Runnable() {
+                
+                @Override
+                public void run() {
+                    ViewGroup buttonsParent = (ViewGroup) findViewById(R.id.nameButtons);
+                    buttonsParent.setVisibility(View.VISIBLE);
+                    popChildrenIn(buttonsParent, null);
+                }
+            });
+            return false;
+        }
+    };
+    
+    private void popChildrenIn(ViewGroup parent, final Runnable endAction) {
+        // for all children, scale in one at a time
+        TimeInterpolator overshooter = new OvershootInterpolator();
+        int childCount = parent.getChildCount();
+        ObjectAnimator[] childAnims = new ObjectAnimator[childCount];
+        for (int i = 0; i < childCount; ++i) {
+            View child = parent.getChildAt(i);
+            child.setScaleX(0);
+            child.setScaleY(0);
+            PropertyValuesHolder pvhSX = PropertyValuesHolder.ofFloat(View.SCALE_X, 1);
+            PropertyValuesHolder pvhSY = PropertyValuesHolder.ofFloat(View.SCALE_Y, 1);
+            ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(child, pvhSX, pvhSY);
+            anim.setDuration(150);
+            anim.setInterpolator(overshooter);
+            childAnims[i] = anim;
+        }
+        AnimatorSet set = new AnimatorSet();
+        set.playSequentially(childAnims);
+        set.start();
+        if (endAction != null) {
+            set.addListener(new AnimatorListenerAdapter() {
+                public void onAnimationEnd(Animator animation) {
+                    endAction.run();
+                }
+            });
+        }
+    }
+    
+    private void slideToNext(final SkewableTextView currentView,
+            final SkewableTextView nextView, final Runnable endAction) {
+        // skew/anticipate current view, slide off, set GONE, restore translation
+        ObjectAnimator currentSkewer = ObjectAnimator.ofFloat(currentView, "skewX", -.5f);
+        currentSkewer.setInterpolator(sDecelerator);
+        ObjectAnimator currentMover = ObjectAnimator.ofFloat(currentView, View.TRANSLATION_X,
+                -mContainer.getWidth());
+        currentMover.setInterpolator(sLinearInterpolator);
+        currentMover.setDuration(ToonGame.MEDIUM_DURATION);
+        
+        // set next view visible, translate off to right, skew,
+        // slide on in parallel, overshoot/wobble, unskew
+        nextView.setVisibility(View.VISIBLE);
+        nextView.setSkewX(-.5f);
+        nextView.setTranslationX(mContainer.getWidth());
+        
+        ObjectAnimator nextMover = ObjectAnimator.ofFloat(nextView, View.TRANSLATION_X, 0);
+        nextMover.setInterpolator(sAccelerator);
+        nextMover.setDuration(ToonGame.MEDIUM_DURATION);
+        ObjectAnimator nextSkewer = ObjectAnimator.ofFloat(nextView, "skewX", 0);
+        nextSkewer.setInterpolator(sOvershooter);
+        
+        AnimatorSet moverSet = new AnimatorSet();
+        moverSet.playTogether(currentMover, nextMover);
+        AnimatorSet fullSet = new AnimatorSet();
+        fullSet.playSequentially(currentSkewer, moverSet, nextSkewer);
+        fullSet.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                currentView.setSkewX(0);
+                currentView.setVisibility(View.GONE);
+                currentView.setTranslationX(0);
+                if (endAction != null) {
+                    endAction.run();
+                }
+            }
+        });
+        
+        fullSet.start();
+    }
+
+}
diff --git a/samples/devbytes/animation/ToonGame/src/com/example/android/toongame/SkewableTextView.java b/samples/devbytes/animation/ToonGame/src/com/example/android/toongame/SkewableTextView.java
new file mode 100644
index 0000000..9ea15ca
--- /dev/null
+++ b/samples/devbytes/animation/ToonGame/src/com/example/android/toongame/SkewableTextView.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2013 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.toongame;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.RectF;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.TextView;
+
+/**
+ * This custom TextView can be skewed to the left or right to enable anticipation and
+ * follow-through effects
+ */
+public class SkewableTextView extends TextView {
+
+    private float mSkewX;
+    RectF mTempRect = new RectF();
+    
+    public SkewableTextView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    public SkewableTextView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public SkewableTextView(Context context) {
+        super(context);
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        if (mSkewX != 0) {
+            canvas.translate(0, getHeight());
+            canvas.skew(mSkewX, 0);
+            canvas.translate(0,  -getHeight());
+        }
+        super.onDraw(canvas);
+    }
+
+    public float getSkewX() {
+        return mSkewX;
+    }
+    
+    public void setSkewX(float value) {
+        if (value != mSkewX) {
+            mSkewX = value;
+            invalidate();             // force redraw with new skew value
+            invalidateSkewedBounds(); // also invalidate appropriate area of parent
+        }
+    }
+    
+    /**
+     * Need to invalidate proper area of parent for skewed bounds
+     */
+    private void invalidateSkewedBounds() {
+        if (mSkewX != 0) {
+            Matrix matrix = new Matrix();
+            matrix.setSkew(-mSkewX, 0);
+            mTempRect.set(0, 0, getRight(), getBottom());
+            matrix.mapRect(mTempRect);
+            mTempRect.offset(getLeft() + getTranslationX(), getTop() + getTranslationY());
+            ((View) getParent()).invalidate((int) mTempRect.left, (int) mTempRect.top,
+                    (int) (mTempRect.right +.5f), (int) (mTempRect.bottom + .5f));
+        }
+    }
+}
diff --git a/samples/devbytes/animation/ToonGame/src/com/example/android/toongame/ToonGame.java b/samples/devbytes/animation/ToonGame/src/com/example/android/toongame/ToonGame.java
new file mode 100644
index 0000000..b03eeeb
--- /dev/null
+++ b/samples/devbytes/animation/ToonGame/src/com/example/android/toongame/ToonGame.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2013 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.toongame;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.animation.ValueAnimator;
+import android.app.Activity;
+import android.content.Intent;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnTouchListener;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.LinearInterpolator;
+import android.widget.Button;
+
+/**
+ * This application shows various cartoon animation techniques in the context of
+ * a larger application, to show how such animations might be used to create a more
+ * interactive, fun, and engaging experience.
+ *
+ * This main activity launches a sub-activity when the Play button is clicked. The
+ * main action in this master activity is bouncing the Play button in, randomly
+ * bouncing it while waiting for input, and animating its press and click behaviors
+ * when the user interacts with it. 
+ *
+ * Watch the associated video for this demo on the DevBytes channel of developer.android.com
+ * or on the DevBytes playlist in the androiddevelopers channel on YouTube at
+ * https://www.youtube.com/playlist?list=PLWz5rJ2EKKc_XOgcRukSoKKjewFJZrKV0.
+ */
+public class ToonGame extends Activity {
+
+    Button mStarter;
+    ViewGroup mContainer;
+    private static final AccelerateInterpolator sAccelerator = new AccelerateInterpolator();
+    private static final DecelerateInterpolator sDecelerator = new DecelerateInterpolator();
+    private static final LinearInterpolator sLinearInterpolator = new LinearInterpolator();
+    static long SHORT_DURATION = 100;
+    static long MEDIUM_DURATION = 200;
+    static long REGULAR_DURATION = 300;
+    static long LONG_DURATION = 500;
+    
+    private static float sDurationScale = 1f;
+    
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        overridePendingTransition(0, 0);
+        setContentView(R.layout.activity_toon_game);
+        
+        mStarter = (Button) findViewById(R.id.startButton);
+        mContainer = (ViewGroup) findViewById(R.id.container);
+        mStarter.setOnTouchListener(funButtonListener);
+        mStarter.animate().setDuration(100);
+        
+    }
+    
+    @Override
+    protected void onResume() {
+        super.onResume();
+        mContainer.setScaleX(1);
+        mContainer.setScaleY(1);
+        mContainer.setAlpha(1);
+        mStarter.setVisibility(View.INVISIBLE);
+        mContainer.getViewTreeObserver().addOnPreDrawListener(mOnPreDrawListener);
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        mStarter.removeCallbacks(mSquishRunnable);
+    }
+
+    private OnTouchListener funButtonListener = new OnTouchListener() {
+        
+        @Override
+        public boolean onTouch(View v, MotionEvent event) {
+            switch (event.getAction()) {
+            case MotionEvent.ACTION_DOWN:
+                mStarter.animate().scaleX(.8f).scaleY(.8f).setInterpolator(sDecelerator);
+                mStarter.setTextColor(Color.CYAN);
+                mStarter.removeCallbacks(mSquishRunnable);
+                mStarter.setPressed(true);
+                break;
+            case MotionEvent.ACTION_MOVE:
+                float x = event.getX();
+                float y = event.getY();
+                boolean isInside = (x > 0 && x < mStarter.getWidth() &&
+                        y > 0 && y < mStarter.getHeight());
+                if (mStarter.isPressed() != isInside) {
+                    mStarter.setPressed(isInside);
+                }
+                break;
+            case MotionEvent.ACTION_UP:
+                if (mStarter.isPressed()) {
+                    mStarter.performClick();
+                    mStarter.setPressed(false);
+                } else {
+                    mStarter.animate().scaleX(1).scaleY(1).setInterpolator(sAccelerator);
+                }
+                mStarter.setTextColor(Color.BLUE);
+                break;
+            }
+            return true;
+        }
+    };
+
+    private Runnable mSquishRunnable = new Runnable() {
+        public void run() {
+            squishyBounce(mStarter, 0,
+                    mContainer.getHeight() - mStarter.getTop() - mStarter.getHeight(),
+                    0, .5f, 1.5f);
+        }
+    };
+    
+    public void play(View view) {
+        mContainer.animate().scaleX(5).scaleY(5).alpha(0).setDuration(LONG_DURATION).
+                setInterpolator(sLinearInterpolator).
+                withEndAction(new Runnable() {
+            @Override
+            public void run() {
+                mStarter.postOnAnimation(new Runnable() {
+                    public void run() {
+                        Intent intent = new Intent(ToonGame.this,
+                                PlayerSetupActivity.class);
+                        startActivity(intent);
+                        overridePendingTransition(0, 0);
+                    }
+                });
+            }
+        });
+        view.removeCallbacks(mSquishRunnable);
+    }
+    
+    private ViewTreeObserver.OnPreDrawListener mOnPreDrawListener =
+            new ViewTreeObserver.OnPreDrawListener() {
+                
+                @Override
+                public boolean onPreDraw() {
+                    mContainer.getViewTreeObserver().removeOnPreDrawListener(this);
+                    mContainer.postDelayed(new Runnable() {
+                        public void run() {
+                            // Drop in the button from off the top of the screen
+                            mStarter.setVisibility(View.VISIBLE);
+                            mStarter.setY(-mStarter.getHeight());
+                            squishyBounce(mStarter, 
+                                    -(mStarter.getTop() + mStarter.getHeight()),
+                                    mContainer.getHeight() - mStarter.getTop() -
+                                            mStarter.getHeight(),
+                                    0, .5f, 1.5f);
+                        }
+                    }, 500);
+                    return true;
+                }
+            };
+
+    private void squishyBounce(final View view, final float startTY, final float bottomTY,
+            final float endTY, final float squash, final float stretch) {
+        view.setPivotX(view.getWidth() / 2);
+        view.setPivotY(view.getHeight());
+        PropertyValuesHolder pvhTY = PropertyValuesHolder.ofFloat(View.TRANSLATION_Y,
+                startTY, bottomTY);
+        PropertyValuesHolder pvhSX = PropertyValuesHolder.ofFloat(View.SCALE_X, .7f);
+        PropertyValuesHolder pvhSY = PropertyValuesHolder.ofFloat(View.SCALE_Y, 1.2f);
+        ObjectAnimator downAnim = ObjectAnimator.ofPropertyValuesHolder(view, pvhTY, pvhSX, pvhSY);
+        downAnim.setInterpolator(sAccelerator);
+
+        pvhTY = PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, bottomTY, endTY);
+        pvhSX = PropertyValuesHolder.ofFloat(View.SCALE_X, 1);
+        pvhSY = PropertyValuesHolder.ofFloat(View.SCALE_Y, 1);
+        ObjectAnimator upAnim = ObjectAnimator.ofPropertyValuesHolder(view, pvhTY, pvhSX, pvhSY);
+        upAnim.setInterpolator(sDecelerator);
+        
+        pvhSX = PropertyValuesHolder.ofFloat(View.SCALE_X, stretch);
+        pvhSY = PropertyValuesHolder.ofFloat(View.SCALE_Y, squash);
+        ObjectAnimator stretchAnim = ObjectAnimator.ofPropertyValuesHolder(view, pvhSX, pvhSY);
+        stretchAnim.setRepeatCount(1);
+        stretchAnim.setRepeatMode(ValueAnimator.REVERSE);
+        stretchAnim.setInterpolator(sDecelerator);
+        
+        AnimatorSet set = new AnimatorSet();
+        set.playSequentially(downAnim, stretchAnim, upAnim);
+        set.setDuration(getDuration(SHORT_DURATION));
+        set.start();
+        set.addListener(new AnimatorListenerAdapter() {
+            public void onAnimationEnd(Animator animation) {
+                view.postDelayed(mSquishRunnable, (long) (500 + Math.random() * 2000));
+            }
+        });
+    }
+    
+    public static long getDuration(long baseDuration) {
+        return (long) (baseDuration * sDurationScale);
+    }
+    
+
+}
diff --git a/samples/devbytes/graphics/FoldingLayout/AndroidManifest.xml b/samples/devbytes/graphics/FoldingLayout/AndroidManifest.xml
new file mode 100644
index 0000000..13758d7
--- /dev/null
+++ b/samples/devbytes/graphics/FoldingLayout/AndroidManifest.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.example.android.foldinglayout"
+          android:versionCode="1"
+          android:versionName="1.0">
+    <uses-permission android:name="android.permission.CAMERA" />
+    <uses-feature android:name="android.hardware.camera" />
+    <uses-sdk android:minSdkVersion="17"
+              android:targetSdkVersion="18"/>
+    <application android:label="@string/app_name" android:icon="@drawable/ic_launcher">
+        <activity android:name=".FoldingLayoutActivity"
+                  android:label="@string/app_name">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/samples/devbytes/graphics/FoldingLayout/res/drawable-hdpi/ic_launcher.png b/samples/devbytes/graphics/FoldingLayout/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..96a442e
--- /dev/null
+++ b/samples/devbytes/graphics/FoldingLayout/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/graphics/FoldingLayout/res/drawable-hdpi/image.jpg b/samples/devbytes/graphics/FoldingLayout/res/drawable-hdpi/image.jpg
new file mode 100644
index 0000000..60ce9f2
--- /dev/null
+++ b/samples/devbytes/graphics/FoldingLayout/res/drawable-hdpi/image.jpg
Binary files differ
diff --git a/samples/devbytes/graphics/FoldingLayout/res/drawable-ldpi/ic_launcher.png b/samples/devbytes/graphics/FoldingLayout/res/drawable-ldpi/ic_launcher.png
new file mode 100644
index 0000000..9923872
--- /dev/null
+++ b/samples/devbytes/graphics/FoldingLayout/res/drawable-ldpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/graphics/FoldingLayout/res/drawable-mdpi/ic_launcher.png b/samples/devbytes/graphics/FoldingLayout/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..359047d
--- /dev/null
+++ b/samples/devbytes/graphics/FoldingLayout/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/graphics/FoldingLayout/res/drawable-xhdpi/ic_launcher.png b/samples/devbytes/graphics/FoldingLayout/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..71c6d76
--- /dev/null
+++ b/samples/devbytes/graphics/FoldingLayout/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/graphics/FoldingLayout/res/layout/activity_fold.xml b/samples/devbytes/graphics/FoldingLayout/res/layout/activity_fold.xml
new file mode 100644
index 0000000..9ed3bc5
--- /dev/null
+++ b/samples/devbytes/graphics/FoldingLayout/res/layout/activity_fold.xml
@@ -0,0 +1,41 @@
+<!-- Copyright (C) 2013 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"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <com.example.android.foldinglayout.FoldingLayout
+        android:layout_weight="1"
+        android:id="@+id/fold_view"
+        android:layout_width="match_parent"
+        android:layout_height="0dp">
+
+        <ImageView
+                android:id="@+id/image_view"
+                android:layout_height="match_parent"
+                android:layout_width="match_parent"
+                android:scaleType="fitXY"/>
+
+        </com.example.android.foldinglayout.FoldingLayout>
+
+    <SeekBar
+        android:id="@+id/anchor_seek_bar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:max="100"/>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/samples/devbytes/graphics/FoldingLayout/res/layout/spinner.xml b/samples/devbytes/graphics/FoldingLayout/res/layout/spinner.xml
new file mode 100644
index 0000000..c35133d
--- /dev/null
+++ b/samples/devbytes/graphics/FoldingLayout/res/layout/spinner.xml
@@ -0,0 +1,18 @@
+<!-- Copyright (C) 2013 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.
+-->
+<Spinner xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:entries="@array/num_of_folds_array" />
\ No newline at end of file
diff --git a/samples/devbytes/graphics/FoldingLayout/res/menu/fold.xml b/samples/devbytes/graphics/FoldingLayout/res/menu/fold.xml
new file mode 100644
index 0000000..a0231bd
--- /dev/null
+++ b/samples/devbytes/graphics/FoldingLayout/res/menu/fold.xml
@@ -0,0 +1,41 @@
+<!-- Copyright (C) 2013 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.
+-->
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <item
+        android:id="@+id/toggle_orientation"
+        android:showAsAction="never"
+        android:title="@string/vertical"/>
+
+    <item
+        android:id="@+id/num_of_folds"
+        android:showAsAction="ifRoom"
+        android:actionLayout="@layout/spinner"/>
+
+    <item
+        android:title="@string/sepia_effect_off"
+        android:id="@+id/sepia"
+        android:checkable="true"/>
+
+    <item
+        android:title="@string/camera_feed"
+        android:id="@+id/camera_feed"/>
+
+    <item
+        android:id="@+id/animate_fold"
+        android:showAsAction="never"
+        android:title="@string/animate"/>
+
+</menu>
\ No newline at end of file
diff --git a/samples/devbytes/graphics/FoldingLayout/res/menu/fold_with_bug.xml b/samples/devbytes/graphics/FoldingLayout/res/menu/fold_with_bug.xml
new file mode 100644
index 0000000..44631ee
--- /dev/null
+++ b/samples/devbytes/graphics/FoldingLayout/res/menu/fold_with_bug.xml
@@ -0,0 +1,32 @@
+<!-- Copyright (C) 2013 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.
+-->
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <item
+            android:id="@+id/toggle_orientation"
+            android:showAsAction="never"
+            android:title="@string/vertical"/>
+
+    <item
+            android:id="@+id/num_of_folds"
+            android:showAsAction="ifRoom"
+            android:actionLayout="@layout/spinner"/>
+
+    <item
+            android:id="@+id/animate_fold"
+            android:showAsAction="never"
+            android:title="@string/animate"/>
+
+</menu>
\ No newline at end of file
diff --git a/samples/devbytes/graphics/FoldingLayout/res/values/strings.xml b/samples/devbytes/graphics/FoldingLayout/res/values/strings.xml
new file mode 100644
index 0000000..181b15d
--- /dev/null
+++ b/samples/devbytes/graphics/FoldingLayout/res/values/strings.xml
@@ -0,0 +1,42 @@
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <string name="app_name">FoldingLayout</string>
+    <string name="title_activity_fold">FoldActivity</string>
+
+    <string name="horizontal">Horizontal</string>
+    <string name="vertical">Vertical</string>
+    <string name="num_of_folds">Number Of Folds</string>
+
+    <string name="animate">Animate</string>
+
+    <string name="camera_feed">Camera Feed</string>
+    <string name="static_image">Static Image</string>
+
+    <string name="sepia_effect_off">Sepia Off</string>
+
+    <string-array name="num_of_folds_array">
+        <item>2</item>
+        <item>3</item>
+        <item>4</item>
+        <item>5</item>
+        <item>6</item>
+        <item>7</item>
+        <item>8</item>
+        <item>1</item>
+    </string-array>
+
+</resources>
diff --git a/samples/devbytes/graphics/FoldingLayout/src/com/example/android/foldinglayout/FoldingLayout.java b/samples/devbytes/graphics/FoldingLayout/src/com/example/android/foldinglayout/FoldingLayout.java
new file mode 100644
index 0000000..8afb27e
--- /dev/null
+++ b/samples/devbytes/graphics/FoldingLayout/src/com/example/android/foldinglayout/FoldingLayout.java
@@ -0,0 +1,545 @@
+/*
+ * Copyright (C) 2013 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.foldinglayout;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.LinearGradient;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import android.graphics.Rect;
+import android.graphics.Shader.TileMode;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * The folding layout where the number of folds, the anchor point and the
+ * orientation of the fold can be specified. Each of these parameters can
+ * be modified individually and updates and resets the fold to a default
+ * (unfolded) state. The fold factor varies between 0 (completely unfolded
+ * flat image) to 1.0 (completely folded, non-visible image).
+ *
+ * This layout throws an exception if there is more than one child added to the view.
+ * For more complicated view hierarchy's inside the folding layout, the views should all
+ * be nested inside 1 parent layout.
+ *
+ * This layout folds the contents of its child in real time. By applying matrix
+ * transformations when drawing to canvas, the contents of the child may change as
+ * the fold takes place. It is important to note that there are jagged edges about
+ * the perimeter of the layout as a result of applying transformations to a rectangle.
+ * This can be avoided by having the child of this layout wrap its content inside a
+ * 1 pixel transparent border. This will cause an anti-aliasing like effect and smoothen
+ * out the edges.
+ *
+ */
+public class FoldingLayout extends ViewGroup {
+
+    public static enum Orientation {
+        VERTICAL,
+        HORIZONTAL
+    }
+
+    private final String FOLDING_VIEW_EXCEPTION_MESSAGE = "Folding Layout can only 1 child at " +
+            "most";
+
+    private final float SHADING_ALPHA = 0.8f;
+    private final float SHADING_FACTOR = 0.5f;
+    private final int DEPTH_CONSTANT = 1500;
+    private final int NUM_OF_POLY_POINTS = 8;
+
+    private Rect[] mFoldRectArray;
+
+    private Matrix [] mMatrix;
+
+    private Orientation mOrientation = Orientation.HORIZONTAL;
+
+    private float mAnchorFactor = 0;
+    private float mFoldFactor = 0;
+
+    private int mNumberOfFolds = 2;
+
+    private boolean mIsHorizontal = true;
+
+    private int mOriginalWidth = 0;
+    private int mOriginalHeight = 0;
+
+    private float mFoldMaxWidth = 0;
+    private float mFoldMaxHeight = 0;
+    private float mFoldDrawWidth = 0;
+    private float mFoldDrawHeight = 0;
+
+    private boolean mIsFoldPrepared = false;
+    private boolean mShouldDraw = true;
+
+    private Paint mSolidShadow;
+    private Paint mGradientShadow;
+    private LinearGradient mShadowLinearGradient;
+    private Matrix mShadowGradientMatrix;
+
+    private float [] mSrc;
+    private float [] mDst;
+
+    private OnFoldListener mFoldListener;
+
+    private float mPreviousFoldFactor = 0;
+
+    private Bitmap mFullBitmap;
+    private Rect mDstRect;
+
+    public FoldingLayout(Context context) {
+        super(context);
+    }
+
+    public FoldingLayout(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public FoldingLayout(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    @Override
+    protected boolean addViewInLayout(View child, int index, LayoutParams params,
+                                      boolean preventRequestLayout) {
+        throwCustomException(getChildCount());
+        boolean returnValue = super.addViewInLayout(child, index, params, preventRequestLayout);
+        return returnValue;
+    }
+
+    @Override
+    public void addView(View child, int index, LayoutParams params) {
+        throwCustomException(getChildCount());
+        super.addView(child, index, params);
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        View child = getChildAt(0);
+        measureChild(child,widthMeasureSpec, heightMeasureSpec);
+        setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        View child = getChildAt(0);
+        child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight());
+        updateFold();
+    }
+
+    /**
+     * The custom exception to be thrown so as to limit the number of views in this
+     * layout to at most one.
+     */
+    private class NumberOfFoldingLayoutChildrenException extends RuntimeException {
+        public NumberOfFoldingLayoutChildrenException(String message) {
+            super(message);
+        }
+    }
+
+    /** Throws an exception if the number of views added to this layout exceeds one.*/
+    private void throwCustomException (int numOfChildViews) {
+        if (numOfChildViews == 1) {
+            throw new NumberOfFoldingLayoutChildrenException(FOLDING_VIEW_EXCEPTION_MESSAGE);
+        }
+    }
+
+    public void setFoldListener(OnFoldListener foldListener) {
+        mFoldListener = foldListener;
+    }
+
+    /**
+     * Sets the fold factor of the folding view and updates all the corresponding
+     * matrices and values to account for the new fold factor. Once that is complete,
+     * it redraws itself with the new fold. */
+    public void setFoldFactor(float foldFactor) {
+        if (foldFactor != mFoldFactor) {
+            mFoldFactor = foldFactor;
+            calculateMatrices();
+            invalidate();
+        }
+    }
+
+    public void setOrientation(Orientation orientation) {
+        if (orientation != mOrientation) {
+            mOrientation = orientation;
+            updateFold();
+        }
+    }
+
+    public void setAnchorFactor(float anchorFactor) {
+        if (anchorFactor != mAnchorFactor) {
+            mAnchorFactor = anchorFactor;
+            updateFold();
+        }
+    }
+
+    public void setNumberOfFolds(int numberOfFolds) {
+        if (numberOfFolds != mNumberOfFolds) {
+            mNumberOfFolds = numberOfFolds;
+            updateFold();
+        }
+    }
+
+    public float getAnchorFactor() {
+        return mAnchorFactor;
+    }
+
+    public Orientation getOrientation() {
+        return mOrientation;
+    }
+
+    public float getFoldFactor() {
+        return mFoldFactor;
+    }
+
+    public int getNumberOfFolds() {
+        return mNumberOfFolds;
+    }
+
+    private void updateFold() {
+        prepareFold(mOrientation, mAnchorFactor, mNumberOfFolds);
+        calculateMatrices();
+        invalidate();
+    }
+
+    /**
+     * This method is called in order to update the fold's orientation, anchor
+     * point and number of folds. This creates the necessary setup in order to
+     * prepare the layout for a fold with the specified parameters. Some of the
+     * dimensions required for the folding transformation are also acquired here.
+     *
+     * After this method is called, it will be in a completely unfolded state by default.
+     */
+    private void prepareFold(Orientation orientation, float anchorFactor, int numberOfFolds) {
+
+        mSrc = new float[NUM_OF_POLY_POINTS];
+        mDst = new float[NUM_OF_POLY_POINTS];
+
+        mDstRect = new Rect();
+
+        mFoldFactor = 0;
+        mPreviousFoldFactor = 0;
+
+        mIsFoldPrepared = false;
+
+        mSolidShadow = new Paint();
+        mGradientShadow = new Paint();
+
+        mOrientation = orientation;
+        mIsHorizontal = (orientation == Orientation.HORIZONTAL);
+
+        if (mIsHorizontal) {
+            mShadowLinearGradient = new LinearGradient(0, 0, SHADING_FACTOR, 0, Color.BLACK,
+                    Color.TRANSPARENT, TileMode.CLAMP);
+        } else {
+            mShadowLinearGradient = new LinearGradient(0, 0, 0, SHADING_FACTOR, Color.BLACK,
+                    Color.TRANSPARENT, TileMode.CLAMP);
+        }
+
+        mGradientShadow.setStyle(Style.FILL);
+        mGradientShadow.setShader(mShadowLinearGradient);
+        mShadowGradientMatrix = new Matrix();
+
+        mAnchorFactor = anchorFactor;
+        mNumberOfFolds = numberOfFolds;
+
+        mOriginalWidth = getMeasuredWidth();
+        mOriginalHeight = getMeasuredHeight();
+
+        mFoldRectArray = new Rect[mNumberOfFolds];
+        mMatrix = new Matrix [mNumberOfFolds];
+
+        for (int x = 0; x < mNumberOfFolds; x++) {
+            mMatrix[x] = new Matrix();
+        }
+
+        int h = mOriginalHeight;
+        int w = mOriginalWidth;
+
+        if (FoldingLayoutActivity.IS_JBMR2) {
+            mFullBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
+            Canvas canvas = new Canvas(mFullBitmap);
+            getChildAt(0).draw(canvas);
+        }
+
+        int delta = Math.round(mIsHorizontal ? ((float) w) / ((float) mNumberOfFolds) :
+                ((float) h) /((float) mNumberOfFolds));
+
+        /* Loops through the number of folds and segments the full layout into a number
+         * of smaller equal components. If the number of folds is odd, then one of the
+         * components will be smaller than all the rest. Note that deltap below handles
+         * the calculation for an odd number of folds.*/
+        for (int x = 0; x < mNumberOfFolds; x++) {
+            if (mIsHorizontal) {
+                int deltap = (x + 1) * delta > w ? w - x * delta : delta;
+                mFoldRectArray[x] = new Rect(x * delta, 0, x * delta + deltap, h);
+            } else {
+                int deltap = (x + 1) * delta > h ? h - x * delta : delta;
+                mFoldRectArray[x] = new Rect(0, x * delta, w, x * delta + deltap);
+            }
+        }
+
+        if (mIsHorizontal) {
+            mFoldMaxHeight = h;
+            mFoldMaxWidth = delta;
+        } else {
+            mFoldMaxHeight = delta;
+            mFoldMaxWidth = w;
+        }
+
+        mIsFoldPrepared = true;
+    }
+
+    /*
+    * Calculates the transformation matrices used to draw each of the separate folding
+    * segments from this view.
+    */
+    private void calculateMatrices() {
+
+        mShouldDraw = true;
+
+        if (!mIsFoldPrepared) {
+            return;
+        }
+
+        /** If the fold factor is 1 than the folding view should not be seen
+         * and the canvas can be left completely empty. */
+        if (mFoldFactor == 1) {
+            mShouldDraw = false;
+            return;
+        }
+
+        if (mFoldFactor == 0 &&  mPreviousFoldFactor > 0) {
+            mFoldListener.onEndFold();
+        }
+
+        if (mPreviousFoldFactor == 0 && mFoldFactor > 0) {
+            mFoldListener.onStartFold();
+        }
+
+        mPreviousFoldFactor = mFoldFactor;
+
+        /* Reset all the transformation matrices back to identity before computing
+         * the new transformation */
+        for (int x = 0; x < mNumberOfFolds; x++) {
+            mMatrix[x].reset();
+        }
+
+        float cTranslationFactor = 1 - mFoldFactor;
+
+        float translatedDistance = mIsHorizontal ? mOriginalWidth * cTranslationFactor :
+                mOriginalHeight * cTranslationFactor;
+
+        float translatedDistancePerFold = Math.round(translatedDistance / mNumberOfFolds);
+
+        /* For an odd number of folds, the rounding error may cause the
+         * translatedDistancePerFold to be grater than the max fold width or height. */
+        mFoldDrawWidth = mFoldMaxWidth < translatedDistancePerFold ?
+                translatedDistancePerFold : mFoldMaxWidth;
+        mFoldDrawHeight = mFoldMaxHeight < translatedDistancePerFold ?
+                translatedDistancePerFold : mFoldMaxHeight;
+
+        float translatedDistanceFoldSquared = translatedDistancePerFold * translatedDistancePerFold;
+
+        /* Calculate the depth of the fold into the screen using pythagorean theorem. */
+        float depth = mIsHorizontal ?
+                (float)Math.sqrt((double)(mFoldDrawWidth * mFoldDrawWidth -
+                        translatedDistanceFoldSquared)) :
+                (float)Math.sqrt((double)(mFoldDrawHeight * mFoldDrawHeight -
+                        translatedDistanceFoldSquared));
+
+        /* The size of some object is always inversely proportional to the distance
+        *  it is away from the viewpoint. The constant can be varied to to affect the
+        *  amount of perspective. */
+        float scaleFactor = DEPTH_CONSTANT / (DEPTH_CONSTANT + depth);
+
+        float scaledWidth, scaledHeight, bottomScaledPoint, topScaledPoint, rightScaledPoint,
+                leftScaledPoint;
+
+        if (mIsHorizontal) {
+            scaledWidth = mFoldDrawWidth * cTranslationFactor;
+            scaledHeight = mFoldDrawHeight * scaleFactor;
+        } else {
+            scaledWidth = mFoldDrawWidth * scaleFactor;
+            scaledHeight = mFoldDrawHeight * cTranslationFactor;
+        }
+
+        topScaledPoint = (mFoldDrawHeight - scaledHeight) / 2.0f;
+        bottomScaledPoint = topScaledPoint + scaledHeight;
+
+        leftScaledPoint = (mFoldDrawWidth - scaledWidth) / 2.0f;
+        rightScaledPoint = leftScaledPoint + scaledWidth;
+
+        float anchorPoint = mIsHorizontal ? mAnchorFactor * mOriginalWidth :
+                mAnchorFactor * mOriginalHeight;
+
+        /* The fold along which the anchor point is located. */
+        float midFold = mIsHorizontal ? (anchorPoint / mFoldDrawWidth) : anchorPoint /
+                mFoldDrawHeight;
+
+        mSrc[0] = 0;
+        mSrc[1] = 0;
+        mSrc[2] = 0;
+        mSrc[3] = mFoldDrawHeight;
+        mSrc[4] = mFoldDrawWidth;
+        mSrc[5] = 0;
+        mSrc[6] = mFoldDrawWidth;
+        mSrc[7] = mFoldDrawHeight;
+
+        /* Computes the transformation matrix for each fold using the values calculated above. */
+        for (int x = 0; x < mNumberOfFolds; x++) {
+
+            boolean isEven = (x % 2 == 0);
+
+            if (mIsHorizontal) {
+                mDst[0] = (anchorPoint > x * mFoldDrawWidth) ? anchorPoint + (x - midFold) *
+                        scaledWidth : anchorPoint - (midFold - x) * scaledWidth;
+                mDst[1] = isEven ? 0 : topScaledPoint;
+                mDst[2] = mDst[0];
+                mDst[3] = isEven ? mFoldDrawHeight: bottomScaledPoint;
+                mDst[4] = (anchorPoint > (x + 1) * mFoldDrawWidth) ? anchorPoint + (x + 1 - midFold)
+                        * scaledWidth : anchorPoint - (midFold - x - 1) * scaledWidth;
+                mDst[5] = isEven ? topScaledPoint : 0;
+                mDst[6] = mDst[4];
+                mDst[7] = isEven ? bottomScaledPoint : mFoldDrawHeight;
+
+            } else {
+                mDst[0] = isEven ? 0 : leftScaledPoint;
+                mDst[1] = (anchorPoint > x * mFoldDrawHeight) ? anchorPoint + (x - midFold) *
+                        scaledHeight : anchorPoint - (midFold - x) * scaledHeight;
+                mDst[2] = isEven ? leftScaledPoint: 0;
+                mDst[3] = (anchorPoint > (x + 1) * mFoldDrawHeight) ? anchorPoint + (x + 1 -
+                        midFold) * scaledHeight : anchorPoint - (midFold - x - 1) * scaledHeight;
+                mDst[4] = isEven ? mFoldDrawWidth : rightScaledPoint;
+                mDst[5] = mDst[1];
+                mDst[6] = isEven ? rightScaledPoint : mFoldDrawWidth;
+                mDst[7] = mDst[3];
+            }
+
+            /* Pixel fractions are present for odd number of folds which need to be
+             * rounded off here.*/
+            for (int y = 0; y < 8; y ++) {
+                mDst[y] = Math.round(mDst[y]);
+            }
+
+            /* If it so happens that any of the folds have reached a point where
+            *  the width or height of that fold is 0, then nothing needs to be
+            *  drawn onto the canvas because the view is essentially completely
+            *  folded.*/
+            if (mIsHorizontal) {
+                if (mDst[4] <= mDst[0] || mDst[6] <= mDst[2]) {
+                    mShouldDraw = false;
+                    return;
+                }
+            } else {
+                if (mDst[3] <= mDst[1] || mDst[7] <= mDst[5]) {
+                    mShouldDraw = false;
+                    return;
+                }
+            }
+
+            /* Sets the shadow and bitmap transformation matrices.*/
+            mMatrix[x].setPolyToPoly(mSrc, 0, mDst, 0, NUM_OF_POLY_POINTS / 2);
+        }
+        /* The shadows on the folds are split into two parts: Solid shadows and gradients.
+         * Every other fold has a solid shadow which overlays the whole fold. Similarly,
+         * the folds in between these alternating folds also have an overlaying shadow.
+         * However, it is a gradient that takes up part of the fold as opposed to a solid
+         * shadow overlaying the whole fold.*/
+
+        /* Solid shadow paint object. */
+        int alpha = (int) (mFoldFactor * 255 * SHADING_ALPHA);
+
+        mSolidShadow.setColor(Color.argb(alpha, 0, 0, 0));
+
+        if (mIsHorizontal) {
+            mShadowGradientMatrix.setScale(mFoldDrawWidth, 1);
+            mShadowLinearGradient.setLocalMatrix(mShadowGradientMatrix);
+        } else {
+            mShadowGradientMatrix.setScale(1, mFoldDrawHeight);
+            mShadowLinearGradient.setLocalMatrix(mShadowGradientMatrix);
+        }
+
+        mGradientShadow.setAlpha(alpha);
+    }
+
+    @Override
+    protected void dispatchDraw(Canvas canvas) {
+        /** If prepareFold has not been called or if preparation has not completed yet,
+         * then no custom drawing will take place so only need to invoke super's
+         * onDraw and return. */
+        if (!mIsFoldPrepared || mFoldFactor == 0) {
+            super.dispatchDraw(canvas);
+            return;
+        }
+
+        if (!mShouldDraw) {
+            return;
+        }
+
+        Rect src;
+         /* Draws the bitmaps and shadows on the canvas with the appropriate transformations. */
+        for (int x = 0; x < mNumberOfFolds; x++) {
+
+            src = mFoldRectArray[x];
+            /* The canvas is saved and restored for every individual fold*/
+            canvas.save();
+
+            /* Concatenates the canvas with the transformation matrix for the
+             *  the segment of the view corresponding to the actual image being
+             *  displayed. */
+            canvas.concat(mMatrix[x]);
+            if (FoldingLayoutActivity.IS_JBMR2) {
+                mDstRect.set(0, 0, src.width(), src.height());
+                canvas.drawBitmap(mFullBitmap, src, mDstRect, null);
+            } else {
+                /* The same transformation matrix is used for both the shadow and the image
+                 * segment. The canvas is clipped to account for the size of each fold and
+                 * is translated so they are drawn in the right place. The shadow is then drawn on
+                 * top of the different folds using the sametransformation matrix.*/
+                canvas.clipRect(0, 0, src.right - src.left, src.bottom - src.top);
+
+                if (mIsHorizontal) {
+                    canvas.translate(-src.left, 0);
+                } else {
+                    canvas.translate(0, -src.top);
+                }
+
+                super.dispatchDraw(canvas);
+
+                if (mIsHorizontal) {
+                    canvas.translate(src.left, 0);
+                } else {
+                    canvas.translate(0, src.top);
+                }
+            }
+            /* Draws the shadows corresponding to this specific fold. */
+            if (x % 2 == 0) {
+                canvas.drawRect(0, 0, mFoldDrawWidth, mFoldDrawHeight, mSolidShadow);
+            } else {
+                canvas.drawRect(0, 0, mFoldDrawWidth, mFoldDrawHeight, mGradientShadow);
+            }
+
+            canvas.restore();
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/samples/devbytes/graphics/FoldingLayout/src/com/example/android/foldinglayout/FoldingLayoutActivity.java b/samples/devbytes/graphics/FoldingLayout/src/com/example/android/foldinglayout/FoldingLayoutActivity.java
new file mode 100644
index 0000000..1a1033d
--- /dev/null
+++ b/samples/devbytes/graphics/FoldingLayout/src/com/example/android/foldinglayout/FoldingLayoutActivity.java
@@ -0,0 +1,429 @@
+/*
+ * Copyright (C) 2013 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.foldinglayout;
+
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.app.Activity;
+import android.graphics.Color;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
+import android.graphics.Paint;
+import android.graphics.SurfaceTexture;
+import android.hardware.Camera;
+import android.os.Build;
+import android.os.Bundle;
+import android.view.GestureDetector;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.TextureView;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.view.animation.AccelerateInterpolator;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.ImageView;
+import android.widget.SeekBar;
+import android.widget.Spinner;
+
+import com.example.android.foldinglayout.FoldingLayout.Orientation;
+
+import java.io.IOException;
+
+/**
+ * This application creates  a paper like folding effect of some view.
+ * The number of folds, orientation (vertical or horizontal) of the fold, and the
+ * anchor point about which the view will fold can be set to achieve different
+ * folding effects.
+ *
+ * Using bitmap and canvas scaling techniques, the foldingLayout can be scaled so as
+ * to depict a paper-like folding effect. The addition of shadows on the separate folds
+ * adds a sense of realism to the visual effect.
+ *
+ * This application shows folding of a TextureView containing a live camera feed,
+ * as well as the folding of an ImageView with a static image. The TextureView experiences
+ * jagged edges as a result of scaling operations on rectangles. The ImageView however
+ * contains a 1 pixel transparent border around its contents which can be used to avoid
+ * this unwanted artifact.
+ */
+public class FoldingLayoutActivity extends Activity {
+
+    private final int ANTIALIAS_PADDING = 1;
+
+    private final int FOLD_ANIMATION_DURATION = 1000;
+
+    /* A bug was introduced in Android 4.3 that ignores changes to the Canvas state
+     * between multiple calls to super.dispatchDraw() when running with hardware acceleration.
+     * To account for this bug, a slightly different approach was taken to fold a
+     * static image whereby a bitmap of the original contents is captured and drawn
+     * in segments onto the canvas. However, this method does not permit the folding
+     * of a TextureView hosting a live camera feed which continuously updates.
+     * Furthermore, the sepia effect was removed from the bitmap variation of the
+     * demo to simplify the logic when running with this workaround."
+     */
+    static final boolean IS_JBMR2 = Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR2;
+
+    private FoldingLayout mFoldLayout;
+    private SeekBar mAnchorSeekBar;
+    private Orientation mOrientation = Orientation.HORIZONTAL;
+
+    private int mTranslation = 0;
+    private int mNumberOfFolds = 2;
+    private int mParentPositionY = -1;
+    private int mTouchSlop = -1;
+
+    private float mAnchorFactor = 0;
+
+    private boolean mDidLoadSpinner = true;
+    private boolean mDidNotStartScroll = true;
+
+    private boolean mIsCameraFeed = false;
+    private boolean mIsSepiaOn = true;
+
+    private GestureDetector mScrollGestureDetector;
+    private ItemSelectedListener mItemSelectedListener;
+
+    private Camera mCamera;
+    private TextureView mTextureView;
+    private ImageView mImageView;
+
+    private Paint mSepiaPaint;
+    private Paint mDefaultPaint;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.activity_fold);
+
+        mImageView = (ImageView)findViewById(R.id.image_view);
+        mImageView.setPadding(ANTIALIAS_PADDING, ANTIALIAS_PADDING, ANTIALIAS_PADDING,
+                ANTIALIAS_PADDING);
+        mImageView.setScaleType(ImageView.ScaleType.FIT_XY);
+        mImageView.setImageDrawable(getResources().getDrawable(R.drawable.image));
+
+        mTextureView = new TextureView(this);
+        mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
+
+        mAnchorSeekBar = (SeekBar)findViewById(R.id.anchor_seek_bar);
+        mFoldLayout = (FoldingLayout)findViewById(R.id.fold_view);
+        mFoldLayout.setBackgroundColor(Color.BLACK);
+        mFoldLayout.setFoldListener(mOnFoldListener);
+
+        mTouchSlop = ViewConfiguration.get(this).getScaledTouchSlop();
+
+        mAnchorSeekBar.setOnSeekBarChangeListener(mSeekBarChangeListener);
+
+        mScrollGestureDetector = new GestureDetector(this, new ScrollGestureDetector());
+        mItemSelectedListener = new ItemSelectedListener();
+
+        mDefaultPaint = new Paint();
+        mSepiaPaint = new Paint();
+
+        ColorMatrix m1 = new ColorMatrix();
+        ColorMatrix m2 = new ColorMatrix();
+        m1.setSaturation(0);
+        m2.setScale(1f, .95f, .82f, 1.0f);
+        m1.setConcat(m2, m1);
+        mSepiaPaint.setColorFilter(new ColorMatrixColorFilter(m1));
+    }
+
+    /**
+     * This listener, along with the setSepiaLayer method below, show a possible use case
+     * of the OnFoldListener provided with the FoldingLayout. This is a fun extra addition
+     * to the demo showing what kind of visual effects can be applied to the child of the
+     * FoldingLayout by setting the layer type to hardware. With a hardware layer type
+     * applied to the child, a paint object can also be applied to the same layer. Using
+     * the concatenation of two different color matrices (above), a color filter was created
+     * which simulates a sepia effect on the layer.*/
+    private OnFoldListener mOnFoldListener =
+            new OnFoldListener() {
+        @Override
+        public void onStartFold() {
+            if (mIsSepiaOn) {
+                setSepiaLayer(mFoldLayout.getChildAt(0), true);
+            }
+        }
+
+        @Override
+        public void onEndFold() {
+            setSepiaLayer(mFoldLayout.getChildAt(0), false);
+        }
+    };
+
+    private void setSepiaLayer (View view, boolean isSepiaLayerOn) {
+        if (!IS_JBMR2) {
+            if (isSepiaLayerOn) {
+                view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+                view.setLayerPaint(mSepiaPaint);
+            } else {
+                view.setLayerPaint(mDefaultPaint);
+            }
+        }
+    }
+
+    /**
+     * Creates a SurfaceTextureListener in order to prepare a TextureView
+     * which displays a live, and continuously updated, feed from the Camera.
+     */
+    private TextureView.SurfaceTextureListener mSurfaceTextureListener = new TextureView
+            .SurfaceTextureListener() {
+        @Override
+        public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i2) {
+            mCamera = Camera.open();
+
+            if (mCamera == null && Camera.getNumberOfCameras() > 1) {
+                mCamera = mCamera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
+            }
+
+            if (mCamera == null) {
+                return;
+            }
+
+            try {
+                mCamera.setPreviewTexture(surfaceTexture);
+                mCamera.setDisplayOrientation(90);
+                mCamera.startPreview();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+
+        @Override
+        public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i2) {
+            // Ignored, Camera does all the work for us
+        }
+
+        @Override
+        public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
+            if (mCamera != null) {
+                mCamera.stopPreview();
+                mCamera.release();
+            }
+            return true;
+        }
+
+        @Override
+        public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
+            // Invoked every time there's a new Camera preview frame
+        }
+    };
+
+    /**
+     * A listener for scrolling changes in the seekbar. The anchor point of the folding
+     * view is updated every time the seekbar stops tracking touch events. Every time the
+     * anchor point is updated, the folding view is restored to a default unfolded state.
+     */
+    private SeekBar.OnSeekBarChangeListener mSeekBarChangeListener = new SeekBar
+            .OnSeekBarChangeListener() {
+        @Override
+        public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
+        }
+
+        @Override
+        public void onStartTrackingTouch(SeekBar seekBar) {
+        }
+
+        @Override
+        public void onStopTrackingTouch(SeekBar seekBar) {
+            mTranslation = 0;
+            mAnchorFactor = ((float)mAnchorSeekBar.getProgress())/100.0f;
+            mFoldLayout.setAnchorFactor(mAnchorFactor);
+        }
+    };
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        if (IS_JBMR2) {
+            getMenuInflater().inflate(R.menu.fold_with_bug, menu);
+        } else {
+            getMenuInflater().inflate(R.menu.fold, menu);
+        }
+        Spinner s = (Spinner) menu.findItem(R.id.num_of_folds).getActionView();
+        s.setOnItemSelectedListener(mItemSelectedListener);
+        return true;
+    }
+
+    @Override
+    public void onWindowFocusChanged (boolean hasFocus) {
+        super.onWindowFocusChanged(hasFocus);
+
+        int[] loc = new int[2];
+        mFoldLayout.getLocationOnScreen(loc);
+        mParentPositionY = loc[1];
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent me) {
+        return mScrollGestureDetector.onTouchEvent(me);
+    }
+
+    @Override
+    public boolean onOptionsItemSelected (MenuItem item) {
+        switch(item.getItemId()) {
+            case R.id.animate_fold:
+                animateFold();
+                break;
+            case R.id.toggle_orientation:
+                mOrientation = (mOrientation == Orientation.HORIZONTAL) ? Orientation.VERTICAL :
+                        Orientation.HORIZONTAL;
+                item.setTitle((mOrientation == Orientation.HORIZONTAL) ? R.string.vertical :
+                R.string.horizontal);
+                mTranslation = 0;
+                mFoldLayout.setOrientation(mOrientation);
+                break;
+            case R.id.camera_feed:
+                mIsCameraFeed = !mIsCameraFeed;
+                item.setTitle(mIsCameraFeed ? R.string.static_image : R.string.camera_feed);
+                item.setChecked(mIsCameraFeed);
+                if (mIsCameraFeed) {
+                    mFoldLayout.removeView(mImageView);
+                    mFoldLayout.addView(mTextureView, new ViewGroup.LayoutParams(
+                            mFoldLayout.getWidth(), mFoldLayout.getHeight()));
+                } else {
+                    mFoldLayout.removeView(mTextureView);
+                    mFoldLayout.addView(mImageView, new ViewGroup.LayoutParams(
+                            mFoldLayout.getWidth(), mFoldLayout.getHeight()));
+                }
+                mTranslation = 0;
+                break;
+            case R.id.sepia:
+                mIsSepiaOn = !mIsSepiaOn;
+                item.setChecked(!mIsSepiaOn);
+                if (mIsSepiaOn && mFoldLayout.getFoldFactor() != 0) {
+                    setSepiaLayer(mFoldLayout.getChildAt(0), true);
+                } else {
+                    setSepiaLayer(mFoldLayout.getChildAt(0), false);
+                }
+                break;
+            default:
+               break;
+
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
+    /**
+     * Animates the folding view inwards (to a completely folded state) from its
+     * current state and then back out to its original state.
+     */
+    public void animateFold ()
+    {
+        float foldFactor = mFoldLayout.getFoldFactor();
+
+        ObjectAnimator animator = ObjectAnimator.ofFloat(mFoldLayout, "foldFactor", foldFactor, 1);
+        animator.setRepeatMode(ValueAnimator.REVERSE);
+        animator.setRepeatCount(1);
+        animator.setDuration(FOLD_ANIMATION_DURATION);
+        animator.setInterpolator(new AccelerateInterpolator());
+        animator.start();
+    }
+
+    /**
+     * Listens for selection events of the spinner located on the action bar. Every
+     * time a new value is selected, the number of folds in the folding view is updated
+     * and is also restored to a default unfolded state.
+     */
+    private class ItemSelectedListener implements OnItemSelectedListener {
+        @Override
+        public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+            mNumberOfFolds = Integer.parseInt(parent.getItemAtPosition(pos).toString());
+            if (mDidLoadSpinner) {
+                mDidLoadSpinner = false;
+            } else {
+                mTranslation = 0;
+                mFoldLayout.setNumberOfFolds(mNumberOfFolds);
+            }
+        }
+
+        @Override
+        public void onNothingSelected(AdapterView<?> arg0) {
+        }
+    }
+
+    /** This class uses user touch events to fold and unfold the folding view. */
+    private class ScrollGestureDetector extends GestureDetector.SimpleOnGestureListener {
+        @Override
+        public boolean onDown (MotionEvent e) {
+            mDidNotStartScroll = true;
+            return true;
+        }
+
+        /**
+         * All the logic here is used to determine by what factor the paper view should
+         * be folded in response to the user's touch events. The logic here uses vertical
+         * scrolling to fold a vertically oriented view and horizontal scrolling to fold
+         * a horizontally oriented fold. Depending on where the anchor point of the fold is,
+         * movements towards or away from the anchor point will either fold or unfold
+         * the paper respectively.
+         *
+         * The translation logic here also accounts for the touch slop when a new user touch
+         * begins, but before a scroll event is first invoked.
+         */
+        @Override
+        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
+            int touchSlop = 0;
+            float factor;
+            if (mOrientation == Orientation.VERTICAL) {
+                factor = Math.abs((float)(mTranslation) / (float)(mFoldLayout.getHeight()));
+
+                if (e2.getY() - mParentPositionY <= mFoldLayout.getHeight()
+                        && e2.getY() - mParentPositionY >= 0) {
+                    if ((e2.getY() - mParentPositionY) > mFoldLayout.getHeight() * mAnchorFactor) {
+                        mTranslation -= (int)distanceY;
+                        touchSlop = distanceY < 0 ? -mTouchSlop : mTouchSlop;
+                    } else {
+                        mTranslation += (int)distanceY;
+                        touchSlop = distanceY < 0 ? mTouchSlop : -mTouchSlop;
+                    }
+                    mTranslation = mDidNotStartScroll ? mTranslation + touchSlop : mTranslation;
+
+                    if (mTranslation < -mFoldLayout.getHeight()) {
+                        mTranslation = -mFoldLayout.getHeight();
+                    }
+                }
+            } else {
+                factor = Math.abs(((float)mTranslation) / ((float) mFoldLayout.getWidth()));
+
+                if (e2.getRawX() > mFoldLayout.getWidth() * mAnchorFactor) {
+                    mTranslation -= (int)distanceX;
+                    touchSlop = distanceX < 0 ? -mTouchSlop : mTouchSlop;
+                } else {
+                    mTranslation += (int)distanceX;
+                    touchSlop = distanceX < 0 ? mTouchSlop : -mTouchSlop;
+                }
+                mTranslation = mDidNotStartScroll ? mTranslation + touchSlop : mTranslation;
+
+                if (mTranslation < -mFoldLayout.getWidth()) {
+                    mTranslation = -mFoldLayout.getWidth();
+                }
+            }
+
+            mDidNotStartScroll = false;
+
+            if (mTranslation > 0) {
+                mTranslation = 0;
+            }
+
+            mFoldLayout.setFoldFactor(factor);
+
+            return true;
+        }
+    }
+}
\ No newline at end of file
diff --git a/samples/devbytes/graphics/FoldingLayout/src/com/example/android/foldinglayout/OnFoldListener.java b/samples/devbytes/graphics/FoldingLayout/src/com/example/android/foldinglayout/OnFoldListener.java
new file mode 100644
index 0000000..a305568
--- /dev/null
+++ b/samples/devbytes/graphics/FoldingLayout/src/com/example/android/foldinglayout/OnFoldListener.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2013 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.foldinglayout;
+
+/**
+ * This interface listens for when the folding layout begins folding (enters
+ * a folded state from a completely unfolded state), or ends folding (enters a
+ * completely unfolded state from a folded state).
+ */
+public interface OnFoldListener {
+    public void onStartFold();
+    public void onEndFold();
+}
diff --git a/samples/devbytes/graphics/ImagePixelization/AndroidManifest.xml b/samples/devbytes/graphics/ImagePixelization/AndroidManifest.xml
new file mode 100644
index 0000000..7bbb4f6
--- /dev/null
+++ b/samples/devbytes/graphics/ImagePixelization/AndroidManifest.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.example.android.imagepixelization"
+          android:versionCode="1"
+          android:versionName="1.0">
+    <uses-sdk android:minSdkVersion="11"
+              android:targetSdkVersion="17"/>
+    <application android:label="@string/app_name" android:icon="@drawable/ic_launcher">
+        <activity android:name=".ImagePixelization"
+                  android:label="@string/app_name">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/samples/devbytes/graphics/ImagePixelization/res/drawable-hdpi/ic_launcher.png b/samples/devbytes/graphics/ImagePixelization/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..96a442e
--- /dev/null
+++ b/samples/devbytes/graphics/ImagePixelization/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/graphics/ImagePixelization/res/drawable-hdpi/image.jpg b/samples/devbytes/graphics/ImagePixelization/res/drawable-hdpi/image.jpg
new file mode 100644
index 0000000..00bdbba
--- /dev/null
+++ b/samples/devbytes/graphics/ImagePixelization/res/drawable-hdpi/image.jpg
Binary files differ
diff --git a/samples/devbytes/graphics/ImagePixelization/res/drawable-ldpi/ic_launcher.png b/samples/devbytes/graphics/ImagePixelization/res/drawable-ldpi/ic_launcher.png
new file mode 100644
index 0000000..9923872
--- /dev/null
+++ b/samples/devbytes/graphics/ImagePixelization/res/drawable-ldpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/graphics/ImagePixelization/res/drawable-mdpi/ic_launcher.png b/samples/devbytes/graphics/ImagePixelization/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..359047d
--- /dev/null
+++ b/samples/devbytes/graphics/ImagePixelization/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/graphics/ImagePixelization/res/drawable-xhdpi/ic_launcher.png b/samples/devbytes/graphics/ImagePixelization/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..71c6d76
--- /dev/null
+++ b/samples/devbytes/graphics/ImagePixelization/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/devbytes/graphics/ImagePixelization/res/layout/activity_image_pixelization.xml b/samples/devbytes/graphics/ImagePixelization/res/layout/activity_image_pixelization.xml
new file mode 100644
index 0000000..b3e30a8
--- /dev/null
+++ b/samples/devbytes/graphics/ImagePixelization/res/layout/activity_image_pixelization.xml
@@ -0,0 +1,42 @@
+<!-- Copyright (C) 2013 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.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                xmlns:tools="http://schemas.android.com/tools"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:paddingLeft="@dimen/activity_horizontal_margin"
+                android:paddingRight="@dimen/activity_horizontal_margin"
+                android:paddingTop="@dimen/activity_vertical_margin"
+                android:orientation="vertical">
+
+        <ImageView
+                android:id="@+id/pixelView"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_alignParentTop="true"
+                android:layout_above="@+id/seekbar"
+                android:scaleType="fitXY"/>
+
+        <SeekBar
+                android:id="@+id/seekbar"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_margin="10dp"
+                android:max="@integer/seek_max"
+                android:progress="0"
+                android:layout_alignParentBottom = "true"/>
+
+</RelativeLayout>
+
diff --git a/samples/devbytes/graphics/ImagePixelization/res/menu/image_pixelization.xml b/samples/devbytes/graphics/ImagePixelization/res/menu/image_pixelization.xml
new file mode 100644
index 0000000..e6a8d66
--- /dev/null
+++ b/samples/devbytes/graphics/ImagePixelization/res/menu/image_pixelization.xml
@@ -0,0 +1,31 @@
+<!-- Copyright (C) 2013 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.
+-->
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <item   android:id="@+id/builtin_pixelation_checkbox"
+            android:showAsAction="never"
+            android:title="@string/builtin_pixelization"
+            android:checkable="true" />
+
+    <item   android:id="@+id/checkbox"
+            android:showAsAction="never"
+            android:title="@string/async_task"
+            android:checkable="true" />
+
+    <item   android:id="@+id/animate"
+            android:showAsAction="never"
+            android:title="@string/animate_pixelation"/>
+
+</menu>
\ No newline at end of file
diff --git a/samples/devbytes/graphics/ImagePixelization/res/values/dimens.xml b/samples/devbytes/graphics/ImagePixelization/res/values/dimens.xml
new file mode 100644
index 0000000..09d93f5
--- /dev/null
+++ b/samples/devbytes/graphics/ImagePixelization/res/values/dimens.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <dimen name="activity_horizontal_margin">16dp</dimen>
+    <dimen name="activity_vertical_margin">16dp</dimen>
+
+</resources>
diff --git a/samples/devbytes/graphics/ImagePixelization/res/values/integers.xml b/samples/devbytes/graphics/ImagePixelization/res/values/integers.xml
new file mode 100644
index 0000000..98c1438
--- /dev/null
+++ b/samples/devbytes/graphics/ImagePixelization/res/values/integers.xml
@@ -0,0 +1,19 @@
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+     <integer name="seek_max">1000</integer>
+
+</resources>
diff --git a/samples/devbytes/graphics/ImagePixelization/res/values/strings.xml b/samples/devbytes/graphics/ImagePixelization/res/values/strings.xml
new file mode 100644
index 0000000..35a87c8
--- /dev/null
+++ b/samples/devbytes/graphics/ImagePixelization/res/values/strings.xml
@@ -0,0 +1,22 @@
+<!-- Copyright (C) 2013 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.
+-->
+<resources>
+
+    <string name="app_name" >ImagePixelization</string>
+    <string name="animate_pixelation">Animate</string>
+    <string name="async_task">Using AyncTask</string>
+    <string name="builtin_pixelization">Built-in Pixelization</string>
+
+</resources>
diff --git a/samples/devbytes/graphics/ImagePixelization/src/com/example/android/imagepixelization/ImagePixelization.java b/samples/devbytes/graphics/ImagePixelization/src/com/example/android/imagepixelization/ImagePixelization.java
new file mode 100644
index 0000000..e31d95d
--- /dev/null
+++ b/samples/devbytes/graphics/ImagePixelization/src/com/example/android/imagepixelization/ImagePixelization.java
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2013 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.imagepixelization;
+
+import android.animation.ObjectAnimator;
+import android.app.Activity;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Color;
+import android.graphics.drawable.BitmapDrawable;
+import android.os.AsyncTask;
+import android.os.Build;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.animation.LinearInterpolator;
+import android.widget.ImageView;
+import android.widget.SeekBar;
+
+import java.util.Arrays;
+
+/**
+ * This application shows three different graphics/animation concepts.
+ *
+ * A pixelization effect is applied to an image with varying pixelization
+ * factors to achieve an image that is pixelized to varying degrees. In
+ * order to optimize the amount of image processing performed on the image
+ * being pixelized, the pixelization effect only takes place if a predefined
+ * amount of time has elapsed since the main image was last pixelized. The
+ * effect is also applied when the user stops moving the seekbar.
+ *
+ * This application also shows how to use a ValueAnimator to achieve a
+ * smooth self-animating seekbar.
+ *
+ * Lastly, this application shows a use case of AsyncTask where some
+ * computation heavy processing can be moved onto a background thread,
+ * so as to keep the UI completely responsive to user input.
+ */
+public class ImagePixelization extends Activity {
+
+    final private static int SEEKBAR_ANIMATION_DURATION = 10000;
+    final private static int TIME_BETWEEN_TASKS = 400;
+    final private static int SEEKBAR_STOP_CHANGE_DELTA = 5;
+    final private static float PROGRESS_TO_PIXELIZATION_FACTOR = 4000.0f;
+
+    Bitmap mImageBitmap;
+    ImageView mImageView;
+    SeekBar mSeekBar;
+    boolean mIsChecked = false;
+    boolean mIsBuiltinPixelizationChecked = false;
+    int mLastProgress = 0;
+    long mLastTime = 0;
+    Bitmap mPixelatedBitmap;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_image_pixelization);
+
+        mImageView = (ImageView) findViewById(R.id.pixelView);
+        mSeekBar = (SeekBar)findViewById(R.id.seekbar);
+
+        mImageBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image);
+        mImageView.setImageBitmap(mImageBitmap);
+
+        mSeekBar.setOnSeekBarChangeListener(mOnSeekBarChangeListener);
+    }
+
+    private SeekBar.OnSeekBarChangeListener mOnSeekBarChangeListener =
+            new SeekBar.OnSeekBarChangeListener() {
+
+        @Override
+        public void onStopTrackingTouch(SeekBar seekBar) {
+            if (Math.abs(mSeekBar.getProgress() - mLastProgress) > SEEKBAR_STOP_CHANGE_DELTA) {
+                invokePixelization();
+            }
+        }
+
+        @Override
+        public void onStartTrackingTouch(SeekBar seekBar) {
+        }
+
+        @Override
+        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+            checkIfShouldPixelize();
+        }
+    };
+
+    /**
+     * Checks if enough time has elapsed since the last pixelization call was invoked.
+     * This prevents too many pixelization processes from being invoked at the same time
+     * while previous ones have not yet completed.
+     */
+    public void checkIfShouldPixelize() {
+        if ((System.currentTimeMillis() - mLastTime) > TIME_BETWEEN_TASKS) {
+            invokePixelization();
+        }
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        getMenuInflater().inflate(R.menu.image_pixelization, menu);
+        return true;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected (MenuItem item) {
+        switch (item.getItemId()){
+            case R.id.animate:
+                ObjectAnimator animator = ObjectAnimator.ofInt(mSeekBar, "progress", 0,
+                        mSeekBar.getMax());
+                animator.setInterpolator(new LinearInterpolator());
+                animator.setDuration(SEEKBAR_ANIMATION_DURATION);
+                animator.start();
+                break;
+            case R.id.checkbox:
+                if (mIsChecked) {
+                    item.setChecked(false);
+                    mIsChecked = false;
+                } else {
+                    item.setChecked(true);
+                    mIsChecked = true;
+                }
+                break;
+            case R.id.builtin_pixelation_checkbox:
+                mIsBuiltinPixelizationChecked = !mIsBuiltinPixelizationChecked;
+                item.setChecked(mIsBuiltinPixelizationChecked);
+                break;
+            default:
+                break;
+        }
+        return true;
+    }
+
+    /**
+     * A simple pixelization algorithm. This uses a box blur algorithm where all the
+     * pixels within some region are averaged, and that average pixel value is then
+     * applied to all the pixels within that region. A higher pixelization factor
+     * imposes a smaller number of regions of greater size. Similarly, a smaller
+     * pixelization factor imposes a larger number of regions of smaller size.
+     */
+    public BitmapDrawable customImagePixelization(float pixelizationFactor, Bitmap bitmap) {
+
+        int width = bitmap.getWidth();
+        int height = bitmap.getHeight();
+
+        if (mPixelatedBitmap == null || !(width == mPixelatedBitmap.getWidth() && height ==
+                mPixelatedBitmap.getHeight())) {
+            mPixelatedBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+        }
+
+        int xPixels = (int) (pixelizationFactor * ((float)width));
+        xPixels = xPixels > 0 ? xPixels : 1;
+        int yPixels = (int)  (pixelizationFactor * ((float)height));
+        yPixels = yPixels > 0 ? yPixels : 1;
+        int pixel = 0, red = 0, green = 0, blue = 0, numPixels = 0;
+
+        int[] bitmapPixels = new int[width * height];
+        bitmap.getPixels(bitmapPixels, 0, width, 0, 0, width, height);
+
+        int[] pixels = new int[yPixels * xPixels];
+
+        int maxX, maxY;
+
+        for (int y = 0; y < height; y+=yPixels) {
+            for (int x = 0; x < width; x+=xPixels) {
+
+                numPixels = red = green = blue = 0;
+
+                maxX = Math.min(x + xPixels, width);
+                maxY = Math.min(y + yPixels, height);
+
+                for (int i = x; i < maxX; i++) {
+                    for (int j = y; j < maxY; j++) {
+                        pixel = bitmapPixels[j * width + i];
+                        red += Color.red(pixel);
+                        green += Color.green(pixel);
+                        blue += Color.blue(pixel);
+                        numPixels ++;
+                    }
+                }
+
+                pixel = Color.rgb(red / numPixels, green / numPixels, blue / numPixels);
+
+                Arrays.fill(pixels, pixel);
+
+                int w = Math.min(xPixels, width - x);
+                int h = Math.min(yPixels, height - y);
+
+                mPixelatedBitmap.setPixels(pixels, 0 , w, x , y, w, h);
+            }
+        }
+
+        return new BitmapDrawable(getResources(), mPixelatedBitmap);
+    }
+
+    /**
+     * This method of image pixelization utilizes the bitmap scaling operations built
+     * into the framework. By downscaling the bitmap and upscaling it back to its
+     * original size (while setting the filter flag to false), the same effect can be
+     * achieved with much better performance.
+     */
+    public BitmapDrawable builtInPixelization(float pixelizationFactor, Bitmap bitmap) {
+
+        int width = bitmap.getWidth();
+        int height = bitmap.getHeight();
+
+        int downScaleFactorWidth = (int)(pixelizationFactor * width);
+        downScaleFactorWidth = downScaleFactorWidth > 0 ? downScaleFactorWidth : 1;
+        int downScaleFactorHeight = (int)(pixelizationFactor * height);
+        downScaleFactorHeight = downScaleFactorHeight > 0 ? downScaleFactorHeight : 1;
+
+        int downScaledWidth =  width / downScaleFactorWidth;
+        int downScaledHeight = height / downScaleFactorHeight;
+
+        Bitmap pixelatedBitmap = Bitmap.createScaledBitmap(bitmap, downScaledWidth,
+                downScaledHeight, false);
+
+        /* Bitmap's createScaledBitmap method has a filter parameter that can be set to either
+         * true or false in order to specify either bilinear filtering or point sampling
+         * respectively when the bitmap is scaled up or now.
+         *
+         * Similarly, a BitmapDrawable also has a flag to specify the same thing. When the
+         * BitmapDrawable is applied to an ImageView that has some scaleType, the filtering
+         * flag is taken into consideration. However, for optimization purposes, this flag was
+         * ignored in BitmapDrawables before Jelly Bean MR1.
+         *
+         * Here, it is important to note that prior to JBMR1, two bitmap scaling operations
+         * are required to achieve the pixelization effect. Otherwise, a BitmapDrawable
+         * can be created corresponding to the downscaled bitmap such that when it is
+         * upscaled to fit the ImageView, the upscaling operation is a lot faster since
+         * it uses internal optimizations to fit the ImageView.
+         * */
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+            BitmapDrawable bitmapDrawable = new BitmapDrawable(getResources(), pixelatedBitmap);
+            bitmapDrawable.setFilterBitmap(false);
+            return bitmapDrawable;
+        } else {
+            Bitmap upscaled = Bitmap.createScaledBitmap(pixelatedBitmap, width, height, false);
+            return new BitmapDrawable(getResources(), upscaled);
+        }
+    }
+
+    /**
+     * Invokes pixelization either on the main thread or on a background thread
+     * depending on whether or not the checkbox was checked.
+     */
+    public void invokePixelization () {
+        mLastTime = System.currentTimeMillis();
+        mLastProgress = mSeekBar.getProgress();
+        if (mIsChecked) {
+            PixelizeImageAsyncTask asyncPixelateTask = new PixelizeImageAsyncTask();
+            asyncPixelateTask.execute(mSeekBar.getProgress() / PROGRESS_TO_PIXELIZATION_FACTOR,
+                    mImageBitmap);
+        } else {
+            mImageView.setImageDrawable(pixelizeImage(mSeekBar.getProgress()
+                    / PROGRESS_TO_PIXELIZATION_FACTOR, mImageBitmap));
+        }
+    }
+
+    /**
+     *  Selects either the custom pixelization algorithm that sets and gets bitmap
+     *  pixels manually or the one that uses built-in bitmap operations.
+     */
+    public BitmapDrawable pixelizeImage(float pixelizationFactor, Bitmap bitmap) {
+        if (mIsBuiltinPixelizationChecked) {
+            return builtInPixelization(pixelizationFactor, bitmap);
+        } else {
+            return customImagePixelization(pixelizationFactor, bitmap);
+        }
+    }
+
+    /**
+     * Implementation of the AsyncTask class showing how to run the
+     * pixelization algorithm in the background, and retrieving the
+     * pixelated image from the resulting operation.
+     */
+    private class PixelizeImageAsyncTask extends AsyncTask<Object, Void, BitmapDrawable> {
+
+        @Override
+        protected BitmapDrawable doInBackground(Object... params) {
+            float pixelizationFactor = (Float)params[0];
+            Bitmap originalBitmap = (Bitmap)params[1];
+            return pixelizeImage(pixelizationFactor, originalBitmap);
+        }
+
+        @Override
+        protected void onPostExecute(BitmapDrawable result) {
+            mImageView.setImageDrawable(result);
+        }
+
+        @Override
+        protected void onPreExecute() {
+
+        }
+
+        @Override
+        protected void onProgressUpdate(Void... values) {
+
+        }
+    }
+}
\ No newline at end of file
diff --git a/samples/training/testingfun/app/AndroidManifest.xml b/samples/training/testingfun/app/AndroidManifest.xml
new file mode 100644
index 0000000..a71247a
--- /dev/null
+++ b/samples/training/testingfun/app/AndroidManifest.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  Copyright (C) 2013 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.
+  -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.android.testingfun"
+    android:versionCode="1"
+    android:versionName="1.0">
+
+    <uses-sdk
+        android:minSdkVersion="8"
+        android:targetSdkVersion="17" />
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/ic_launcher"
+        android:theme="@style/AppTheme"
+        android:allowBackup="false">
+
+        <activity
+            android:name=".lesson2.MyFirstTestActivity"
+            android:label="@string/my_first_test">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <activity
+            android:name=".lesson3.ClickFunActivity"
+            android:label="@string/click_fun">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <activity
+            android:name=".lesson4.LaunchActivity"
+            android:label="@string/launch_next">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <activity
+            android:name=".lesson4.NextActivity"
+            android:label="@string/next_activity" />
+        <activity
+            android:name=".lesson5.SenderActivity"
+            android:label="@string/sender_activity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <activity
+            android:name=".lesson5.ReceiverActivity"
+            android:label="@string/receiver_activity" />
+    </application>
+</manifest>
diff --git a/samples/training/testingfun/app/build.gradle b/samples/training/testingfun/app/build.gradle
new file mode 100644
index 0000000..c68484f
--- /dev/null
+++ b/samples/training/testingfun/app/build.gradle
@@ -0,0 +1,27 @@
+apply plugin: 'android'
+
+android {
+    compileSdkVersion 17
+    buildToolsVersion "17.0.0"
+
+    defaultConfig {
+        minSdkVersion 8
+    }
+
+    android {
+        sourceSets {
+            main {
+                manifest.srcFile 'AndroidManifest.xml'
+                java.srcDirs = ['src']
+                resources.srcDirs = ['src']
+                aild.srcDirs = ['src']
+                renderscript.srcDirs = ['src']
+                res.srcDirs = ['res']
+                assets.srcDirs = ['assets']
+            }
+
+            instrumentTest.setRoot('tests')
+            instrumentTest.java.srcDirs = ['tests/src']
+        }
+    }
+}
\ No newline at end of file
diff --git a/samples/training/testingfun/app/project.properties b/samples/training/testingfun/app/project.properties
new file mode 100644
index 0000000..a3ee5ab
--- /dev/null
+++ b/samples/training/testingfun/app/project.properties
@@ -0,0 +1,14 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-17
diff --git a/samples/training/testingfun/app/res/drawable-hdpi/ic_launcher.png b/samples/training/testingfun/app/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..136343e
--- /dev/null
+++ b/samples/training/testingfun/app/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/training/testingfun/app/res/drawable-mdpi/ic_launcher.png b/samples/training/testingfun/app/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..6837266
--- /dev/null
+++ b/samples/training/testingfun/app/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/training/testingfun/app/res/drawable-xhdpi/ic_launcher.png b/samples/training/testingfun/app/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..e88e975
--- /dev/null
+++ b/samples/training/testingfun/app/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/training/testingfun/app/res/drawable-xxhdpi/ic_launcher.png b/samples/training/testingfun/app/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..ac31a90
--- /dev/null
+++ b/samples/training/testingfun/app/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/training/testingfun/app/res/layout/activity_click_fun.xml b/samples/training/testingfun/app/res/layout/activity_click_fun.xml
new file mode 100644
index 0000000..c960c3b
--- /dev/null
+++ b/samples/training/testingfun/app/res/layout/activity_click_fun.xml
@@ -0,0 +1,32 @@
+<!--
+  Copyright (C) 2013 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="match_parent">
+
+    <Button
+        android:id="@+id/launch_next_activity_button"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/label_click_me" />
+
+    <TextView
+        android:id="@+id/info_text_view"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:visibility="gone" />
+</LinearLayout>
\ No newline at end of file
diff --git a/samples/training/testingfun/app/res/layout/activity_launch_next.xml b/samples/training/testingfun/app/res/layout/activity_launch_next.xml
new file mode 100644
index 0000000..cfd0114
--- /dev/null
+++ b/samples/training/testingfun/app/res/layout/activity_launch_next.xml
@@ -0,0 +1,25 @@
+<!--
+  Copyright (C) 2013 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.
+  -->
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <Button
+        android:id="@+id/launch_next_activity_button"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/label_launch_next" />
+</merge>
\ No newline at end of file
diff --git a/samples/training/testingfun/app/res/layout/activity_my_first_test.xml b/samples/training/testingfun/app/res/layout/activity_my_first_test.xml
new file mode 100644
index 0000000..3499bc7
--- /dev/null
+++ b/samples/training/testingfun/app/res/layout/activity_my_first_test.xml
@@ -0,0 +1,27 @@
+<!--
+  Copyright (C) 2013 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="match_parent">
+
+    <TextView
+        android:id="@+id/my_first_test_text_view"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/my_first_test" />
+</LinearLayout>
+
diff --git a/samples/training/testingfun/app/res/layout/activity_next.xml b/samples/training/testingfun/app/res/layout/activity_next.xml
new file mode 100644
index 0000000..92f30f7
--- /dev/null
+++ b/samples/training/testingfun/app/res/layout/activity_next.xml
@@ -0,0 +1,25 @@
+<!--
+  Copyright (C) 2013 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.
+  -->
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <TextView
+        android:id="@+id/next_activity_info_text_view"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" />
+
+</merge>
\ No newline at end of file
diff --git a/samples/training/testingfun/app/res/layout/activity_receiver.xml b/samples/training/testingfun/app/res/layout/activity_receiver.xml
new file mode 100644
index 0000000..e93d16b
--- /dev/null
+++ b/samples/training/testingfun/app/res/layout/activity_receiver.xml
@@ -0,0 +1,25 @@
+<!--
+  Copyright (C) 2013 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.
+  -->
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <TextView
+        android:id="@+id/received_message_text_view"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" />
+
+</merge>
\ No newline at end of file
diff --git a/samples/training/testingfun/app/res/layout/activity_sender.xml b/samples/training/testingfun/app/res/layout/activity_sender.xml
new file mode 100644
index 0000000..e18f4c4
--- /dev/null
+++ b/samples/training/testingfun/app/res/layout/activity_sender.xml
@@ -0,0 +1,33 @@
+<!--
+  Copyright (C) 2013 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="match_parent">
+
+    <EditText
+        android:id="@+id/message_input_edit_text"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:hint="@string/message_input_hint_edit_text" />
+
+    <Button
+        android:id="@+id/send_message_button"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/label_send_message" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/samples/training/testingfun/app/res/values-sw720dp-land/dimens.xml b/samples/training/testingfun/app/res/values-sw720dp-land/dimens.xml
new file mode 100644
index 0000000..3201e93
--- /dev/null
+++ b/samples/training/testingfun/app/res/values-sw720dp-land/dimens.xml
@@ -0,0 +1,18 @@
+<!--
+  Copyright (C) 2013 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.
+  -->
+<resources>
+    <dimen name="activity_horizontal_margin">128dp</dimen>
+</resources>
diff --git a/samples/training/testingfun/app/res/values-v11/styles.xml b/samples/training/testingfun/app/res/values-v11/styles.xml
new file mode 100644
index 0000000..90ff160
--- /dev/null
+++ b/samples/training/testingfun/app/res/values-v11/styles.xml
@@ -0,0 +1,18 @@
+<!--
+  Copyright (C) 2013 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.
+  -->
+<resources>
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar" />
+</resources>
diff --git a/samples/training/testingfun/app/res/values-v14/styles.xml b/samples/training/testingfun/app/res/values-v14/styles.xml
new file mode 100644
index 0000000..90ff160
--- /dev/null
+++ b/samples/training/testingfun/app/res/values-v14/styles.xml
@@ -0,0 +1,18 @@
+<!--
+  Copyright (C) 2013 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.
+  -->
+<resources>
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar" />
+</resources>
diff --git a/samples/training/testingfun/app/res/values/dimens.xml b/samples/training/testingfun/app/res/values/dimens.xml
new file mode 100644
index 0000000..e96acda
--- /dev/null
+++ b/samples/training/testingfun/app/res/values/dimens.xml
@@ -0,0 +1,19 @@
+<!--
+  Copyright (C) 2013 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.
+  -->
+<resources>
+    <dimen name="activity_horizontal_margin">16dp</dimen>
+    <dimen name="activity_vertical_margin">16dp</dimen>
+</resources>
diff --git a/samples/training/testingfun/app/res/values/strings.xml b/samples/training/testingfun/app/res/values/strings.xml
new file mode 100644
index 0000000..1fc3bc0
--- /dev/null
+++ b/samples/training/testingfun/app/res/values/strings.xml
@@ -0,0 +1,34 @@
+<!--
+  Copyright (C) 2013 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.
+  -->
+<resources>
+    <string name="app_name">Android Testing Fun</string>
+
+    <string name="my_first_test">My First Test</string>
+
+    <string name="click_fun">Click Fun Test</string>
+    <string name="label_click_me">Click me</string>
+
+    <string name="launch_next">Launch Activity</string>
+    <string name="next_activity">Next Activity</string>
+
+    <string name="sender_activity">Sender Activity</string>
+    <string name="receiver_activity">Receiver Activity</string>
+
+    <string name="info_text">Button clicked!</string>
+    <string name="label_launch_next">Launch Next</string>
+    <string name="label_send_message">Send</string>
+    <string name="message_input_hint_edit_text">Enter a message</string>
+</resources>
diff --git a/samples/training/testingfun/app/res/values/styles.xml b/samples/training/testingfun/app/res/values/styles.xml
new file mode 100644
index 0000000..fa3d1bd
--- /dev/null
+++ b/samples/training/testingfun/app/res/values/styles.xml
@@ -0,0 +1,20 @@
+<!--
+  Copyright (C) 2013 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.
+  -->
+<resources>
+    <style name="AppBaseTheme" parent="android:Theme.Light" />
+
+    <style name="AppTheme" parent="AppBaseTheme" />
+</resources>
diff --git a/samples/training/testingfun/app/src/com/example/android/testingfun/lesson2/MyFirstTestActivity.java b/samples/training/testingfun/app/src/com/example/android/testingfun/lesson2/MyFirstTestActivity.java
new file mode 100644
index 0000000..db977cf
--- /dev/null
+++ b/samples/training/testingfun/app/src/com/example/android/testingfun/lesson2/MyFirstTestActivity.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2013 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.testingfun.lesson2;
+
+import com.example.android.testingfun.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * Activity with a TextView that contains a String label.
+ */
+public class MyFirstTestActivity extends Activity {
+
+    /**
+     * Called when the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_my_first_test);
+    }
+}
diff --git a/samples/training/testingfun/app/src/com/example/android/testingfun/lesson3/ClickFunActivity.java b/samples/training/testingfun/app/src/com/example/android/testingfun/lesson3/ClickFunActivity.java
new file mode 100644
index 0000000..09db694
--- /dev/null
+++ b/samples/training/testingfun/app/src/com/example/android/testingfun/lesson3/ClickFunActivity.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2013 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.testingfun.lesson3;
+
+import com.example.android.testingfun.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+
+/**
+ * Activity which shows a "click me" button. When the button is clicked, a TextView is shown below
+ * the button.
+ */
+public class ClickFunActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_click_fun);
+
+        final TextView infoTextView = (TextView) findViewById(R.id.info_text_view);
+        final Button clickMeButton = (Button) findViewById(R.id.launch_next_activity_button);
+        clickMeButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                infoTextView.setVisibility(View.VISIBLE);
+                infoTextView.setText(getString(R.string.info_text));
+            }
+        });
+    }
+}
\ No newline at end of file
diff --git a/samples/training/testingfun/app/src/com/example/android/testingfun/lesson4/LaunchActivity.java b/samples/training/testingfun/app/src/com/example/android/testingfun/lesson4/LaunchActivity.java
new file mode 100644
index 0000000..8f1fb9b
--- /dev/null
+++ b/samples/training/testingfun/app/src/com/example/android/testingfun/lesson4/LaunchActivity.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2013 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.testingfun.lesson4;
+
+import com.example.android.testingfun.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+
+/**
+ * Launches NextActivity and passes a payload in the Bundle.
+ */
+public class LaunchActivity extends Activity {
+
+    /**
+     * The payload that is passed as Intent data to NextActivity.
+     */
+    public final static String STRING_PAYLOAD = "Started from LaunchActivity";
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_launch_next);
+        Button launchNextButton = (Button) findViewById(R.id.launch_next_activity_button);
+        launchNextButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                startActivity(NextActivity.makeIntent(LaunchActivity.this, STRING_PAYLOAD));
+                finish();
+            }
+        });
+    }
+}
diff --git a/samples/training/testingfun/app/src/com/example/android/testingfun/lesson4/NextActivity.java b/samples/training/testingfun/app/src/com/example/android/testingfun/lesson4/NextActivity.java
new file mode 100644
index 0000000..68965c2
--- /dev/null
+++ b/samples/training/testingfun/app/src/com/example/android/testingfun/lesson4/NextActivity.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2013 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.testingfun.lesson4;
+
+import com.example.android.testingfun.R;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.widget.TextView;
+
+/**
+ * This activity is started from LaunchActivity. It reads the payload from the given bundle and
+ * displays it using a TextView.
+ */
+public class NextActivity extends Activity {
+
+    /**
+     * Extras key for the payload.
+     */
+    public final static String EXTRAS_PAYLOAD_KEY
+            = "com.example.android.testingfun.lesson4.EXTRAS_PAYLOAD_KEY";
+
+    /**
+     * Factory method to create a launch Intent for this activity.
+     *
+     * @param context the context that intent should be bound to
+     * @param payload the payload data that should be added for this intent
+     * @return a configured intent to launch this activity with a String payload.
+     */
+    public static Intent makeIntent(Context context, String payload) {
+        return new Intent(context, NextActivity.class).putExtra(EXTRAS_PAYLOAD_KEY, payload);
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_next);
+
+        final String stringPayload = getIntent().getStringExtra(EXTRAS_PAYLOAD_KEY);
+
+        if (stringPayload != null) {
+            ((TextView) findViewById(R.id.next_activity_info_text_view)).setText(stringPayload);
+        }
+
+    }
+}
diff --git a/samples/training/testingfun/app/src/com/example/android/testingfun/lesson5/ReceiverActivity.java b/samples/training/testingfun/app/src/com/example/android/testingfun/lesson5/ReceiverActivity.java
new file mode 100644
index 0000000..2bc401d
--- /dev/null
+++ b/samples/training/testingfun/app/src/com/example/android/testingfun/lesson5/ReceiverActivity.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2013 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.testingfun.lesson5;
+
+import com.example.android.testingfun.R;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.widget.TextView;
+
+/**
+ * Receives a message from SenderActivity and displays the message.
+ */
+public class ReceiverActivity extends Activity {
+
+    /**
+     * The extra key that is used to identify the message in the Intents data bundle
+     */
+    private static final String EXTRA_SENDER_MESSAGE_TEXT
+            = "com.example.android.testingfun.lesson5.extra.sender.message.text";
+
+    /**
+     * Factory method to create an launch intent for this activity.
+     *
+     * @param context the context to this intent should be bound to
+     * @param message the message data that should be added to this intent
+     * @return a configured intent to launch this activity with a given message
+     */
+    public static Intent makeIntent(Context context, CharSequence message) {
+        return new Intent(context, ReceiverActivity.class)
+                .putExtra(EXTRA_SENDER_MESSAGE_TEXT, message);
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_receiver);
+        final CharSequence senderMessage = getIntent()
+                .getCharSequenceExtra(EXTRA_SENDER_MESSAGE_TEXT);
+        final TextView receiverTextView = (TextView) findViewById(R.id.received_message_text_view);
+        if (!TextUtils.isEmpty(senderMessage)) {
+            receiverTextView.setText(senderMessage);
+        }
+    }
+}
diff --git a/samples/training/testingfun/app/src/com/example/android/testingfun/lesson5/SenderActivity.java b/samples/training/testingfun/app/src/com/example/android/testingfun/lesson5/SenderActivity.java
new file mode 100644
index 0000000..495f1e6
--- /dev/null
+++ b/samples/training/testingfun/app/src/com/example/android/testingfun/lesson5/SenderActivity.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2013 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.testingfun.lesson5;
+
+import com.example.android.testingfun.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+
+/**
+ * Sends a user generated message to the ReceiverActivity
+ */
+public class SenderActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_sender);
+        final Button sendMessageButton = (Button) findViewById(R.id.send_message_button);
+        final EditText messageInputEditText = (EditText) findViewById(R.id.message_input_edit_text);
+        sendMessageButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (messageInputEditText != null) {
+                    final CharSequence message = messageInputEditText.getText();
+                    startActivity(ReceiverActivity.makeIntent(SenderActivity.this, message));
+                }
+            }
+        });
+    }
+}
diff --git a/samples/training/testingfun/app/tests/AndroidManifest.xml b/samples/training/testingfun/app/tests/AndroidManifest.xml
new file mode 100644
index 0000000..13ce6ab
--- /dev/null
+++ b/samples/training/testingfun/app/tests/AndroidManifest.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  Copyright (C) 2013 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 name must be unique so suffix with "tests" so package loader doesn't ignore us -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.android.testingfun.tests"
+    android:versionCode="1"
+    android:versionName="1.0">
+
+    <uses-sdk
+        android:minSdkVersion="8"
+        android:targetSdkVersion="17" />
+
+    <!-- We add an application tag here just so that we can indicate that
+         this package needs to link against the android.test library,
+         which is needed when building test cases. -->
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <!--
+    Specifies the instrumentation test runner used to run the tests.
+    -->
+    <instrumentation
+        android:name="android.test.InstrumentationTestRunner"
+        android:targetPackage="com.example.android.testingfun"
+        android:label="Tests for com.example.android.testingfun" />
+</manifest>
\ No newline at end of file
diff --git a/samples/training/testingfun/app/tests/project.properties b/samples/training/testingfun/app/tests/project.properties
new file mode 100644
index 0000000..a3ee5ab
--- /dev/null
+++ b/samples/training/testingfun/app/tests/project.properties
@@ -0,0 +1,14 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-17
diff --git a/samples/training/testingfun/app/tests/src/com/example/android/testingfun/tests/lesson2/MyFirstTestActivityTest.java b/samples/training/testingfun/app/tests/src/com/example/android/testingfun/tests/lesson2/MyFirstTestActivityTest.java
new file mode 100644
index 0000000..ad18b55
--- /dev/null
+++ b/samples/training/testingfun/app/tests/src/com/example/android/testingfun/tests/lesson2/MyFirstTestActivityTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2013 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.testingfun.tests.lesson2;
+
+import com.example.android.testingfun.R;
+import com.example.android.testingfun.lesson2.MyFirstTestActivity;
+
+import android.test.ActivityInstrumentationTestCase2;
+import android.widget.TextView;
+
+/**
+ * Tests for MyFirstTestActivity.
+ */
+public class MyFirstTestActivityTest extends ActivityInstrumentationTestCase2<MyFirstTestActivity> {
+
+    private MyFirstTestActivity mFirstTestActivity;
+    private TextView mFirstTestText;
+
+    public MyFirstTestActivityTest() {
+        super(MyFirstTestActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        // Starts the activity under test using the default Intent with:
+        // action = {@link Intent#ACTION_MAIN}
+        // flags = {@link Intent#FLAG_ACTIVITY_NEW_TASK}
+        // All other fields are null or empty.
+        mFirstTestActivity = getActivity();
+        mFirstTestText = (TextView) mFirstTestActivity.findViewById(R.id.my_first_test_text_view);
+    }
+
+    /**
+     * Test if your test fixture has been set up correctly. You should always implement a test that
+     * checks the correct setup of your test fixture. If this tests fails all other tests are
+     * likely to fail as well.
+     */
+    public void testPreconditions() {
+        //Try to add a message to add context to your assertions. These messages will be shown if
+        //a tests fails and make it easy to understand why a test failed
+        assertNotNull("mFirstTestActivity is null", mFirstTestActivity);
+        assertNotNull("mFirstTestText is null", mFirstTestText);
+    }
+
+    /**
+     * Tests the correctness of the initial text.
+     */
+    public void testMyFirstTestTextView_labelText() {
+        //It is good practice to read the string from your resources in order to not break
+        //multiple tests when a string changes.
+        final String expected = mFirstTestActivity.getString(R.string.my_first_test);
+        final String actual = mFirstTestText.getText().toString();
+        assertEquals("mFirstTestText contains wrong text", expected, actual);
+    }
+}
\ No newline at end of file
diff --git a/samples/training/testingfun/app/tests/src/com/example/android/testingfun/tests/lesson3/ClickFunActivityTest.java b/samples/training/testingfun/app/tests/src/com/example/android/testingfun/tests/lesson3/ClickFunActivityTest.java
new file mode 100644
index 0000000..5d3d387
--- /dev/null
+++ b/samples/training/testingfun/app/tests/src/com/example/android/testingfun/tests/lesson3/ClickFunActivityTest.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2013 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.testingfun.tests.lesson3;
+
+
+import com.example.android.testingfun.R;
+import com.example.android.testingfun.lesson3.ClickFunActivity;
+
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.TouchUtils;
+import android.test.ViewAsserts;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.TextView;
+
+/**
+ * Tests for ClickFunActivity. Introduces touch mode, test size annotations and TouchUtils.
+ */
+public class ClickFunActivityTest extends ActivityInstrumentationTestCase2<ClickFunActivity> {
+    
+    private ClickFunActivity mClickFunActivity;
+    private Button mClickMeButton;
+    private TextView mInfoTextView;
+
+    public ClickFunActivityTest() {
+        super(ClickFunActivity.class);
+    }
+
+    /**
+     * Sets up the test fixture for this test case. This method is always called before every test
+     * run.
+     */
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        //Sets the initial touch mode for the Activity under test. This must be called before
+        //getActivity()
+        setActivityInitialTouchMode(true);
+
+        //Get a reference to the Activity under test, starting it if necessary.
+        mClickFunActivity = getActivity();
+
+        //Get references to all views
+        mClickMeButton = (Button) mClickFunActivity.findViewById(R.id.launch_next_activity_button);
+        mInfoTextView = (TextView) mClickFunActivity.findViewById(R.id.info_text_view);
+    }
+
+    /**
+     * Tests the preconditions of this test fixture.
+     */
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull("mClickFunActivity is null", mClickFunActivity);
+        assertNotNull("mClickMeButton is null", mClickMeButton);
+        assertNotNull("mInfoTextView is null", mInfoTextView);
+    }
+
+    @MediumTest
+    public void testClickMeButton_layout() {
+        //Retrieve the top-level window decor view
+        final View decorView = mClickFunActivity.getWindow().getDecorView();
+
+        //Verify that the mClickMeButton is on screen
+        ViewAsserts.assertOnScreen(decorView, mClickMeButton);
+
+        //Verify width and heights
+        final ViewGroup.LayoutParams layoutParams = mClickMeButton.getLayoutParams();
+        assertNotNull(layoutParams);
+        assertEquals(layoutParams.width, WindowManager.LayoutParams.MATCH_PARENT);
+        assertEquals(layoutParams.height, WindowManager.LayoutParams.WRAP_CONTENT);
+    }
+
+    @MediumTest
+    public void testClickMeButton_labelText() {
+        //Verify that mClickMeButton uses the correct string resource
+        final String expectedNextButtonText = mClickFunActivity.getString(R.string.label_click_me);
+        final String actualNextButtonText = mClickMeButton.getText().toString();
+        assertEquals(expectedNextButtonText, actualNextButtonText);
+    }
+
+    @MediumTest
+    public void testInfoTextView_layout() {
+        //Retrieve the top-level window decor view
+        final View decorView = mClickFunActivity.getWindow().getDecorView();
+
+        //Verify that the mInfoTextView is on screen and is not visible
+        ViewAsserts.assertOnScreen(decorView, mInfoTextView);
+        assertTrue(View.GONE == mInfoTextView.getVisibility());
+    }
+
+    @MediumTest
+    public void testInfoTextViewText_isEmpty() {
+        //Verify that the mInfoTextView is initialized with the correct default value
+        assertEquals("", mInfoTextView.getText());
+    }
+
+    @MediumTest
+    public void testClickMeButton_clickButtonAndExpectInfoText() {
+        String expectedInfoText = mClickFunActivity.getString(R.string.info_text);
+        //Perform a click on mClickMeButton
+        TouchUtils.clickView(this, mClickMeButton);
+        //Verify the that mClickMeButton was clicked. mInfoTextView is visible and contains
+        //the correct text.
+        assertTrue(View.VISIBLE == mInfoTextView.getVisibility());
+        assertEquals(expectedInfoText, mInfoTextView.getText());
+    }
+}
diff --git a/samples/training/testingfun/app/tests/src/com/example/android/testingfun/tests/lesson4/LaunchActivityTest.java b/samples/training/testingfun/app/tests/src/com/example/android/testingfun/tests/lesson4/LaunchActivityTest.java
new file mode 100644
index 0000000..7d472c3
--- /dev/null
+++ b/samples/training/testingfun/app/tests/src/com/example/android/testingfun/tests/lesson4/LaunchActivityTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2013 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.testingfun.tests.lesson4;
+
+import com.example.android.testingfun.R;
+import com.example.android.testingfun.lesson4.LaunchActivity;
+import com.example.android.testingfun.lesson4.NextActivity;
+
+import android.content.Intent;
+import android.test.ActivityUnitTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.Button;
+
+/**
+ * Tests LaunchActivity in isolation from the system.
+ */
+public class LaunchActivityTest extends ActivityUnitTestCase<LaunchActivity> {
+
+    private Intent mLaunchIntent;
+
+    public LaunchActivityTest() {
+        super(LaunchActivity.class);
+    }
+
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        //Create an intent to launch target Activity
+        mLaunchIntent = new Intent(getInstrumentation().getTargetContext(),
+                LaunchActivity.class);
+    }
+
+    /**
+     * Tests the preconditions of this test fixture.
+     */
+    @MediumTest
+    public void testPreconditions() {
+        //Start the activity under test in isolation, without values for savedInstanceState and
+        //lastNonConfigurationInstance
+        startActivity(mLaunchIntent, null, null);
+        final Button launchNextButton = (Button) getActivity().findViewById(R.id.launch_next_activity_button);
+
+        assertNotNull("mLaunchActivity is null", getActivity());
+        assertNotNull("mLaunchNextButton is null", launchNextButton);
+    }
+
+
+    @MediumTest
+    public void testLaunchNextActivityButton_labelText() {
+        startActivity(mLaunchIntent, null, null);
+        final Button launchNextButton = (Button) getActivity().findViewById(R.id.launch_next_activity_button);
+
+        final String expectedButtonText = getActivity().getString(R.string.label_launch_next);
+        assertEquals("Unexpected button label text", expectedButtonText,
+                launchNextButton.getText());
+    }
+
+    @MediumTest
+    public void testNextActivityWasLaunchedWithIntent() {
+        startActivity(mLaunchIntent, null, null);
+        final Button launchNextButton = (Button) getActivity().findViewById(R.id.launch_next_activity_button);
+        //Because this is an isolated ActivityUnitTestCase we have to directly click the
+        //button from code
+        launchNextButton.performClick();
+
+        // Get the intent for the next started activity
+        final Intent launchIntent = getStartedActivityIntent();
+        //Verify the intent was not null.
+        assertNotNull("Intent was null", launchIntent);
+        //Verify that LaunchActivity was finished after button click
+        assertTrue(isFinishCalled());
+
+
+        final String payload = launchIntent.getStringExtra(NextActivity.EXTRAS_PAYLOAD_KEY);
+        //Verify that payload data was added to the intent
+        assertEquals("Payload is empty", LaunchActivity.STRING_PAYLOAD
+                , payload);
+    }
+}
\ No newline at end of file
diff --git a/samples/training/testingfun/app/tests/src/com/example/android/testingfun/tests/lesson5/SenderActivityTest.java b/samples/training/testingfun/app/tests/src/com/example/android/testingfun/tests/lesson5/SenderActivityTest.java
new file mode 100644
index 0000000..75bc302
--- /dev/null
+++ b/samples/training/testingfun/app/tests/src/com/example/android/testingfun/tests/lesson5/SenderActivityTest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2013 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.testingfun.tests.lesson5;
+
+import com.example.android.testingfun.R;
+import com.example.android.testingfun.lesson5.ReceiverActivity;
+import com.example.android.testingfun.lesson5.SenderActivity;
+
+import android.app.Instrumentation;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.TouchUtils;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.TextView;
+
+/**
+ * Functional test across multiple Activities. Tests SenderActivity and ReceiverActivity. Introduces
+ * advanced Instrumentation testing practices as sending key events and interaction monitoring
+ * between Activities and the system.
+ */
+public class SenderActivityTest extends ActivityInstrumentationTestCase2<SenderActivity> {
+
+    private static final int TIMEOUT_IN_MS = 5000;
+    private static final String TEST_MESSAGE = "Hello Receiver";
+    private SenderActivity mSenderActivity;
+
+    public SenderActivityTest() {
+        super(SenderActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        setActivityInitialTouchMode(true);
+        mSenderActivity = getActivity();
+    }
+
+    /**
+     * Tests the preconditions of this test fixture.
+     */
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull("mSenderActivity is null", mSenderActivity);
+    }
+
+    @MediumTest
+    public void testSendMessageToReceiverActivity() {
+
+        //Because this functional test tests interaction across multiple components these views
+        //are part of the actual test method and not of the test fixture
+        final Button sendToReceiverButton = (Button) mSenderActivity
+                .findViewById(R.id.send_message_button);
+        final EditText senderMessageEditText = (EditText) mSenderActivity
+                .findViewById(R.id.message_input_edit_text);
+
+        //Create and add an ActivityMonitor to monitor interaction between the system and the
+        //ReceiverActivity
+        Instrumentation.ActivityMonitor receiverActivityMonitor = getInstrumentation()
+                .addMonitor(ReceiverActivity.class.getName(), null, false);
+
+        //Request focus on the EditText field. This must be done on the UiThread because
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                senderMessageEditText.requestFocus();
+            }
+        });
+        //Wait until all events from the MainHandler's queue are processed
+        getInstrumentation().waitForIdleSync();
+
+        //Send the text message
+        getInstrumentation().sendStringSync(TEST_MESSAGE);
+        getInstrumentation().waitForIdleSync();
+
+        //Click on the sendToReceiverButton to send the message to ReceiverActivity
+        TouchUtils.clickView(this, sendToReceiverButton);
+
+        //Wait until ReceiverActivity was launched and get a reference to it.
+        ReceiverActivity receiverActivity = (ReceiverActivity) receiverActivityMonitor
+                .waitForActivityWithTimeout(TIMEOUT_IN_MS);
+        //Verify that ReceiverActivity was started
+        assertNotNull("ReceiverActivity is null", receiverActivity);
+        assertEquals("Monitor for ReceiverActivity has not been called", 1,
+                receiverActivityMonitor.getHits());
+        assertEquals("Activity is of wrong type", ReceiverActivity.class,
+                receiverActivity.getClass());
+
+        //Read the message received by ReceiverActivity
+        final TextView receivedMessage = (TextView) receiverActivity
+                .findViewById(R.id.received_message_text_view);
+        //Verify that received message is correct
+        assertNotNull(receivedMessage);
+        assertEquals("Wrong received message", TEST_MESSAGE, receivedMessage.getText().toString());
+
+        //Unregister monitor for ReceiverActivity
+        getInstrumentation().removeMonitor(receiverActivityMonitor);
+    }
+}
\ No newline at end of file
diff --git a/samples/training/testingfun/build.gradle b/samples/training/testingfun/build.gradle
new file mode 100644
index 0000000..06b6030
--- /dev/null
+++ b/samples/training/testingfun/build.gradle
@@ -0,0 +1,8 @@
+buildscript {
+    repositories {
+        mavenCentral()
+    }
+    dependencies {
+        classpath 'com.android.tools.build:gradle:0.4.2'
+    }
+}
diff --git a/samples/training/testingfun/gradle/wrapper/gradle-wrapper.jar b/samples/training/testingfun/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..8c0fb64
--- /dev/null
+++ b/samples/training/testingfun/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/samples/training/testingfun/gradle/wrapper/gradle-wrapper.properties b/samples/training/testingfun/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..5c22dec
--- /dev/null
+++ b/samples/training/testingfun/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Apr 10 15:27:10 PDT 2013
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=http\://services.gradle.org/distributions/gradle-1.6-bin.zip
diff --git a/samples/training/testingfun/gradlew b/samples/training/testingfun/gradlew
new file mode 100755
index 0000000..91a7e26
--- /dev/null
+++ b/samples/training/testingfun/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+    echo "$*"
+}
+
+die ( ) {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+    [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+    JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/samples/training/testingfun/gradlew.bat b/samples/training/testingfun/gradlew.bat
new file mode 100644
index 0000000..aec9973
--- /dev/null
+++ b/samples/training/testingfun/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off

+@rem ##########################################################################

+@rem

+@rem  Gradle startup script for Windows

+@rem

+@rem ##########################################################################

+

+@rem Set local scope for the variables with windows NT shell

+if "%OS%"=="Windows_NT" setlocal

+

+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.

+set DEFAULT_JVM_OPTS=

+

+set DIRNAME=%~dp0

+if "%DIRNAME%" == "" set DIRNAME=.

+set APP_BASE_NAME=%~n0

+set APP_HOME=%DIRNAME%

+

+@rem Find java.exe

+if defined JAVA_HOME goto findJavaFromJavaHome

+

+set JAVA_EXE=java.exe

+%JAVA_EXE% -version >NUL 2>&1

+if "%ERRORLEVEL%" == "0" goto init

+

+echo.

+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

+echo.

+echo Please set the JAVA_HOME variable in your environment to match the

+echo location of your Java installation.

+

+goto fail

+

+:findJavaFromJavaHome

+set JAVA_HOME=%JAVA_HOME:"=%

+set JAVA_EXE=%JAVA_HOME%/bin/java.exe

+

+if exist "%JAVA_EXE%" goto init

+

+echo.

+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%

+echo.

+echo Please set the JAVA_HOME variable in your environment to match the

+echo location of your Java installation.

+

+goto fail

+

+:init

+@rem Get command-line arguments, handling Windowz variants

+

+if not "%OS%" == "Windows_NT" goto win9xME_args

+if "%@eval[2+2]" == "4" goto 4NT_args

+

+:win9xME_args

+@rem Slurp the command line arguments.

+set CMD_LINE_ARGS=

+set _SKIP=2

+

+:win9xME_args_slurp

+if "x%~1" == "x" goto execute

+

+set CMD_LINE_ARGS=%*

+goto execute

+

+:4NT_args

+@rem Get arguments from the 4NT Shell from JP Software

+set CMD_LINE_ARGS=%$

+

+:execute

+@rem Setup the command line

+

+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar

+

+@rem Execute Gradle

+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%

+

+:end

+@rem End local scope for the variables with windows NT shell

+if "%ERRORLEVEL%"=="0" goto mainEnd

+

+:fail

+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of

+rem the _cmd.exe /c_ return code!

+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1

+exit /b 1

+

+:mainEnd

+if "%OS%"=="Windows_NT" endlocal

+

+:omega

diff --git a/samples/training/testingfun/settings.gradle b/samples/training/testingfun/settings.gradle
new file mode 100644
index 0000000..e7b4def
--- /dev/null
+++ b/samples/training/testingfun/settings.gradle
@@ -0,0 +1 @@
+include ':app'
diff --git a/scripts/app_engine_server/memcache_zipserve.py b/scripts/app_engine_server/memcache_zipserve.py
index dfd7de9..9c6f42e 100644
--- a/scripts/app_engine_server/memcache_zipserve.py
+++ b/scripts/app_engine_server/memcache_zipserve.py
@@ -1,4 +1,5 @@
 #!/usr/bin/env python
+# -*- coding: utf-8 -*-
 #
 # Copyright 2009 Google Inc.
 #
@@ -526,6 +527,10 @@
     resp_data = None
     file_itr = iter(self.zipfilenames)
 
+    # decode any escape characters in the URI
+    # Note: We are currenty just looking for '@' (%40)
+    file_path = file_path.replace('%40', '@')
+
     # check the index, if we have one, to see what archive the file is in
     archive_name = self.MapFileToArchive(file_path)
     if not archive_name:
diff --git a/scripts/app_engine_server/redirects.yaml b/scripts/app_engine_server/redirects.yaml
index 88b1f46..42165b5 100644
--- a/scripts/app_engine_server/redirects.yaml
+++ b/scripts/app_engine_server/redirects.yaml
@@ -77,11 +77,17 @@
   type: permanent
   comment: Redirect sdk reference to new location
 
-# new one works
 - src: /sdk/compatibility-library.html
-  dst: /tools/extras/support-library.html
+  dst: /tools/support-library/index.html
   type: permanent
-  comment: Redirect sdk reference to new location
+
+- src: /tools/extras/support-library.html
+  dst: /tools/support-library/index.html
+  type: permanent
+
+- src: /training/basics/fragments/support-lib.html
+  dst: /tools/support-library/setup.html
+  type: permanent
 
 # new one works
 - src: /sdk/eclipse-adt.html
@@ -424,6 +430,23 @@
   dst: /training/articles/perf-jni.html
   type: permanent
 
+# move ui docs to design
+
+- src: /guide/practices/ui_guidelines/index.html
+  dst: /design/index.html
+  type: permanent
+
+- src: /guide/practices/ui_guidelines/icon_design.*
+  dst: /design/style/iconography.html
+  type: permanent
+
+- src: /guide/practices/ui_guidelines/activity_task_design.html
+  dst: /design/patterns/app-structure.html
+  type: permanent
+
+- src: /guide/practices/ui_guidelines/menu_design.html
+  dst: /design/patterns/actionbar.html
+  type: permanent
 
 
 # new one
@@ -539,6 +562,10 @@
 
 # ------------------- TRAINING -------------------
 
+- src: /guide/topics/ui/layout/tabs.html
+  dst: /training/implementing-navigation/lateral.html
+  type: permanent
+
 - src: /training/cloudsync/aesync.html
   dst: /google/gcm/index.html
   type: permanent
@@ -638,18 +665,22 @@
   dst: http://www.youtube.com/user/androiddevelopers
   type: permanent
 
-- src: /playbadge
+- src: /playbadge/?$
   dst: http://developer.android.com/distribute/googleplay/promote/badges.html
   type: permanent
 
-- src: /deviceart
+- src: /deviceart/?$
   dst: http://developer.android.com/distribute/promote/device-art.html
   type: permanent
 
+- src: /edu/signup/?$
+  dst: https://services.google.com/fb/forms/playedu
+  type: permanent
+
+- src: /edu/?$
+  dst: /distribute/googleplay/edu/index.html
+  type: permanent
+
 - src: /edu/signup
   dst: https://services.google.com/fb/forms/playedu
   type: permanent
-
-- src: /edu
-  dst: /distribute/googleplay/edu/index.html
-  type: permanent
diff --git a/scripts/gdb/dalvik.gdb b/scripts/gdb/dalvik.gdb
new file mode 100644
index 0000000..cab0951
--- /dev/null
+++ b/scripts/gdb/dalvik.gdb
@@ -0,0 +1,51 @@
+#  dump dalvik backtrace
+define dbt
+    if $argc == 1
+        set $FP = $arg0
+    else
+        set $FP = $r5
+    end
+
+    set $frame = 0
+    set $savedPC = 0
+    while $FP
+        set $stackSave = $FP - sizeof(StackSaveArea)
+        set $savedPC = ((StackSaveArea *)$stackSave)->savedPc
+        set $method = ((StackSaveArea *)$stackSave)->method
+        printf "#%d\n", $frame
+        printf "    FP = %#x\n", $FP
+        printf "    stack save = %#x\n", $stackSave
+        printf "    Curr pc = %#x\n", ((StackSaveArea *) $stackSave)->xtra.currentPc
+        printf "    FP prev = %#x\n", ((StackSaveArea *) $stackSave)->prevFrame
+        if $method != 0
+            printf "    returnAddr: 0x%x\n", \
+                   ((StackSaveArea *)$stackSave)->returnAddr
+            printf "    class = %s\n", ((Method *) $method)->clazz->descriptor
+            printf "    method = %s (%#08x)\n", ((Method *) $method)->name, $method
+            printf "    signature = %s\n", ((Method *) $method)->shorty
+            printf "    bytecode offset = 0x%x\n", (short *) (((StackSaveArea *) $stackSave)->xtra.currentPc) - (short *) (((Method *) $method)->insns)
+            set $regSize = ((Method *) $method)->registersSize
+            set $insSize = ((Method *) $method)->insSize
+            set $index = 0
+            while $index < $regSize
+                printf "    v%d = %d", $index, ((int *)$FP)[$index]
+                if $regSize - $index <= $insSize
+                    printf " (in%d)\n", $insSize - $regSize + $index
+                else
+                    printf " (local%d)\n", $index
+                end
+                set $index = $index + 1
+            end
+        else
+            printf "    break frame\n"
+        end
+        set $FP = (int) ((StackSaveArea *)$stackSave)->prevFrame
+        set $frame = $frame + 1
+    end
+end
+
+document dbt
+    Unwind Dalvik stack frames. Argument 0 is the frame address of the top
+    frame. If omitted r5 will be used as the default (as the case in the
+    interpreter and JIT'ed code).
+end
diff --git a/sdk/api-versions.xml b/sdk/api-versions.xml
index 70e6584..4ce952f 100644
--- a/sdk/api-versions.xml
+++ b/sdk/api-versions.xml
@@ -24,6 +24,7 @@
 		<field name="BIND_APPWIDGET" since="3" />
 		<field name="BIND_DEVICE_ADMIN" since="8" />
 		<field name="BIND_INPUT_METHOD" since="3" />
+		<field name="BIND_NOTIFICATION_LISTENER_SERVICE" since="18" />
 		<field name="BIND_REMOTEVIEWS" since="11" />
 		<field name="BIND_TEXT_SERVICE" since="14" />
 		<field name="BIND_VPN_SERVICE" since="14" />
@@ -60,6 +61,7 @@
 		<field name="GET_ACCOUNTS" />
 		<field name="GET_PACKAGE_SIZE" />
 		<field name="GET_TASKS" />
+		<field name="GET_TOP_ACTIVITY_INFO" since="18" />
 		<field name="GLOBAL_SEARCH" since="4" />
 		<field name="HARDWARE_TEST" />
 		<field name="INJECT_EVENTS" />
@@ -68,6 +70,7 @@
 		<field name="INTERNAL_SYSTEM_WINDOW" />
 		<field name="INTERNET" />
 		<field name="KILL_BACKGROUND_PROCESSES" since="8" />
+		<field name="LOCATION_HARDWARE" since="18" />
 		<field name="MANAGE_ACCOUNTS" since="5" />
 		<field name="MANAGE_APP_TOKENS" />
 		<field name="MASTER_CLEAR" />
@@ -102,6 +105,7 @@
 		<field name="RECORD_AUDIO" />
 		<field name="REORDER_TASKS" />
 		<field name="RESTART_PACKAGES" />
+		<field name="SEND_RESPOND_VIA_MESSAGE" since="18" />
 		<field name="SEND_SMS" />
 		<field name="SET_ACTIVITY_WATCHER" />
 		<field name="SET_ALARM" since="9" />
@@ -146,6 +150,7 @@
 	<class name="android/Manifest$permission_group" since="1">
 		<extends name="java/lang/Object" />
 		<method name="&lt;init>()V" />
+		<field name="ACCESSIBILITY_FEATURES" since="18" />
 		<field name="ACCOUNTS" />
 		<field name="AFFECTS_BATTERY" since="17" />
 		<field name="APP_INFO" since="17" />
@@ -321,6 +326,9 @@
 		<field name="cacheColorHint" />
 		<field name="calendarViewShown" since="11" />
 		<field name="calendarViewStyle" since="11" />
+		<field name="canRequestEnhancedWebAccessibility" since="18" />
+		<field name="canRequestFilterKeyEvents" since="18" />
+		<field name="canRequestTouchExplorationMode" since="18" />
 		<field name="canRetrieveWindowContent" since="14" />
 		<field name="candidatesTextStyleSpans" since="3" />
 		<field name="capitalize" />
@@ -340,8 +348,10 @@
 		<field name="checkedTextViewStyle" since="17" />
 		<field name="childDivider" />
 		<field name="childIndicator" />
+		<field name="childIndicatorEnd" since="18" />
 		<field name="childIndicatorLeft" />
 		<field name="childIndicatorRight" />
+		<field name="childIndicatorStart" since="18" />
 		<field name="choiceMode" />
 		<field name="clearTaskOnLaunch" />
 		<field name="clickable" />
@@ -575,8 +585,10 @@
 		<field name="indeterminateDuration" />
 		<field name="indeterminateOnly" />
 		<field name="indeterminateProgressStyle" since="11" />
+		<field name="indicatorEnd" since="18" />
 		<field name="indicatorLeft" />
 		<field name="indicatorRight" />
+		<field name="indicatorStart" since="18" />
 		<field name="inflatedId" />
 		<field name="initOrder" />
 		<field name="initialKeyguardLayout" since="17" />
@@ -633,6 +645,7 @@
 		<field name="layout" />
 		<field name="layoutAnimation" />
 		<field name="layoutDirection" since="17" />
+		<field name="layoutMode" since="18" />
 		<field name="layout_above" />
 		<field name="layout_alignBaseline" />
 		<field name="layout_alignBottom" />
@@ -729,6 +742,8 @@
 		<field name="minResizeWidth" since="14" />
 		<field name="minSdkVersion" />
 		<field name="minWidth" />
+		<field name="mipMap" since="18" />
+		<field name="mirrorForRtl" since="18" />
 		<field name="mode" />
 		<field name="moreIcon" />
 		<field name="multiprocess" />
@@ -845,6 +860,8 @@
 		<field name="reqNavigation" since="3" />
 		<field name="reqTouchScreen" since="3" />
 		<field name="required" since="5" />
+		<field name="requiredAccountType" since="18" />
+		<field name="requiredForAllUsers" since="18" />
 		<field name="requiresFadingEdge" since="14" />
 		<field name="requiresSmallestWidthDp" since="13" />
 		<field name="resizeMode" since="12" />
@@ -852,6 +869,7 @@
 		<field name="resource" />
 		<field name="restoreAnyVersion" since="8" />
 		<field name="restoreNeedsApplication" since="5" />
+		<field name="restrictedAccountType" since="18" />
 		<field name="right" />
 		<field name="ringtonePreferenceStyle" />
 		<field name="ringtoneType" />
@@ -1173,6 +1191,7 @@
 		<field name="windowMinWidthMinor" since="11" />
 		<field name="windowNoDisplay" since="3" />
 		<field name="windowNoTitle" />
+		<field name="windowOverscan" since="18" />
 		<field name="windowShowAnimation" />
 		<field name="windowShowWallpaper" since="5" />
 		<field name="windowSoftInputMode" since="3" />
@@ -1710,9 +1729,11 @@
 		<field name="Theme_DeviceDefault_Light_Dialog_NoActionBar_MinWidth" since="14" />
 		<field name="Theme_DeviceDefault_Light_NoActionBar" since="14" />
 		<field name="Theme_DeviceDefault_Light_NoActionBar_Fullscreen" since="14" />
+		<field name="Theme_DeviceDefault_Light_NoActionBar_Overscan" since="18" />
 		<field name="Theme_DeviceDefault_Light_Panel" since="14" />
 		<field name="Theme_DeviceDefault_NoActionBar" since="14" />
 		<field name="Theme_DeviceDefault_NoActionBar_Fullscreen" since="14" />
+		<field name="Theme_DeviceDefault_NoActionBar_Overscan" since="18" />
 		<field name="Theme_DeviceDefault_Panel" since="14" />
 		<field name="Theme_DeviceDefault_Wallpaper" since="14" />
 		<field name="Theme_DeviceDefault_Wallpaper_NoTitleBar" since="14" />
@@ -1735,9 +1756,11 @@
 		<field name="Theme_Holo_Light_Dialog_NoActionBar_MinWidth" since="11" />
 		<field name="Theme_Holo_Light_NoActionBar" since="13" />
 		<field name="Theme_Holo_Light_NoActionBar_Fullscreen" since="13" />
+		<field name="Theme_Holo_Light_NoActionBar_Overscan" since="18" />
 		<field name="Theme_Holo_Light_Panel" since="11" />
 		<field name="Theme_Holo_NoActionBar" since="11" />
 		<field name="Theme_Holo_NoActionBar_Fullscreen" since="11" />
+		<field name="Theme_Holo_NoActionBar_Overscan" since="18" />
 		<field name="Theme_Holo_Panel" since="11" />
 		<field name="Theme_Holo_Wallpaper" since="11" />
 		<field name="Theme_Holo_Wallpaper_NoTitleBar" since="11" />
@@ -2053,6 +2076,7 @@
 		<method name="onAccessibilityEvent(Landroid/view/accessibility/AccessibilityEvent;)V" />
 		<method name="onGesture(I)Z" since="16" />
 		<method name="onInterrupt()V" />
+		<method name="onKeyEvent(Landroid/view/KeyEvent;)Z" since="18" />
 		<method name="onServiceConnected()V" />
 		<method name="performGlobalAction(I)Z" since="16" />
 		<method name="setServiceInfo(Landroid/accessibilityservice/AccessibilityServiceInfo;)V" />
@@ -2084,14 +2108,20 @@
 		<extends name="java/lang/Object" />
 		<implements name="android/os/Parcelable" />
 		<method name="&lt;init>()V" />
+		<method name="capabilityToString(I)Ljava/lang/String;" since="18" />
 		<method name="feedbackTypeToString(I)Ljava/lang/String;" since="14" />
 		<method name="flagToString(I)Ljava/lang/String;" since="14" />
 		<method name="getCanRetrieveWindowContent()Z" since="14" />
+		<method name="getCapabilities()I" since="18" />
 		<method name="getDescription()Ljava/lang/String;" since="14" />
 		<method name="getId()Ljava/lang/String;" since="14" />
 		<method name="getResolveInfo()Landroid/content/pm/ResolveInfo;" since="14" />
 		<method name="getSettingsActivityName()Ljava/lang/String;" since="14" />
 		<method name="loadDescription(Landroid/content/pm/PackageManager;)Ljava/lang/String;" since="16" />
+		<field name="CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY" since="18" />
+		<field name="CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS" since="18" />
+		<field name="CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION" since="18" />
+		<field name="CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT" since="18" />
 		<field name="CREATOR" />
 		<field name="DEFAULT" />
 		<field name="FEEDBACK_ALL_MASK" since="14" />
@@ -2102,6 +2132,9 @@
 		<field name="FEEDBACK_SPOKEN" />
 		<field name="FEEDBACK_VISUAL" />
 		<field name="FLAG_INCLUDE_NOT_IMPORTANT_VIEWS" since="16" />
+		<field name="FLAG_REPORT_VIEW_IDS" since="18" />
+		<field name="FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY" since="18" />
+		<field name="FLAG_REQUEST_FILTER_KEY_EVENTS" since="18" />
 		<field name="FLAG_REQUEST_TOUCH_EXPLORATION_MODE" since="16" />
 		<field name="eventTypes" />
 		<field name="feedbackType" />
@@ -2113,8 +2146,10 @@
 		<extends name="java/lang/Object" />
 		<method name="&lt;init>(Landroid/content/Context;)V" />
 		<method name="addAccount(Landroid/accounts/AccountAuthenticatorResponse;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Landroid/os/Bundle;)Landroid/os/Bundle;" />
+		<method name="addAccountFromCredentials(Landroid/accounts/AccountAuthenticatorResponse;Landroid/accounts/Account;Landroid/os/Bundle;)Landroid/os/Bundle;" since="18" />
 		<method name="confirmCredentials(Landroid/accounts/AccountAuthenticatorResponse;Landroid/accounts/Account;Landroid/os/Bundle;)Landroid/os/Bundle;" />
 		<method name="editProperties(Landroid/accounts/AccountAuthenticatorResponse;Ljava/lang/String;)Landroid/os/Bundle;" />
+		<method name="getAccountCredentialsForCloning(Landroid/accounts/AccountAuthenticatorResponse;Landroid/accounts/Account;)Landroid/os/Bundle;" since="18" />
 		<method name="getAccountRemovalAllowed(Landroid/accounts/AccountAuthenticatorResponse;Landroid/accounts/Account;)Landroid/os/Bundle;" />
 		<method name="getAuthToken(Landroid/accounts/AccountAuthenticatorResponse;Landroid/accounts/Account;Ljava/lang/String;Landroid/os/Bundle;)Landroid/os/Bundle;" />
 		<method name="getAuthTokenLabel(Ljava/lang/String;)Ljava/lang/String;" />
@@ -2159,6 +2194,7 @@
 		<method name="getAccounts()[Landroid/accounts/Account;" />
 		<method name="getAccountsByType(Ljava/lang/String;)[Landroid/accounts/Account;" />
 		<method name="getAccountsByTypeAndFeatures(Ljava/lang/String;[Ljava/lang/String;Landroid/accounts/AccountManagerCallback;Landroid/os/Handler;)Landroid/accounts/AccountManagerFuture;" />
+		<method name="getAccountsByTypeForPackage(Ljava/lang/String;Ljava/lang/String;)[Landroid/accounts/Account;" since="18" />
 		<method name="getAuthToken(Landroid/accounts/Account;Ljava/lang/String;Landroid/os/Bundle;Landroid/app/Activity;Landroid/accounts/AccountManagerCallback;Landroid/os/Handler;)Landroid/accounts/AccountManagerFuture;" />
 		<method name="getAuthToken(Landroid/accounts/Account;Ljava/lang/String;Landroid/os/Bundle;ZLandroid/accounts/AccountManagerCallback;Landroid/os/Handler;)Landroid/accounts/AccountManagerFuture;" since="14" />
 		<method name="getAuthToken(Landroid/accounts/Account;Ljava/lang/String;ZLandroid/accounts/AccountManagerCallback;Landroid/os/Handler;)Landroid/accounts/AccountManagerFuture;" />
@@ -2180,6 +2216,7 @@
 		<field name="AUTHENTICATOR_ATTRIBUTES_NAME" />
 		<field name="AUTHENTICATOR_META_DATA_NAME" />
 		<field name="ERROR_CODE_BAD_ARGUMENTS" />
+		<field name="ERROR_CODE_BAD_AUTHENTICATION" since="18" />
 		<field name="ERROR_CODE_BAD_REQUEST" />
 		<field name="ERROR_CODE_CANCELED" />
 		<field name="ERROR_CODE_INVALID_RESPONSE" />
@@ -2265,6 +2302,15 @@
 		<method name="&lt;init>(Ljava/lang/String;Ljava/lang/Throwable;)V" />
 		<method name="&lt;init>(Ljava/lang/Throwable;)V" />
 	</class>
+	<class name="android/animation/Animatable" since="18">
+		<extends name="java/lang/Object" />
+		<method name="getDuration()J" />
+		<method name="getInterpolator()Landroid/animation/TimeInterpolator;" />
+		<method name="getStartDelay()J" />
+		<method name="setDuration(J)Landroid/animation/Animatable;" />
+		<method name="setInterpolator(Landroid/animation/TimeInterpolator;)V" />
+		<method name="setStartDelay(J)V" />
+	</class>
 	<class name="android/animation/Animator" since="11">
 		<extends name="java/lang/Object" />
 		<implements name="java/lang/Cloneable" />
@@ -2274,6 +2320,7 @@
 		<method name="clone()Landroid/animation/Animator;" />
 		<method name="end()V" />
 		<method name="getDuration()J" />
+		<method name="getInterpolator()Landroid/animation/TimeInterpolator;" since="18" />
 		<method name="getListeners()Ljava/util/ArrayList;" />
 		<method name="getStartDelay()J" />
 		<method name="isRunning()Z" />
@@ -2415,6 +2462,7 @@
 		<method name="ofObject(Ljava/lang/Object;Landroid/util/Property;Landroid/animation/TypeEvaluator;[Ljava/lang/Object;)Landroid/animation/ObjectAnimator;" since="14" />
 		<method name="ofObject(Ljava/lang/Object;Ljava/lang/String;Landroid/animation/TypeEvaluator;[Ljava/lang/Object;)Landroid/animation/ObjectAnimator;" />
 		<method name="ofPropertyValuesHolder(Ljava/lang/Object;[Landroid/animation/PropertyValuesHolder;)Landroid/animation/ObjectAnimator;" />
+		<method name="setAutoCancel(Z)V" since="18" />
 		<method name="setDuration(J)Landroid/animation/ObjectAnimator;" />
 		<method name="setProperty(Landroid/util/Property;)V" since="14" />
 		<method name="setPropertyName(Ljava/lang/String;)V" />
@@ -2441,6 +2489,12 @@
 		<method name="setProperty(Landroid/util/Property;)V" since="14" />
 		<method name="setPropertyName(Ljava/lang/String;)V" />
 	</class>
+	<class name="android/animation/RectEvaluator" since="18">
+		<extends name="java/lang/Object" />
+		<implements name="android/animation/TypeEvaluator" />
+		<method name="&lt;init>()V" />
+		<method name="evaluate(FLandroid/graphics/Rect;Landroid/graphics/Rect;)Landroid/graphics/Rect;" />
+	</class>
 	<class name="android/animation/TimeAnimator" since="16">
 		<extends name="android/animation/ValueAnimator" />
 		<method name="&lt;init>()V" />
@@ -2546,6 +2600,10 @@
 		<method name="setDisplayShowHomeEnabled(Z)V" />
 		<method name="setDisplayShowTitleEnabled(Z)V" />
 		<method name="setDisplayUseLogoEnabled(Z)V" />
+		<method name="setHomeActionContentDescription(I)V" since="18" />
+		<method name="setHomeActionContentDescription(Ljava/lang/CharSequence;)V" since="18" />
+		<method name="setHomeAsUpIndicator(I)V" since="18" />
+		<method name="setHomeAsUpIndicator(Landroid/graphics/drawable/Drawable;)V" since="18" />
 		<method name="setHomeButtonEnabled(Z)V" since="14" />
 		<method name="setIcon(I)V" since="14" />
 		<method name="setIcon(Landroid/graphics/drawable/Drawable;)V" since="14" />
@@ -2669,6 +2727,7 @@
 		<method name="isChild()Z" />
 		<method name="isDestroyed()Z" since="17" />
 		<method name="isFinishing()Z" />
+		<method name="isImmersive()Z" since="18" />
 		<method name="isTaskRoot()Z" />
 		<method name="managedQuery(Landroid/net/Uri;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)Landroid/database/Cursor;" />
 		<method name="moveTaskToBack(Z)Z" />
@@ -2702,6 +2761,7 @@
 		<method name="onPrepareDialog(ILandroid/app/Dialog;Landroid/os/Bundle;)V" since="8" />
 		<method name="onPrepareNavigateUpTaskStack(Landroid/app/TaskStackBuilder;)V" since="16" />
 		<method name="onPrepareOptionsMenu(Landroid/view/Menu;)Z" />
+		<method name="onProvideAssistData(Landroid/os/Bundle;)V" since="18" />
 		<method name="onRestart()V" />
 		<method name="onRestoreInstanceState(Landroid/os/Bundle;)V" />
 		<method name="onResume()V" />
@@ -2731,6 +2791,7 @@
 		<method name="setFeatureDrawableResource(II)V" />
 		<method name="setFeatureDrawableUri(ILandroid/net/Uri;)V" />
 		<method name="setFinishOnTouchOutside(Z)V" since="11" />
+		<method name="setImmersive(Z)V" since="18" />
 		<method name="setIntent(Landroid/content/Intent;)V" />
 		<method name="setPersistent(Z)V" />
 		<method name="setProgress(I)V" />
@@ -3033,7 +3094,9 @@
 		<method name="onCreate()V" />
 		<method name="onTerminate()V" />
 		<method name="registerActivityLifecycleCallbacks(Landroid/app/Application$ActivityLifecycleCallbacks;)V" since="14" />
+		<method name="registerOnProvideAssistDataListener(Landroid/app/Application$OnProvideAssistDataListener;)V" since="18" />
 		<method name="unregisterActivityLifecycleCallbacks(Landroid/app/Application$ActivityLifecycleCallbacks;)V" since="14" />
+		<method name="unregisterOnProvideAssistDataListener(Landroid/app/Application$OnProvideAssistDataListener;)V" since="18" />
 	</class>
 	<class name="android/app/Application$ActivityLifecycleCallbacks" since="14">
 		<extends name="java/lang/Object" />
@@ -3045,6 +3108,10 @@
 		<method name="onActivityStarted(Landroid/app/Activity;)V" />
 		<method name="onActivityStopped(Landroid/app/Activity;)V" />
 	</class>
+	<class name="android/app/Application$OnProvideAssistDataListener" since="18">
+		<extends name="java/lang/Object" />
+		<method name="onProvideAssistData(Landroid/app/Activity;Landroid/os/Bundle;)V" />
+	</class>
 	<class name="android/app/ApplicationErrorReport" since="14">
 		<extends name="java/lang/Object" />
 		<implements name="android/os/Parcelable" />
@@ -3508,6 +3575,7 @@
 		<method name="getComponentName()Landroid/content/ComponentName;" />
 		<method name="getContext()Landroid/content/Context;" />
 		<method name="getTargetContext()Landroid/content/Context;" />
+		<method name="getUiAutomation()Landroid/app/UiAutomation;" since="18" />
 		<method name="invokeContextMenuAction(Landroid/app/Activity;II)Z" />
 		<method name="invokeMenuActionSync(Landroid/app/Activity;II)Z" />
 		<method name="isProfiling()Z" />
@@ -4056,6 +4124,35 @@
 		<extends name="java/lang/Object" />
 		<method name="onTimeSet(Landroid/widget/TimePicker;II)V" />
 	</class>
+	<class name="android/app/UiAutomation" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>()V" />
+		<method name="executeAndWaitForEvent(Ljava/lang/Runnable;Landroid/app/UiAutomation$AccessibilityEventFilter;J)Landroid/view/accessibility/AccessibilityEvent;" />
+		<method name="getRootInActiveWindow()Landroid/view/accessibility/AccessibilityNodeInfo;" />
+		<method name="getServiceInfo()Landroid/accessibilityservice/AccessibilityServiceInfo;" />
+		<method name="injectInputEvent(Landroid/view/InputEvent;Z)Z" />
+		<method name="performGlobalAction(I)Z" />
+		<method name="setOnAccessibilityEventListener(Landroid/app/UiAutomation$OnAccessibilityEventListener;)V" />
+		<method name="setRotation(I)Z" />
+		<method name="setRunAsMonkey(Z)V" />
+		<method name="setServiceInfo(Landroid/accessibilityservice/AccessibilityServiceInfo;)V" />
+		<method name="takeScreenshot()Landroid/graphics/Bitmap;" />
+		<method name="waitForIdle(JJ)V" />
+		<field name="ROTATION_FREEZE_0" />
+		<field name="ROTATION_FREEZE_180" />
+		<field name="ROTATION_FREEZE_270" />
+		<field name="ROTATION_FREEZE_90" />
+		<field name="ROTATION_FREEZE_CURRENT" />
+		<field name="ROTATION_UNFREEZE" />
+	</class>
+	<class name="android/app/UiAutomation$AccessibilityEventFilter" since="18">
+		<extends name="java/lang/Object" />
+		<method name="accept(Landroid/view/accessibility/AccessibilityEvent;)Z" />
+	</class>
+	<class name="android/app/UiAutomation$OnAccessibilityEventListener" since="18">
+		<extends name="java/lang/Object" />
+		<method name="onAccessibilityEvent(Landroid/view/accessibility/AccessibilityEvent;)V" />
+	</class>
 	<class name="android/app/UiModeManager" since="8">
 		<extends name="java/lang/Object" />
 		<method name="&lt;init>()V" />
@@ -4195,6 +4292,7 @@
 		<method name="hasGrantedPolicy(Landroid/content/ComponentName;I)Z" since="11" />
 		<method name="isActivePasswordSufficient()Z" />
 		<method name="isAdminActive(Landroid/content/ComponentName;)Z" />
+		<method name="isDeviceOwnerApp(Ljava/lang/String;)Z" since="18" />
 		<method name="lockNow()V" />
 		<method name="removeActiveAdmin(Landroid/content/ComponentName;)V" />
 		<method name="resetPassword(Ljava/lang/String;I)Z" />
@@ -4458,6 +4556,9 @@
 		<method name="listenUsingRfcommWithServiceRecord(Ljava/lang/String;Ljava/util/UUID;)Landroid/bluetooth/BluetoothServerSocket;" />
 		<method name="setName(Ljava/lang/String;)Z" />
 		<method name="startDiscovery()Z" />
+		<method name="startLeScan(Landroid/bluetooth/BluetoothAdapter$LeScanCallback;)Z" since="18" />
+		<method name="startLeScan([Ljava/util/UUID;Landroid/bluetooth/BluetoothAdapter$LeScanCallback;)Z" since="18" />
+		<method name="stopLeScan(Landroid/bluetooth/BluetoothAdapter$LeScanCallback;)V" since="18" />
 		<field name="ACTION_CONNECTION_STATE_CHANGED" since="11" />
 		<field name="ACTION_DISCOVERY_FINISHED" />
 		<field name="ACTION_DISCOVERY_STARTED" />
@@ -4487,6 +4588,18 @@
 		<field name="STATE_TURNING_OFF" />
 		<field name="STATE_TURNING_ON" />
 	</class>
+	<class name="android/bluetooth/BluetoothAdapter$LeScanCallback" since="18">
+		<extends name="java/lang/Object" />
+		<method name="onLeScan(Landroid/bluetooth/BluetoothDevice;I[B)V" />
+	</class>
+	<class name="android/bluetooth/BluetoothAdapterCallback" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>()V" />
+		<method name="onCallbackRegistration(I)V" />
+		<method name="onLeScan(Landroid/bluetooth/BluetoothDevice;I[B)V" />
+		<field name="CALLBACK_REGISTERED" />
+		<field name="CALLBACK_REGISTRATION_FAILURE" />
+	</class>
 	<class name="android/bluetooth/BluetoothAssignedNumbers" since="11">
 		<extends name="java/lang/Object" />
 		<method name="&lt;init>()V" />
@@ -4683,6 +4796,7 @@
 		<extends name="java/lang/Object" />
 		<implements name="android/os/Parcelable" />
 		<method name="&lt;init>()V" />
+		<method name="connectGatt(Landroid/content/Context;ZLandroid/bluetooth/BluetoothGattCallback;)Landroid/bluetooth/BluetoothGatt;" since="18" />
 		<method name="createInsecureRfcommSocketToServiceRecord(Ljava/util/UUID;)Landroid/bluetooth/BluetoothSocket;" since="10" />
 		<method name="createRfcommSocketToServiceRecord(Ljava/util/UUID;)Landroid/bluetooth/BluetoothSocket;" />
 		<method name="fetchUuidsWithSdp()Z" since="15" />
@@ -4690,6 +4804,7 @@
 		<method name="getBluetoothClass()Landroid/bluetooth/BluetoothClass;" />
 		<method name="getBondState()I" />
 		<method name="getName()Ljava/lang/String;" />
+		<method name="getType()I" since="18" />
 		<method name="getUuids()[Landroid/os/ParcelUuid;" since="15" />
 		<field name="ACTION_ACL_CONNECTED" />
 		<field name="ACTION_ACL_DISCONNECTED" />
@@ -4703,6 +4818,10 @@
 		<field name="BOND_BONDING" />
 		<field name="BOND_NONE" />
 		<field name="CREATOR" />
+		<field name="DEVICE_TYPE_CLASSIC" since="18" />
+		<field name="DEVICE_TYPE_DUAL" since="18" />
+		<field name="DEVICE_TYPE_LE" since="18" />
+		<field name="DEVICE_TYPE_UNKNOWN" since="18" />
 		<field name="ERROR" />
 		<field name="EXTRA_BOND_STATE" />
 		<field name="EXTRA_CLASS" />
@@ -4712,6 +4831,161 @@
 		<field name="EXTRA_RSSI" />
 		<field name="EXTRA_UUID" since="15" />
 	</class>
+	<class name="android/bluetooth/BluetoothGatt" since="18">
+		<extends name="java/lang/Object" />
+		<implements name="android/bluetooth/BluetoothProfile" />
+		<method name="&lt;init>()V" />
+		<method name="abortReliableWrite(Landroid/bluetooth/BluetoothDevice;)V" />
+		<method name="beginReliableWrite()Z" />
+		<method name="close()V" />
+		<method name="connect()Z" />
+		<method name="disconnect()V" />
+		<method name="discoverServices()Z" />
+		<method name="executeReliableWrite()Z" />
+		<method name="getDevice()Landroid/bluetooth/BluetoothDevice;" />
+		<method name="getService(Ljava/util/UUID;)Landroid/bluetooth/BluetoothGattService;" />
+		<method name="getServices()Ljava/util/List;" />
+		<method name="readCharacteristic(Landroid/bluetooth/BluetoothGattCharacteristic;)Z" />
+		<method name="readDescriptor(Landroid/bluetooth/BluetoothGattDescriptor;)Z" />
+		<method name="readRemoteRssi()Z" />
+		<method name="setCharacteristicNotification(Landroid/bluetooth/BluetoothGattCharacteristic;Z)Z" />
+		<method name="writeCharacteristic(Landroid/bluetooth/BluetoothGattCharacteristic;)Z" />
+		<method name="writeDescriptor(Landroid/bluetooth/BluetoothGattDescriptor;)Z" />
+		<field name="GATT_FAILURE" />
+		<field name="GATT_INSUFFICIENT_AUTHENTICATION" />
+		<field name="GATT_INSUFFICIENT_ENCRYPTION" />
+		<field name="GATT_INVALID_ATTRIBUTE_LENGTH" />
+		<field name="GATT_INVALID_OFFSET" />
+		<field name="GATT_READ_NOT_PERMITTED" />
+		<field name="GATT_REQUEST_NOT_SUPPORTED" />
+		<field name="GATT_SUCCESS" />
+		<field name="GATT_WRITE_NOT_PERMITTED" />
+	</class>
+	<class name="android/bluetooth/BluetoothGattCallback" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>()V" />
+		<method name="onCharacteristicChanged(Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;)V" />
+		<method name="onCharacteristicRead(Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;I)V" />
+		<method name="onCharacteristicWrite(Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;I)V" />
+		<method name="onConnectionStateChange(Landroid/bluetooth/BluetoothGatt;II)V" />
+		<method name="onDescriptorRead(Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattDescriptor;I)V" />
+		<method name="onDescriptorWrite(Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattDescriptor;I)V" />
+		<method name="onReadRemoteRssi(Landroid/bluetooth/BluetoothGatt;II)V" />
+		<method name="onReliableWriteCompleted(Landroid/bluetooth/BluetoothGatt;I)V" />
+		<method name="onServicesDiscovered(Landroid/bluetooth/BluetoothGatt;I)V" />
+	</class>
+	<class name="android/bluetooth/BluetoothGattCharacteristic" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>(Ljava/util/UUID;II)V" />
+		<method name="addDescriptor(Landroid/bluetooth/BluetoothGattDescriptor;)Z" />
+		<method name="getDescriptor(Ljava/util/UUID;)Landroid/bluetooth/BluetoothGattDescriptor;" />
+		<method name="getDescriptors()Ljava/util/List;" />
+		<method name="getFloatValue(II)Ljava/lang/Float;" />
+		<method name="getInstanceId()I" />
+		<method name="getIntValue(II)Ljava/lang/Integer;" />
+		<method name="getPermissions()I" />
+		<method name="getProperties()I" />
+		<method name="getService()Landroid/bluetooth/BluetoothGattService;" />
+		<method name="getStringValue(I)Ljava/lang/String;" />
+		<method name="getUuid()Ljava/util/UUID;" />
+		<method name="getValue()[B" />
+		<method name="getWriteType()I" />
+		<method name="setValue(III)Z" />
+		<method name="setValue(IIII)Z" />
+		<method name="setValue(Ljava/lang/String;)Z" />
+		<method name="setValue([B)Z" />
+		<method name="setWriteType(I)V" />
+		<field name="FORMAT_FLOAT" />
+		<field name="FORMAT_SFLOAT" />
+		<field name="FORMAT_SINT16" />
+		<field name="FORMAT_SINT32" />
+		<field name="FORMAT_SINT8" />
+		<field name="FORMAT_UINT16" />
+		<field name="FORMAT_UINT32" />
+		<field name="FORMAT_UINT8" />
+		<field name="PERMISSION_READ" />
+		<field name="PERMISSION_READ_ENCRYPTED" />
+		<field name="PERMISSION_READ_ENCRYPTED_MITM" />
+		<field name="PERMISSION_WRITE" />
+		<field name="PERMISSION_WRITE_ENCRYPTED" />
+		<field name="PERMISSION_WRITE_ENCRYPTED_MITM" />
+		<field name="PERMISSION_WRITE_SIGNED" />
+		<field name="PERMISSION_WRITE_SIGNED_MITM" />
+		<field name="PROPERTY_BROADCAST" />
+		<field name="PROPERTY_EXTENDED_PROPS" />
+		<field name="PROPERTY_INDICATE" />
+		<field name="PROPERTY_NOTIFY" />
+		<field name="PROPERTY_READ" />
+		<field name="PROPERTY_SIGNED_WRITE" />
+		<field name="PROPERTY_WRITE" />
+		<field name="PROPERTY_WRITE_NO_RESPONSE" />
+		<field name="WRITE_TYPE_DEFAULT" />
+		<field name="WRITE_TYPE_NO_RESPONSE" />
+		<field name="WRITE_TYPE_SIGNED" />
+		<field name="mDescriptors" />
+	</class>
+	<class name="android/bluetooth/BluetoothGattDescriptor" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>(Ljava/util/UUID;I)V" />
+		<method name="getCharacteristic()Landroid/bluetooth/BluetoothGattCharacteristic;" />
+		<method name="getPermissions()I" />
+		<method name="getUuid()Ljava/util/UUID;" />
+		<method name="getValue()[B" />
+		<method name="setValue([B)Z" />
+		<field name="DISABLE_NOTIFICATION_VALUE" />
+		<field name="ENABLE_INDICATION_VALUE" />
+		<field name="ENABLE_NOTIFICATION_VALUE" />
+		<field name="PERMISSION_READ" />
+		<field name="PERMISSION_READ_ENCRYPTED" />
+		<field name="PERMISSION_READ_ENCRYPTED_MITM" />
+		<field name="PERMISSION_WRITE" />
+		<field name="PERMISSION_WRITE_ENCRYPTED" />
+		<field name="PERMISSION_WRITE_ENCRYPTED_MITM" />
+		<field name="PERMISSION_WRITE_SIGNED" />
+		<field name="PERMISSION_WRITE_SIGNED_MITM" />
+	</class>
+	<class name="android/bluetooth/BluetoothGattServer" since="18">
+		<extends name="java/lang/Object" />
+		<implements name="android/bluetooth/BluetoothProfile" />
+		<method name="&lt;init>()V" />
+		<method name="addService(Landroid/bluetooth/BluetoothGattService;)Z" />
+		<method name="cancelConnection(Landroid/bluetooth/BluetoothDevice;)V" />
+		<method name="clearServices()V" />
+		<method name="close()V" />
+		<method name="connect(Landroid/bluetooth/BluetoothDevice;Z)Z" />
+		<method name="getService(Ljava/util/UUID;)Landroid/bluetooth/BluetoothGattService;" />
+		<method name="getServices()Ljava/util/List;" />
+		<method name="notifyCharacteristicChanged(Landroid/bluetooth/BluetoothDevice;Landroid/bluetooth/BluetoothGattCharacteristic;Z)Z" />
+		<method name="removeService(Landroid/bluetooth/BluetoothGattService;)Z" />
+		<method name="sendResponse(Landroid/bluetooth/BluetoothDevice;III[B)Z" />
+	</class>
+	<class name="android/bluetooth/BluetoothGattServerCallback" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>()V" />
+		<method name="onCharacteristicReadRequest(Landroid/bluetooth/BluetoothDevice;IILandroid/bluetooth/BluetoothGattCharacteristic;)V" />
+		<method name="onCharacteristicWriteRequest(Landroid/bluetooth/BluetoothDevice;ILandroid/bluetooth/BluetoothGattCharacteristic;ZZI[B)V" />
+		<method name="onConnectionStateChange(Landroid/bluetooth/BluetoothDevice;II)V" />
+		<method name="onDescriptorReadRequest(Landroid/bluetooth/BluetoothDevice;IILandroid/bluetooth/BluetoothGattDescriptor;)V" />
+		<method name="onDescriptorWriteRequest(Landroid/bluetooth/BluetoothDevice;ILandroid/bluetooth/BluetoothGattDescriptor;ZZI[B)V" />
+		<method name="onExecuteWrite(Landroid/bluetooth/BluetoothDevice;IZ)V" />
+		<method name="onServiceAdded(ILandroid/bluetooth/BluetoothGattService;)V" />
+	</class>
+	<class name="android/bluetooth/BluetoothGattService" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>(Ljava/util/UUID;I)V" />
+		<method name="addCharacteristic(Landroid/bluetooth/BluetoothGattCharacteristic;)Z" />
+		<method name="addService(Landroid/bluetooth/BluetoothGattService;)Z" />
+		<method name="getCharacteristic(Ljava/util/UUID;)Landroid/bluetooth/BluetoothGattCharacteristic;" />
+		<method name="getCharacteristics()Ljava/util/List;" />
+		<method name="getIncludedServices()Ljava/util/List;" />
+		<method name="getInstanceId()I" />
+		<method name="getType()I" />
+		<method name="getUuid()Ljava/util/UUID;" />
+		<field name="SERVICE_TYPE_PRIMARY" />
+		<field name="SERVICE_TYPE_SECONDARY" />
+		<field name="mCharacteristics" />
+		<field name="mIncludedServices" />
+	</class>
 	<class name="android/bluetooth/BluetoothHeadset" since="11">
 		<extends name="java/lang/Object" />
 		<implements name="android/bluetooth/BluetoothProfile" />
@@ -4772,6 +5046,15 @@
 		<method name="onHealthAppConfigurationStatusChange(Landroid/bluetooth/BluetoothHealthAppConfiguration;I)V" />
 		<method name="onHealthChannelStateChange(Landroid/bluetooth/BluetoothHealthAppConfiguration;Landroid/bluetooth/BluetoothDevice;IILandroid/os/ParcelFileDescriptor;I)V" />
 	</class>
+	<class name="android/bluetooth/BluetoothManager" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>()V" />
+		<method name="getAdapter()Landroid/bluetooth/BluetoothAdapter;" />
+		<method name="getConnectedDevices(I)Ljava/util/List;" />
+		<method name="getConnectionState(Landroid/bluetooth/BluetoothDevice;I)I" />
+		<method name="getDevicesMatchingConnectionStates(I[I)Ljava/util/List;" />
+		<method name="openGattServer(Landroid/content/Context;Landroid/bluetooth/BluetoothGattServerCallback;)Landroid/bluetooth/BluetoothGattServer;" />
+	</class>
 	<class name="android/bluetooth/BluetoothProfile" since="11">
 		<extends name="java/lang/Object" />
 		<method name="getConnectedDevices()Ljava/util/List;" />
@@ -4780,6 +5063,8 @@
 		<field name="A2DP" />
 		<field name="EXTRA_PREVIOUS_STATE" />
 		<field name="EXTRA_STATE" />
+		<field name="GATT" since="18" />
+		<field name="GATT_SERVER" since="18" />
 		<field name="HEADSET" />
 		<field name="HEALTH" since="14" />
 		<field name="STATE_CONNECTED" />
@@ -5017,6 +5302,7 @@
 		<method name="bulkInsert(Landroid/net/Uri;[Landroid/content/ContentValues;)I" />
 		<method name="call(Ljava/lang/String;Ljava/lang/String;Landroid/os/Bundle;)Landroid/os/Bundle;" since="11" />
 		<method name="delete(Landroid/net/Uri;Ljava/lang/String;[Ljava/lang/String;)I" />
+		<method name="dump(Ljava/io/FileDescriptor;Ljava/io/PrintWriter;[Ljava/lang/String;)V" since="18" />
 		<method name="getContext()Landroid/content/Context;" />
 		<method name="getPathPermissions()[Landroid/content/pm/PathPermission;" since="4" />
 		<method name="getReadPermission()Ljava/lang/String;" />
@@ -5332,6 +5618,7 @@
 		<field name="BIND_IMPORTANT" since="14" />
 		<field name="BIND_NOT_FOREGROUND" since="8" />
 		<field name="BIND_WAIVE_PRIORITY" since="14" />
+		<field name="BLUETOOTH_SERVICE" since="18" />
 		<field name="CLIPBOARD_SERVICE" />
 		<field name="CONNECTIVITY_SERVICE" />
 		<field name="CONTEXT_IGNORE_SECURITY" />
@@ -5611,6 +5898,7 @@
 		<field name="ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE" since="8" />
 		<field name="ACTION_FACTORY_TEST" />
 		<field name="ACTION_GET_CONTENT" />
+		<field name="ACTION_GET_RESTRICTION_ENTRIES" since="18" />
 		<field name="ACTION_GTALK_SERVICE_CONNECTED" />
 		<field name="ACTION_GTALK_SERVICE_DISCONNECTED" />
 		<field name="ACTION_HEADSET_PLUG" />
@@ -5719,7 +6007,10 @@
 		<field name="CATEGORY_UNIT_TEST" />
 		<field name="CREATOR" />
 		<field name="EXTRA_ALARM_COUNT" />
+		<field name="EXTRA_ALLOW_MULTIPLE" since="18" />
 		<field name="EXTRA_ALLOW_REPLACE" since="14" />
+		<field name="EXTRA_ASSIST_CONTEXT" since="18" />
+		<field name="EXTRA_ASSIST_PACKAGE" since="18" />
 		<field name="EXTRA_BCC" />
 		<field name="EXTRA_BUG_REPORT" since="14" />
 		<field name="EXTRA_CC" />
@@ -5748,6 +6039,9 @@
 		<field name="EXTRA_REFERRER" since="17" />
 		<field name="EXTRA_REMOTE_INTENT_TOKEN" since="5" />
 		<field name="EXTRA_REPLACING" since="3" />
+		<field name="EXTRA_RESTRICTIONS_BUNDLE" since="18" />
+		<field name="EXTRA_RESTRICTIONS_INTENT" since="18" />
+		<field name="EXTRA_RESTRICTIONS_LIST" since="18" />
 		<field name="EXTRA_RETURN_RESULT" since="14" />
 		<field name="EXTRA_SHORTCUT_ICON" />
 		<field name="EXTRA_SHORTCUT_ICON_RESOURCE" />
@@ -5917,6 +6211,7 @@
 		<method name="&lt;init>(Landroid/content/Context;)V" />
 		<method name="abandon()V" />
 		<method name="cancelLoad()Z" since="16" />
+		<method name="commitContentChanged()V" since="18" />
 		<method name="dataToString(Ljava/lang/Object;)Ljava/lang/String;" />
 		<method name="deliverCancellation()V" since="16" />
 		<method name="deliverResult(Ljava/lang/Object;)V" />
@@ -5937,6 +6232,7 @@
 		<method name="registerListener(ILandroid/content/Loader$OnLoadCompleteListener;)V" />
 		<method name="registerOnLoadCanceledListener(Landroid/content/Loader$OnLoadCanceledListener;)V" since="16" />
 		<method name="reset()V" />
+		<method name="rollbackContentChanged()V" since="18" />
 		<method name="startLoading()V" />
 		<method name="stopLoading()V" />
 		<method name="takeContentChanged()Z" />
@@ -5984,6 +6280,38 @@
 		<extends name="android/util/AndroidRuntimeException" />
 		<method name="&lt;init>(Ljava/lang/String;)V" />
 	</class>
+	<class name="android/content/RestrictionEntry" since="18">
+		<extends name="java/lang/Object" />
+		<implements name="android/os/Parcelable" />
+		<method name="&lt;init>(Landroid/os/Parcel;)V" />
+		<method name="&lt;init>(Ljava/lang/String;Ljava/lang/String;)V" />
+		<method name="&lt;init>(Ljava/lang/String;Z)V" />
+		<method name="&lt;init>(Ljava/lang/String;[Ljava/lang/String;)V" />
+		<method name="getAllSelectedStrings()[Ljava/lang/String;" />
+		<method name="getChoiceEntries()[Ljava/lang/String;" />
+		<method name="getChoiceValues()[Ljava/lang/String;" />
+		<method name="getDescription()Ljava/lang/String;" />
+		<method name="getKey()Ljava/lang/String;" />
+		<method name="getSelectedState()Z" />
+		<method name="getSelectedString()Ljava/lang/String;" />
+		<method name="getTitle()Ljava/lang/String;" />
+		<method name="getType()I" />
+		<method name="setAllSelectedStrings([Ljava/lang/String;)V" />
+		<method name="setChoiceEntries(Landroid/content/Context;I)V" />
+		<method name="setChoiceEntries([Ljava/lang/String;)V" />
+		<method name="setChoiceValues(Landroid/content/Context;I)V" />
+		<method name="setChoiceValues([Ljava/lang/String;)V" />
+		<method name="setDescription(Ljava/lang/String;)V" />
+		<method name="setSelectedState(Z)V" />
+		<method name="setSelectedString(Ljava/lang/String;)V" />
+		<method name="setTitle(Ljava/lang/String;)V" />
+		<method name="setType(I)V" />
+		<field name="CREATOR" />
+		<field name="TYPE_BOOLEAN" />
+		<field name="TYPE_CHOICE" />
+		<field name="TYPE_MULTI_SELECT" />
+		<field name="TYPE_NULL" />
+	</class>
 	<class name="android/content/SearchRecentSuggestionsProvider" since="1">
 		<extends name="android/content/ContentProvider" />
 		<method name="&lt;init>()V" />
@@ -6137,6 +6465,7 @@
 		<field name="FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS" since="5" />
 		<field name="FLAG_FINISH_ON_TASK_LAUNCH" />
 		<field name="FLAG_HARDWARE_ACCELERATED" since="11" />
+		<field name="FLAG_IMMERSIVE" since="18" />
 		<field name="FLAG_MULTIPROCESS" />
 		<field name="FLAG_NO_HISTORY" since="3" />
 		<field name="FLAG_SINGLE_USER" since="17" />
@@ -6147,7 +6476,9 @@
 		<field name="LAUNCH_SINGLE_TOP" />
 		<field name="SCREEN_ORIENTATION_BEHIND" />
 		<field name="SCREEN_ORIENTATION_FULL_SENSOR" since="9" />
+		<field name="SCREEN_ORIENTATION_FULL_USER" since="18" />
 		<field name="SCREEN_ORIENTATION_LANDSCAPE" />
+		<field name="SCREEN_ORIENTATION_LOCKED" since="18" />
 		<field name="SCREEN_ORIENTATION_NOSENSOR" />
 		<field name="SCREEN_ORIENTATION_PORTRAIT" />
 		<field name="SCREEN_ORIENTATION_REVERSE_LANDSCAPE" since="9" />
@@ -6157,6 +6488,8 @@
 		<field name="SCREEN_ORIENTATION_SENSOR_PORTRAIT" since="9" />
 		<field name="SCREEN_ORIENTATION_UNSPECIFIED" />
 		<field name="SCREEN_ORIENTATION_USER" />
+		<field name="SCREEN_ORIENTATION_USER_LANDSCAPE" since="18" />
+		<field name="SCREEN_ORIENTATION_USER_PORTRAIT" since="18" />
 		<field name="UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW" since="14" />
 		<field name="configChanges" />
 		<field name="flags" />
@@ -6405,6 +6738,7 @@
 		<method name="getPackageGids(Ljava/lang/String;)[I" />
 		<method name="getPackageInfo(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;" />
 		<method name="getPackagesForUid(I)[Ljava/lang/String;" />
+		<method name="getPackagesHoldingPermissions([Ljava/lang/String;I)Ljava/util/List;" since="18" />
 		<method name="getPermissionGroupInfo(Ljava/lang/String;I)Landroid/content/pm/PermissionGroupInfo;" />
 		<method name="getPermissionInfo(Ljava/lang/String;I)Landroid/content/pm/PermissionInfo;" />
 		<method name="getPreferredActivities(Ljava/util/List;Ljava/util/List;Ljava/lang/String;)I" />
@@ -6441,13 +6775,16 @@
 		<method name="verifyPendingInstall(II)V" since="14" />
 		<field name="COMPONENT_ENABLED_STATE_DEFAULT" />
 		<field name="COMPONENT_ENABLED_STATE_DISABLED" />
+		<field name="COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED" since="18" />
 		<field name="COMPONENT_ENABLED_STATE_DISABLED_USER" since="14" />
 		<field name="COMPONENT_ENABLED_STATE_ENABLED" />
 		<field name="DONT_KILL_APP" />
 		<field name="EXTRA_VERIFICATION_ID" since="14" />
 		<field name="EXTRA_VERIFICATION_RESULT" since="17" />
+		<field name="FEATURE_APP_WIDGETS" since="18" />
 		<field name="FEATURE_AUDIO_LOW_LATENCY" since="9" />
 		<field name="FEATURE_BLUETOOTH" since="8" />
+		<field name="FEATURE_BLUETOOTH_LE" since="18" />
 		<field name="FEATURE_CAMERA" since="7" />
 		<field name="FEATURE_CAMERA_ANY" since="17" />
 		<field name="FEATURE_CAMERA_AUTOFOCUS" since="7" />
@@ -6456,6 +6793,8 @@
 		<field name="FEATURE_FAKETOUCH" since="11" />
 		<field name="FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT" since="13" />
 		<field name="FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND" since="13" />
+		<field name="FEATURE_HOME_SCREEN" since="18" />
+		<field name="FEATURE_INPUT_METHODS" since="18" />
 		<field name="FEATURE_LIVE_WALLPAPER" since="7" />
 		<field name="FEATURE_LOCATION" since="8" />
 		<field name="FEATURE_LOCATION_GPS" since="8" />
@@ -6488,6 +6827,7 @@
 		<field name="GET_ACTIVITIES" />
 		<field name="GET_CONFIGURATIONS" since="3" />
 		<field name="GET_DISABLED_COMPONENTS" />
+		<field name="GET_DISABLED_UNTIL_USED_COMPONENTS" since="18" />
 		<field name="GET_GIDS" />
 		<field name="GET_INSTRUMENTATION" />
 		<field name="GET_INTENT_FILTERS" />
@@ -6563,17 +6903,6 @@
 		<field name="externalObbSize" since="11" />
 		<field name="packageName" />
 	</class>
-	<class name="android/content/pm/PackageUserState" since="17">
-		<extends name="java/lang/Object" />
-		<method name="&lt;init>()V" />
-		<method name="&lt;init>(Landroid/content/pm/PackageUserState;)V" />
-		<field name="disabledComponents" />
-		<field name="enabled" />
-		<field name="enabledComponents" />
-		<field name="installed" />
-		<field name="notLaunched" />
-		<field name="stopped" />
-	</class>
 	<class name="android/content/pm/PathPermission" since="4">
 		<extends name="android/os/PatternMatcher" />
 		<method name="&lt;init>(Landroid/os/Parcel;)V" />
@@ -9080,8 +9409,11 @@
 		<method name="getPaint()Landroid/graphics/Paint;" />
 		<method name="getTileModeX()Landroid/graphics/Shader$TileMode;" />
 		<method name="getTileModeY()Landroid/graphics/Shader$TileMode;" />
+		<method name="hasAntiAlias()Z" since="18" />
+		<method name="hasMipMap()Z" since="18" />
 		<method name="setAntiAlias(Z)V" />
 		<method name="setGravity(I)V" />
+		<method name="setMipMap(Z)V" since="18" />
 		<method name="setTargetDensity(I)V" since="4" />
 		<method name="setTargetDensity(Landroid/graphics/Canvas;)V" since="4" />
 		<method name="setTargetDensity(Landroid/util/DisplayMetrics;)V" since="4" />
@@ -9653,16 +9985,20 @@
 		<field name="TYPE_ACCELEROMETER" />
 		<field name="TYPE_ALL" />
 		<field name="TYPE_AMBIENT_TEMPERATURE" since="14" />
+		<field name="TYPE_GAME_ROTATION_VECTOR" since="18" />
 		<field name="TYPE_GRAVITY" since="9" />
 		<field name="TYPE_GYROSCOPE" />
+		<field name="TYPE_GYROSCOPE_UNCALIBRATED" since="18" />
 		<field name="TYPE_LIGHT" />
 		<field name="TYPE_LINEAR_ACCELERATION" since="9" />
 		<field name="TYPE_MAGNETIC_FIELD" />
+		<field name="TYPE_MAGNETIC_FIELD_UNCALIBRATED" since="18" />
 		<field name="TYPE_ORIENTATION" />
 		<field name="TYPE_PRESSURE" />
 		<field name="TYPE_PROXIMITY" />
 		<field name="TYPE_RELATIVE_HUMIDITY" since="14" />
 		<field name="TYPE_ROTATION_VECTOR" since="9" />
+		<field name="TYPE_SIGNIFICANT_MOTION" since="18" />
 		<field name="TYPE_TEMPERATURE" />
 	</class>
 	<class name="android/hardware/SensorEvent" since="3">
@@ -9686,6 +10022,7 @@
 	<class name="android/hardware/SensorManager" since="1">
 		<extends name="java/lang/Object" />
 		<method name="&lt;init>()V" />
+		<method name="cancelTriggerSensor(Landroid/hardware/TriggerEventListener;Landroid/hardware/Sensor;)Z" since="18" />
 		<method name="getAltitude(FF)F" since="9" />
 		<method name="getAngleChange([F[F[F)V" since="9" />
 		<method name="getDefaultSensor(I)Landroid/hardware/Sensor;" since="3" />
@@ -9701,6 +10038,7 @@
 		<method name="registerListener(Landroid/hardware/SensorListener;I)Z" />
 		<method name="registerListener(Landroid/hardware/SensorListener;II)Z" />
 		<method name="remapCoordinateSystem([FII[F)Z" since="3" />
+		<method name="requestTriggerSensor(Landroid/hardware/TriggerEventListener;Landroid/hardware/Sensor;)Z" since="18" />
 		<method name="unregisterListener(Landroid/hardware/SensorEventListener;)V" since="3" />
 		<method name="unregisterListener(Landroid/hardware/SensorEventListener;Landroid/hardware/Sensor;)V" since="3" />
 		<method name="unregisterListener(Landroid/hardware/SensorListener;)V" />
@@ -9763,6 +10101,18 @@
 		<field name="SENSOR_TRICORDER" />
 		<field name="STANDARD_GRAVITY" />
 	</class>
+	<class name="android/hardware/TriggerEvent" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>()V" />
+		<field name="sensor" />
+		<field name="timestamp" />
+		<field name="values" />
+	</class>
+	<class name="android/hardware/TriggerEventListener" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>()V" />
+		<method name="onTrigger(Landroid/hardware/TriggerEvent;)V" />
+	</class>
 	<class name="android/hardware/display/DisplayManager" since="17">
 		<extends name="java/lang/Object" />
 		<method name="&lt;init>()V" />
@@ -9795,6 +10145,61 @@
 		<method name="onInputDeviceChanged(I)V" />
 		<method name="onInputDeviceRemoved(I)V" />
 	</class>
+	<class name="android/hardware/location/GeofenceHardware" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>()V" />
+		<method name="addGeofence(IILandroid/hardware/location/GeofenceHardwareRequest;Landroid/hardware/location/GeofenceHardwareCallback;)Z" />
+		<method name="getMonitoringTypes()[I" />
+		<method name="getStatusOfMonitoringType(I)I" />
+		<method name="pauseGeofence(II)Z" />
+		<method name="registerForMonitorStateChangeCallback(ILandroid/hardware/location/GeofenceHardwareMonitorCallback;)Z" />
+		<method name="removeGeofence(II)Z" />
+		<method name="resumeGeofence(III)Z" />
+		<method name="unregisterForMonitorStateChangeCallback(ILandroid/hardware/location/GeofenceHardwareMonitorCallback;)Z" />
+		<field name="GEOFENCE_ENTERED" />
+		<field name="GEOFENCE_ERROR_ID_EXISTS" />
+		<field name="GEOFENCE_ERROR_ID_UNKNOWN" />
+		<field name="GEOFENCE_ERROR_INVALID_TRANSITION" />
+		<field name="GEOFENCE_ERROR_TOO_MANY_GEOFENCES" />
+		<field name="GEOFENCE_EXITED" />
+		<field name="GEOFENCE_FAILURE" />
+		<field name="GEOFENCE_SUCCESS" />
+		<field name="GEOFENCE_UNCERTAIN" />
+		<field name="MONITORING_TYPE_GPS_HARDWARE" />
+		<field name="MONITOR_CURRENTLY_AVAILABLE" />
+		<field name="MONITOR_CURRENTLY_UNAVAILABLE" />
+		<field name="MONITOR_UNSUPPORTED" />
+	</class>
+	<class name="android/hardware/location/GeofenceHardwareCallback" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>()V" />
+		<method name="onGeofenceAdd(II)V" />
+		<method name="onGeofencePause(II)V" />
+		<method name="onGeofenceRemove(II)V" />
+		<method name="onGeofenceResume(II)V" />
+		<method name="onGeofenceTransition(IILandroid/location/Location;JI)V" />
+	</class>
+	<class name="android/hardware/location/GeofenceHardwareMonitorCallback" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>()V" />
+		<method name="onMonitoringSystemChange(IZLandroid/location/Location;)V" />
+	</class>
+	<class name="android/hardware/location/GeofenceHardwareRequest" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>()V" />
+		<method name="createCircularGeofence(DDD)Landroid/hardware/location/GeofenceHardwareRequest;" />
+		<method name="getLastTransition()I" />
+		<method name="getLatitude()D" />
+		<method name="getLongitude()D" />
+		<method name="getMonitorTransitions()I" />
+		<method name="getNotificationResponsiveness()I" />
+		<method name="getRadius()D" />
+		<method name="getUnknownTimer()I" />
+		<method name="setLastTransition(I)V" />
+		<method name="setMonitorTransitions(I)V" />
+		<method name="setNotificationResponsiveness(I)V" />
+		<method name="setUnknownTimer(I)V" />
+	</class>
 	<class name="android/hardware/usb/UsbAccessory" since="12">
 		<extends name="java/lang/Object" />
 		<implements name="android/os/Parcelable" />
@@ -9865,9 +10270,11 @@
 		<extends name="java/lang/Object" />
 		<method name="&lt;init>()V" />
 		<method name="bulkTransfer(Landroid/hardware/usb/UsbEndpoint;[BII)I" />
+		<method name="bulkTransfer(Landroid/hardware/usb/UsbEndpoint;[BIII)I" since="18" />
 		<method name="claimInterface(Landroid/hardware/usb/UsbInterface;Z)Z" />
 		<method name="close()V" />
 		<method name="controlTransfer(IIII[BII)I" />
+		<method name="controlTransfer(IIII[BIII)I" since="18" />
 		<method name="getFileDescriptor()I" />
 		<method name="getRawDescriptors()[B" since="13" />
 		<method name="getSerial()Ljava/lang/String;" />
@@ -10258,13 +10665,6 @@
 		<method name="getFromLocationName(Ljava/lang/String;IDDDD)Ljava/util/List;" />
 		<method name="isPresent()Z" since="9" />
 	</class>
-	<class name="android/location/Geofence" since="17">
-		<extends name="java/lang/Object" />
-		<implements name="android/os/Parcelable" />
-		<method name="&lt;init>()V" />
-		<method name="createCircle(DDF)Landroid/location/Geofence;" />
-		<field name="CREATOR" />
-	</class>
 	<class name="android/location/GpsSatellite" since="3">
 		<extends name="java/lang/Object" />
 		<method name="&lt;init>()V" />
@@ -10320,6 +10720,7 @@
 		<method name="hasAltitude()Z" />
 		<method name="hasBearing()Z" />
 		<method name="hasSpeed()Z" />
+		<method name="isFromMockProvider()Z" since="18" />
 		<method name="removeAccuracy()V" />
 		<method name="removeAltitude()V" />
 		<method name="removeBearing()V" />
@@ -10412,30 +10813,6 @@
 		<field name="OUT_OF_SERVICE" />
 		<field name="TEMPORARILY_UNAVAILABLE" />
 	</class>
-	<class name="android/location/LocationRequest" since="17">
-		<extends name="java/lang/Object" />
-		<implements name="android/os/Parcelable" />
-		<method name="&lt;init>()V" />
-		<method name="create()Landroid/location/LocationRequest;" />
-		<method name="getExpireAt()J" />
-		<method name="getFastestInterval()J" />
-		<method name="getInterval()J" />
-		<method name="getNumUpdates()I" />
-		<method name="getQuality()I" />
-		<method name="setExpireAt(J)Landroid/location/LocationRequest;" />
-		<method name="setExpireIn(J)Landroid/location/LocationRequest;" />
-		<method name="setFastestInterval(J)Landroid/location/LocationRequest;" />
-		<method name="setInterval(J)Landroid/location/LocationRequest;" />
-		<method name="setNumUpdates(I)Landroid/location/LocationRequest;" />
-		<method name="setQuality(I)Landroid/location/LocationRequest;" />
-		<field name="ACCURACY_BLOCK" />
-		<field name="ACCURACY_CITY" />
-		<field name="ACCURACY_FINE" />
-		<field name="CREATOR" />
-		<field name="POWER_HIGH" />
-		<field name="POWER_LOW" />
-		<field name="POWER_NONE" />
-	</class>
 	<class name="android/media/AsyncPlayer" since="1">
 		<extends name="java/lang/Object" />
 		<method name="&lt;init>(Ljava/lang/String;)V" />
@@ -10513,6 +10890,7 @@
 		<method name="loadSoundEffects()V" />
 		<method name="playSoundEffect(I)V" />
 		<method name="playSoundEffect(IF)V" since="3" />
+		<method name="registerMediaButtonEventReceiver(Landroid/app/PendingIntent;)V" since="18" />
 		<method name="registerMediaButtonEventReceiver(Landroid/content/ComponentName;)V" since="8" />
 		<method name="registerRemoteControlClient(Landroid/media/RemoteControlClient;)V" since="14" />
 		<method name="requestAudioFocus(Landroid/media/AudioManager$OnAudioFocusChangeListener;II)I" since="8" />
@@ -10533,6 +10911,7 @@
 		<method name="startBluetoothSco()V" since="8" />
 		<method name="stopBluetoothSco()V" since="8" />
 		<method name="unloadSoundEffects()V" />
+		<method name="unregisterMediaButtonEventReceiver(Landroid/app/PendingIntent;)V" since="18" />
 		<method name="unregisterMediaButtonEventReceiver(Landroid/content/ComponentName;)V" since="8" />
 		<method name="unregisterRemoteControlClient(Landroid/media/RemoteControlClient;)V" since="14" />
 		<field name="ACTION_AUDIO_BECOMING_NOISY" since="3" />
@@ -10753,6 +11132,10 @@
 		<field name="QUALITY_LOW" />
 		<field name="QUALITY_MEDIUM" />
 	</class>
+	<class name="android/media/DeniedByServerException" since="18">
+		<extends name="android/media/MediaDrmException" />
+		<method name="&lt;init>(Ljava/lang/String;)V" />
+	</class>
 	<class name="android/media/ExifInterface" since="5">
 		<extends name="java/lang/Object" />
 		<method name="&lt;init>(Ljava/lang/String;)V" />
@@ -10861,10 +11244,13 @@
 		<method name="createByCodecName(Ljava/lang/String;)Landroid/media/MediaCodec;" />
 		<method name="createDecoderByType(Ljava/lang/String;)Landroid/media/MediaCodec;" />
 		<method name="createEncoderByType(Ljava/lang/String;)Landroid/media/MediaCodec;" />
+		<method name="createInputSurface()Landroid/view/Surface;" since="18" />
 		<method name="dequeueInputBuffer(J)I" />
 		<method name="dequeueOutputBuffer(Landroid/media/MediaCodec$BufferInfo;J)I" />
 		<method name="flush()V" />
+		<method name="getCodecInfo()Landroid/media/MediaCodecInfo;" since="18" />
 		<method name="getInputBuffers()[Ljava/nio/ByteBuffer;" />
+		<method name="getName()Ljava/lang/String;" since="18" />
 		<method name="getOutputBuffers()[Ljava/nio/ByteBuffer;" />
 		<method name="getOutputFormat()Landroid/media/MediaFormat;" />
 		<method name="queueInputBuffer(IIIJI)V" />
@@ -10872,6 +11258,7 @@
 		<method name="release()V" />
 		<method name="releaseOutputBuffer(IZ)V" />
 		<method name="setVideoScalingMode(I)V" />
+		<method name="signalEndOfInputStream()V" since="18" />
 		<method name="start()V" />
 		<method name="stop()V" />
 		<field name="BUFFER_FLAG_CODEC_CONFIG" />
@@ -10952,6 +11339,7 @@
 		<field name="COLOR_FormatRawBayer10bit" />
 		<field name="COLOR_FormatRawBayer8bit" />
 		<field name="COLOR_FormatRawBayer8bitcompressed" />
+		<field name="COLOR_FormatSurface" since="18" />
 		<field name="COLOR_FormatYCbYCr" />
 		<field name="COLOR_FormatYCrYCb" />
 		<field name="COLOR_FormatYUV411PackedPlanar" />
@@ -11047,6 +11435,11 @@
 		<field name="MPEG4ProfileSimpleFBA" />
 		<field name="MPEG4ProfileSimpleFace" />
 		<field name="MPEG4ProfileSimpleScalable" />
+		<field name="VP8Level_Version0" since="18" />
+		<field name="VP8Level_Version1" since="18" />
+		<field name="VP8Level_Version2" since="18" />
+		<field name="VP8Level_Version3" since="18" />
+		<field name="VP8ProfileMain" since="18" />
 		<field name="level" />
 		<field name="profile" />
 	</class>
@@ -11067,11 +11460,75 @@
 		<extends name="java/lang/Exception" />
 		<method name="&lt;init>(Ljava/lang/String;)V" />
 	</class>
+	<class name="android/media/MediaDrm" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>(Ljava/util/UUID;)V" />
+		<method name="closeSession([B)V" />
+		<method name="getCryptoSession([BLjava/lang/String;Ljava/lang/String;)Landroid/media/MediaDrm$CryptoSession;" />
+		<method name="getKeyRequest([B[BLjava/lang/String;ILjava/util/HashMap;)Landroid/media/MediaDrm$KeyRequest;" />
+		<method name="getPropertyByteArray(Ljava/lang/String;)[B" />
+		<method name="getPropertyString(Ljava/lang/String;)Ljava/lang/String;" />
+		<method name="getProvisionRequest()Landroid/media/MediaDrm$ProvisionRequest;" />
+		<method name="getSecureStops()Ljava/util/List;" />
+		<method name="isCryptoSchemeSupported(Ljava/util/UUID;)Z" />
+		<method name="openSession()[B" />
+		<method name="provideKeyResponse([B[B)[B" />
+		<method name="provideProvisionResponse([B)V" />
+		<method name="queryKeyStatus([B)Ljava/util/HashMap;" />
+		<method name="release()V" />
+		<method name="releaseSecureStops([B)V" />
+		<method name="removeKeys([B)V" />
+		<method name="restoreKeys([B[B)V" />
+		<method name="setOnEventListener(Landroid/media/MediaDrm$OnEventListener;)V" />
+		<method name="setPropertyByteArray(Ljava/lang/String;[B)V" />
+		<method name="setPropertyString(Ljava/lang/String;Ljava/lang/String;)V" />
+		<field name="EVENT_KEY_EXPIRED" />
+		<field name="EVENT_KEY_REQUIRED" />
+		<field name="EVENT_PROVISION_REQUIRED" />
+		<field name="EVENT_VENDOR_DEFINED" />
+		<field name="KEY_TYPE_OFFLINE" />
+		<field name="KEY_TYPE_RELEASE" />
+		<field name="KEY_TYPE_STREAMING" />
+		<field name="PROPERTY_ALGORITHMS" />
+		<field name="PROPERTY_DESCRIPTION" />
+		<field name="PROPERTY_DEVICE_UNIQUE_ID" />
+		<field name="PROPERTY_VENDOR" />
+		<field name="PROPERTY_VERSION" />
+	</class>
+	<class name="android/media/MediaDrm$CryptoSession" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>(Landroid/media/MediaDrm;)V" />
+		<method name="decrypt([B[B[B)[B" />
+		<method name="encrypt([B[B[B)[B" />
+		<method name="sign([B[B)[B" />
+		<method name="verify([B[B[B)Z" />
+	</class>
+	<class name="android/media/MediaDrm$KeyRequest" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>()V" />
+		<method name="getData()[B" />
+		<method name="getDefaultUrl()Ljava/lang/String;" />
+	</class>
+	<class name="android/media/MediaDrm$OnEventListener" since="18">
+		<extends name="java/lang/Object" />
+		<method name="onEvent(Landroid/media/MediaDrm;[BII[B)V" />
+	</class>
+	<class name="android/media/MediaDrm$ProvisionRequest" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>()V" />
+		<method name="getData()[B" />
+		<method name="getDefaultUrl()Ljava/lang/String;" />
+	</class>
+	<class name="android/media/MediaDrmException" since="18">
+		<extends name="java/lang/Exception" />
+		<method name="&lt;init>(Ljava/lang/String;)V" />
+	</class>
 	<class name="android/media/MediaExtractor" since="16">
 		<extends name="java/lang/Object" />
 		<method name="&lt;init>()V" />
 		<method name="advance()Z" />
 		<method name="getCachedDuration()J" />
+		<method name="getPsshInfo()Ljava/util/Map;" since="18" />
 		<method name="getSampleCryptoInfo(Landroid/media/MediaCodec$CryptoInfo;)Z" />
 		<method name="getSampleFlags()I" />
 		<method name="getSampleTime()J" />
@@ -11169,6 +11626,21 @@
 		<field name="OPTION_NEXT_SYNC" />
 		<field name="OPTION_PREVIOUS_SYNC" />
 	</class>
+	<class name="android/media/MediaMuxer" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>(Ljava/lang/String;I)V" />
+		<method name="addTrack(Landroid/media/MediaFormat;)I" />
+		<method name="release()V" />
+		<method name="setOrientationHint(I)V" />
+		<method name="start()V" />
+		<method name="stop()V" />
+		<method name="writeSampleData(ILjava/nio/ByteBuffer;Landroid/media/MediaCodec$BufferInfo;)V" />
+	</class>
+	<class name="android/media/MediaMuxer$OutputFormat" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>()V" />
+		<field name="MUXER_OUTPUT_MPEG_4" />
+	</class>
 	<class name="android/media/MediaPlayer" since="1">
 		<extends name="java/lang/Object" />
 		<method name="&lt;init>()V" />
@@ -11384,6 +11856,7 @@
 		<extends name="java/lang/Object" />
 		<method name="&lt;init>()V" />
 		<method name="addCallback(ILandroid/media/MediaRouter$Callback;)V" />
+		<method name="addCallback(ILandroid/media/MediaRouter$Callback;I)V" since="18" />
 		<method name="addUserRoute(Landroid/media/MediaRouter$UserRouteInfo;)V" />
 		<method name="clearUserRoutes()V" />
 		<method name="createRouteCategory(IZ)Landroid/media/MediaRouter$RouteCategory;" />
@@ -11391,12 +11864,15 @@
 		<method name="createUserRoute(Landroid/media/MediaRouter$RouteCategory;)Landroid/media/MediaRouter$UserRouteInfo;" />
 		<method name="getCategoryAt(I)Landroid/media/MediaRouter$RouteCategory;" />
 		<method name="getCategoryCount()I" />
+		<method name="getDefaultRoute()Landroid/media/MediaRouter$RouteInfo;" since="18" />
 		<method name="getRouteAt(I)Landroid/media/MediaRouter$RouteInfo;" />
 		<method name="getRouteCount()I" />
 		<method name="getSelectedRoute(I)Landroid/media/MediaRouter$RouteInfo;" />
 		<method name="removeCallback(Landroid/media/MediaRouter$Callback;)V" />
 		<method name="removeUserRoute(Landroid/media/MediaRouter$UserRouteInfo;)V" />
 		<method name="selectRoute(ILandroid/media/MediaRouter$RouteInfo;)V" />
+		<field name="CALLBACK_FLAG_PERFORM_ACTIVE_SCAN" since="18" />
+		<field name="CALLBACK_FLAG_UNFILTERED_EVENTS" since="18" />
 		<field name="ROUTE_TYPE_LIVE_AUDIO" />
 		<field name="ROUTE_TYPE_LIVE_VIDEO" since="17" />
 		<field name="ROUTE_TYPE_USER" />
@@ -11439,6 +11915,7 @@
 		<extends name="java/lang/Object" />
 		<method name="&lt;init>()V" />
 		<method name="getCategory()Landroid/media/MediaRouter$RouteCategory;" />
+		<method name="getDescription()Ljava/lang/CharSequence;" since="18" />
 		<method name="getGroup()Landroid/media/MediaRouter$RouteGroup;" />
 		<method name="getIconDrawable()Landroid/graphics/drawable/Drawable;" />
 		<method name="getName()Ljava/lang/CharSequence;" />
@@ -11452,6 +11929,7 @@
 		<method name="getVolume()I" />
 		<method name="getVolumeHandling()I" />
 		<method name="getVolumeMax()I" />
+		<method name="isConnecting()Z" since="18" />
 		<method name="isEnabled()Z" since="17" />
 		<method name="requestSetVolume(I)V" />
 		<method name="requestUpdateVolume(I)V" />
@@ -11469,6 +11947,7 @@
 		<extends name="android/media/MediaRouter$RouteInfo" />
 		<method name="&lt;init>()V" />
 		<method name="getRemoteControlClient()Landroid/media/RemoteControlClient;" />
+		<method name="setDescription(Ljava/lang/CharSequence;)V" since="18" />
 		<method name="setIconDrawable(Landroid/graphics/drawable/Drawable;)V" />
 		<method name="setIconResource(I)V" />
 		<method name="setName(I)V" />
@@ -11518,18 +11997,26 @@
 		<field name="SYNC_EVENT_NONE" />
 		<field name="SYNC_EVENT_PRESENTATION_COMPLETE" />
 	</class>
+	<class name="android/media/NotProvisionedException" since="18">
+		<extends name="android/media/MediaDrmException" />
+		<method name="&lt;init>(Ljava/lang/String;)V" />
+	</class>
 	<class name="android/media/RemoteControlClient" since="14">
 		<extends name="java/lang/Object" />
 		<method name="&lt;init>(Landroid/app/PendingIntent;)V" />
 		<method name="&lt;init>(Landroid/app/PendingIntent;Landroid/os/Looper;)V" />
 		<method name="editMetadata(Z)Landroid/media/RemoteControlClient$MetadataEditor;" />
+		<method name="setOnGetPlaybackPositionListener(Landroid/media/RemoteControlClient$OnGetPlaybackPositionListener;)V" since="18" />
+		<method name="setPlaybackPositionUpdateListener(Landroid/media/RemoteControlClient$OnPlaybackPositionUpdateListener;)V" since="18" />
 		<method name="setPlaybackState(I)V" />
+		<method name="setPlaybackState(IJF)V" since="18" />
 		<method name="setTransportControlFlags(I)V" />
 		<field name="FLAG_KEY_MEDIA_FAST_FORWARD" />
 		<field name="FLAG_KEY_MEDIA_NEXT" />
 		<field name="FLAG_KEY_MEDIA_PAUSE" />
 		<field name="FLAG_KEY_MEDIA_PLAY" />
 		<field name="FLAG_KEY_MEDIA_PLAY_PAUSE" />
+		<field name="FLAG_KEY_MEDIA_POSITION_UPDATE" since="18" />
 		<field name="FLAG_KEY_MEDIA_PREVIOUS" />
 		<field name="FLAG_KEY_MEDIA_REWIND" />
 		<field name="FLAG_KEY_MEDIA_STOP" />
@@ -11553,6 +12040,14 @@
 		<method name="putString(ILjava/lang/String;)Landroid/media/RemoteControlClient$MetadataEditor;" />
 		<field name="BITMAP_KEY_ARTWORK" />
 	</class>
+	<class name="android/media/RemoteControlClient$OnGetPlaybackPositionListener" since="18">
+		<extends name="java/lang/Object" />
+		<method name="onGetPlaybackPosition()J" />
+	</class>
+	<class name="android/media/RemoteControlClient$OnPlaybackPositionUpdateListener" since="18">
+		<extends name="java/lang/Object" />
+		<method name="onPlaybackPositionUpdate(J)V" />
+	</class>
 	<class name="android/media/Ringtone" since="1">
 		<extends name="java/lang/Object" />
 		<method name="&lt;init>()V" />
@@ -11751,6 +12246,10 @@
 		<field name="TONE_SUP_RADIO_NOTAVAIL" />
 		<field name="TONE_SUP_RINGTONE" />
 	</class>
+	<class name="android/media/UnsupportedSchemeException" since="18">
+		<extends name="android/media/MediaDrmException" />
+		<method name="&lt;init>(Ljava/lang/String;)V" />
+	</class>
 	<class name="android/media/audiofx/AcousticEchoCanceler" since="16">
 		<extends name="android/media/audiofx/AudioEffect" />
 		<method name="&lt;init>()V" />
@@ -11779,6 +12278,14 @@
 		<field name="CONTENT_TYPE_VOICE" />
 		<field name="EFFECT_AUXILIARY" />
 		<field name="EFFECT_INSERT" />
+		<field name="EFFECT_TYPE_AEC" since="18" />
+		<field name="EFFECT_TYPE_AGC" since="18" />
+		<field name="EFFECT_TYPE_BASS_BOOST" since="18" />
+		<field name="EFFECT_TYPE_ENV_REVERB" since="18" />
+		<field name="EFFECT_TYPE_EQUALIZER" since="18" />
+		<field name="EFFECT_TYPE_NS" since="18" />
+		<field name="EFFECT_TYPE_PRESET_REVERB" since="18" />
+		<field name="EFFECT_TYPE_VIRTUALIZER" since="18" />
 		<field name="ERROR" />
 		<field name="ERROR_BAD_VALUE" />
 		<field name="ERROR_DEAD_OBJECT" />
@@ -12999,6 +13506,7 @@
 		<field name="allowedKeyManagement" />
 		<field name="allowedPairwiseCiphers" />
 		<field name="allowedProtocols" />
+		<field name="enterpriseConfig" since="18" />
 		<field name="hiddenSSID" />
 		<field name="networkId" />
 		<field name="preSharedKey" />
@@ -13061,6 +13569,47 @@
 		<field name="ENABLED" />
 		<field name="strings" />
 	</class>
+	<class name="android/net/wifi/WifiEnterpriseConfig" since="18">
+		<extends name="java/lang/Object" />
+		<implements name="android/os/Parcelable" />
+		<method name="&lt;init>()V" />
+		<method name="&lt;init>(Landroid/net/wifi/WifiEnterpriseConfig;)V" />
+		<method name="getAnonymousIdentity()Ljava/lang/String;" />
+		<method name="getCaCertificate()Ljava/security/cert/X509Certificate;" />
+		<method name="getClientCertificate()Ljava/security/cert/X509Certificate;" />
+		<method name="getEapMethod()I" />
+		<method name="getIdentity()Ljava/lang/String;" />
+		<method name="getPassword()Ljava/lang/String;" />
+		<method name="getPhase2Method()I" />
+		<method name="getSubjectMatch()Ljava/lang/String;" />
+		<method name="setAnonymousIdentity(Ljava/lang/String;)V" />
+		<method name="setCaCertificate(Ljava/security/cert/X509Certificate;)V" />
+		<method name="setClientKeyEntry(Ljava/security/PrivateKey;Ljava/security/cert/X509Certificate;)V" />
+		<method name="setEapMethod(I)V" />
+		<method name="setIdentity(Ljava/lang/String;)V" />
+		<method name="setPassword(Ljava/lang/String;)V" />
+		<method name="setPhase2Method(I)V" />
+		<method name="setSubjectMatch(Ljava/lang/String;)V" />
+		<field name="CREATOR" />
+	</class>
+	<class name="android/net/wifi/WifiEnterpriseConfig$Eap" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>()V" />
+		<field name="NONE" />
+		<field name="PEAP" />
+		<field name="PWD" />
+		<field name="TLS" />
+		<field name="TTLS" />
+	</class>
+	<class name="android/net/wifi/WifiEnterpriseConfig$Phase2" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>()V" />
+		<field name="GTC" />
+		<field name="MSCHAP" />
+		<field name="MSCHAPV2" />
+		<field name="NONE" />
+		<field name="PAP" />
+	</class>
 	<class name="android/net/wifi/WifiInfo" since="1">
 		<extends name="java/lang/Object" />
 		<implements name="android/os/Parcelable" />
@@ -13094,6 +13643,7 @@
 		<method name="getDhcpInfo()Landroid/net/DhcpInfo;" />
 		<method name="getScanResults()Ljava/util/List;" />
 		<method name="getWifiState()I" />
+		<method name="isScanAlwaysAvailable()Z" since="18" />
 		<method name="isWifiEnabled()Z" />
 		<method name="pingSupplicant()Z" />
 		<method name="reassociate()Z" />
@@ -13104,6 +13654,7 @@
 		<method name="startScan()Z" />
 		<method name="updateNetwork(Landroid/net/wifi/WifiConfiguration;)I" />
 		<field name="ACTION_PICK_WIFI_NETWORK" />
+		<field name="ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE" since="18" />
 		<field name="ERROR_AUTHENTICATING" />
 		<field name="EXTRA_BSSID" />
 		<field name="EXTRA_NETWORK_INFO" />
@@ -13198,6 +13749,7 @@
 		<implements name="android/os/Parcelable" />
 		<method name="&lt;init>()V" />
 		<method name="&lt;init>(Landroid/net/wifi/p2p/WifiP2pDeviceList;)V" />
+		<method name="get(Ljava/lang/String;)Landroid/net/wifi/p2p/WifiP2pDevice;" since="18" />
 		<method name="getDeviceList()Ljava/util/Collection;" />
 		<field name="CREATOR" />
 	</class>
@@ -13251,7 +13803,9 @@
 		<field name="ERROR" />
 		<field name="EXTRA_DISCOVERY_STATE" since="16" />
 		<field name="EXTRA_NETWORK_INFO" />
+		<field name="EXTRA_P2P_DEVICE_LIST" since="18" />
 		<field name="EXTRA_WIFI_P2P_DEVICE" />
+		<field name="EXTRA_WIFI_P2P_GROUP" since="18" />
 		<field name="EXTRA_WIFI_P2P_INFO" />
 		<field name="EXTRA_WIFI_STATE" />
 		<field name="NO_SERVICE_REQUESTS" since="16" />
@@ -13412,12 +13966,18 @@
 		<method name="setNdefPushMessage(Landroid/nfc/NdefMessage;Landroid/app/Activity;[Landroid/app/Activity;)V" since="14" />
 		<method name="setNdefPushMessageCallback(Landroid/nfc/NfcAdapter$CreateNdefMessageCallback;Landroid/app/Activity;[Landroid/app/Activity;)V" since="14" />
 		<method name="setOnNdefPushCompleteCallback(Landroid/nfc/NfcAdapter$OnNdefPushCompleteCallback;Landroid/app/Activity;[Landroid/app/Activity;)V" since="14" />
+		<field name="ACTION_ADAPTER_STATE_CHANGED" since="18" />
 		<field name="ACTION_NDEF_DISCOVERED" since="10" />
 		<field name="ACTION_TAG_DISCOVERED" />
 		<field name="ACTION_TECH_DISCOVERED" since="10" />
+		<field name="EXTRA_ADAPTER_STATE" since="18" />
 		<field name="EXTRA_ID" />
 		<field name="EXTRA_NDEF_MESSAGES" />
 		<field name="EXTRA_TAG" since="10" />
+		<field name="STATE_OFF" since="18" />
+		<field name="STATE_ON" since="18" />
+		<field name="STATE_TURNING_OFF" since="18" />
+		<field name="STATE_TURNING_ON" since="18" />
 	</class>
 	<class name="android/nfc/NfcAdapter$CreateBeamUrisCallback" since="16">
 		<extends name="java/lang/Object" />
@@ -13767,6 +14327,15 @@
 		<extends name="android/opengl/EGLObjectHandle" />
 		<method name="&lt;init>()V" />
 	</class>
+	<class name="android/opengl/EGLExt" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>()V" />
+		<method name="eglPresentationTimeANDROID(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSurface;J)Z" />
+		<field name="EGL_CONTEXT_FLAGS_KHR" />
+		<field name="EGL_CONTEXT_MAJOR_VERSION_KHR" />
+		<field name="EGL_CONTEXT_MINOR_VERSION_KHR" />
+		<field name="EGL_OPENGL_ES3_BIT_KHR" />
+	</class>
 	<class name="android/opengl/EGLObjectHandle" since="17">
 		<extends name="java/lang/Object" />
 		<method name="&lt;init>(I)V" />
@@ -15115,6 +15684,476 @@
 		<field name="GL_VIEWPORT" />
 		<field name="GL_ZERO" />
 	</class>
+	<class name="android/opengl/GLES30" since="18">
+		<extends name="android/opengl/GLES20" />
+		<method name="&lt;init>()V" />
+		<method name="glBeginQuery(II)V" />
+		<method name="glBeginTransformFeedback(I)V" />
+		<method name="glBindBufferBase(III)V" />
+		<method name="glBindBufferRange(IIIII)V" />
+		<method name="glBindSampler(II)V" />
+		<method name="glBindTransformFeedback(II)V" />
+		<method name="glBindVertexArray(I)V" />
+		<method name="glBlitFramebuffer(IIIIIIIIII)V" />
+		<method name="glClearBufferfi(IIFI)V" />
+		<method name="glClearBufferfv(IILjava/nio/FloatBuffer;)V" />
+		<method name="glClearBufferfv(II[FI)V" />
+		<method name="glClearBufferiv(IILjava/nio/IntBuffer;)V" />
+		<method name="glClearBufferiv(II[II)V" />
+		<method name="glClearBufferuiv(IILjava/nio/IntBuffer;)V" />
+		<method name="glClearBufferuiv(II[II)V" />
+		<method name="glClientWaitSync(JIJ)I" />
+		<method name="glCompressedTexImage3D(IIIIIIIII)V" />
+		<method name="glCompressedTexImage3D(IIIIIIIILjava/nio/Buffer;)V" />
+		<method name="glCompressedTexSubImage3D(IIIIIIIIIII)V" />
+		<method name="glCompressedTexSubImage3D(IIIIIIIIIILjava/nio/Buffer;)V" />
+		<method name="glCopyBufferSubData(IIIII)V" />
+		<method name="glCopyTexSubImage3D(IIIIIIIII)V" />
+		<method name="glDeleteQueries(ILjava/nio/IntBuffer;)V" />
+		<method name="glDeleteQueries(I[II)V" />
+		<method name="glDeleteSamplers(ILjava/nio/IntBuffer;)V" />
+		<method name="glDeleteSamplers(I[II)V" />
+		<method name="glDeleteSync(J)V" />
+		<method name="glDeleteTransformFeedbacks(ILjava/nio/IntBuffer;)V" />
+		<method name="glDeleteTransformFeedbacks(I[II)V" />
+		<method name="glDeleteVertexArrays(ILjava/nio/IntBuffer;)V" />
+		<method name="glDeleteVertexArrays(I[II)V" />
+		<method name="glDrawArraysInstanced(IIII)V" />
+		<method name="glDrawBuffers(ILjava/nio/IntBuffer;)V" />
+		<method name="glDrawBuffers(I[II)V" />
+		<method name="glDrawElementsInstanced(IIIII)V" />
+		<method name="glDrawElementsInstanced(IIILjava/nio/Buffer;I)V" />
+		<method name="glDrawRangeElements(IIIIII)V" />
+		<method name="glDrawRangeElements(IIIIILjava/nio/Buffer;)V" />
+		<method name="glEndQuery(I)V" />
+		<method name="glEndTransformFeedback()V" />
+		<method name="glFenceSync(II)J" />
+		<method name="glFlushMappedBufferRange(III)V" />
+		<method name="glFramebufferTextureLayer(IIIII)V" />
+		<method name="glGenQueries(ILjava/nio/IntBuffer;)V" />
+		<method name="glGenQueries(I[II)V" />
+		<method name="glGenSamplers(ILjava/nio/IntBuffer;)V" />
+		<method name="glGenSamplers(I[II)V" />
+		<method name="glGenTransformFeedbacks(ILjava/nio/IntBuffer;)V" />
+		<method name="glGenTransformFeedbacks(I[II)V" />
+		<method name="glGenVertexArrays(ILjava/nio/IntBuffer;)V" />
+		<method name="glGenVertexArrays(I[II)V" />
+		<method name="glGetActiveUniformBlockName(II)Ljava/lang/String;" />
+		<method name="glGetActiveUniformBlockName(III[II[BI)V" />
+		<method name="glGetActiveUniformBlockName(IILjava/nio/Buffer;Ljava/nio/Buffer;)V" />
+		<method name="glGetActiveUniformBlockiv(IIILjava/nio/IntBuffer;)V" />
+		<method name="glGetActiveUniformBlockiv(III[II)V" />
+		<method name="glGetActiveUniformsiv(IILjava/nio/IntBuffer;ILjava/nio/IntBuffer;)V" />
+		<method name="glGetActiveUniformsiv(II[III[II)V" />
+		<method name="glGetBufferParameteri64v(IILjava/nio/LongBuffer;)V" />
+		<method name="glGetBufferParameteri64v(II[JI)V" />
+		<method name="glGetBufferPointerv(II)Ljava/nio/Buffer;" />
+		<method name="glGetFragDataLocation(ILjava/lang/String;)I" />
+		<method name="glGetInteger64i_v(IILjava/nio/LongBuffer;)V" />
+		<method name="glGetInteger64i_v(II[JI)V" />
+		<method name="glGetInteger64v(ILjava/nio/LongBuffer;)V" />
+		<method name="glGetInteger64v(I[JI)V" />
+		<method name="glGetIntegeri_v(IILjava/nio/IntBuffer;)V" />
+		<method name="glGetIntegeri_v(II[II)V" />
+		<method name="glGetInternalformativ(IIIILjava/nio/IntBuffer;)V" />
+		<method name="glGetInternalformativ(IIII[II)V" />
+		<method name="glGetProgramBinary(IILjava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/Buffer;)V" />
+		<method name="glGetProgramBinary(II[II[IILjava/nio/Buffer;)V" />
+		<method name="glGetQueryObjectuiv(IILjava/nio/IntBuffer;)V" />
+		<method name="glGetQueryObjectuiv(II[II)V" />
+		<method name="glGetQueryiv(IILjava/nio/IntBuffer;)V" />
+		<method name="glGetQueryiv(II[II)V" />
+		<method name="glGetSamplerParameterfv(IILjava/nio/FloatBuffer;)V" />
+		<method name="glGetSamplerParameterfv(II[FI)V" />
+		<method name="glGetSamplerParameteriv(IILjava/nio/IntBuffer;)V" />
+		<method name="glGetSamplerParameteriv(II[II)V" />
+		<method name="glGetStringi(II)Ljava/lang/String;" />
+		<method name="glGetSynciv(JIILjava/nio/IntBuffer;Ljava/nio/IntBuffer;)V" />
+		<method name="glGetSynciv(JII[II[II)V" />
+		<method name="glGetTransformFeedbackVarying(IIILjava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;B)V" />
+		<method name="glGetTransformFeedbackVarying(III[II[II[II[BI)V" />
+		<method name="glGetTransformFeedbackVarying(IILjava/nio/IntBuffer;Ljava/nio/IntBuffer;)Ljava/lang/String;" />
+		<method name="glGetTransformFeedbackVarying(II[II[II)Ljava/lang/String;" />
+		<method name="glGetUniformBlockIndex(ILjava/lang/String;)I" />
+		<method name="glGetUniformIndices(I[Ljava/lang/String;Ljava/nio/IntBuffer;)V" />
+		<method name="glGetUniformIndices(I[Ljava/lang/String;[II)V" />
+		<method name="glGetUniformuiv(IILjava/nio/IntBuffer;)V" />
+		<method name="glGetUniformuiv(II[II)V" />
+		<method name="glGetVertexAttribIiv(IILjava/nio/IntBuffer;)V" />
+		<method name="glGetVertexAttribIiv(II[II)V" />
+		<method name="glGetVertexAttribIuiv(IILjava/nio/IntBuffer;)V" />
+		<method name="glGetVertexAttribIuiv(II[II)V" />
+		<method name="glInvalidateFramebuffer(IILjava/nio/IntBuffer;)V" />
+		<method name="glInvalidateFramebuffer(II[II)V" />
+		<method name="glInvalidateSubFramebuffer(IILjava/nio/IntBuffer;IIII)V" />
+		<method name="glInvalidateSubFramebuffer(II[IIIIII)V" />
+		<method name="glIsQuery(I)Z" />
+		<method name="glIsSampler(I)Z" />
+		<method name="glIsSync(J)Z" />
+		<method name="glIsTransformFeedback(I)Z" />
+		<method name="glIsVertexArray(I)Z" />
+		<method name="glMapBufferRange(IIII)Ljava/nio/Buffer;" />
+		<method name="glPauseTransformFeedback()V" />
+		<method name="glProgramBinary(IILjava/nio/Buffer;I)V" />
+		<method name="glProgramParameteri(III)V" />
+		<method name="glReadBuffer(I)V" />
+		<method name="glRenderbufferStorageMultisample(IIIII)V" />
+		<method name="glResumeTransformFeedback()V" />
+		<method name="glSamplerParameterf(IIF)V" />
+		<method name="glSamplerParameterfv(IILjava/nio/FloatBuffer;)V" />
+		<method name="glSamplerParameterfv(II[FI)V" />
+		<method name="glSamplerParameteri(III)V" />
+		<method name="glSamplerParameteriv(IILjava/nio/IntBuffer;)V" />
+		<method name="glSamplerParameteriv(II[II)V" />
+		<method name="glTexImage3D(IIIIIIIIII)V" />
+		<method name="glTexImage3D(IIIIIIIIILjava/nio/Buffer;)V" />
+		<method name="glTexStorage2D(IIIII)V" />
+		<method name="glTexStorage3D(IIIIII)V" />
+		<method name="glTexSubImage3D(IIIIIIIIIII)V" />
+		<method name="glTexSubImage3D(IIIIIIIIIILjava/nio/Buffer;)V" />
+		<method name="glTransformFeedbackVaryings(I[Ljava/lang/String;I)V" />
+		<method name="glUniform1ui(II)V" />
+		<method name="glUniform1uiv(IILjava/nio/IntBuffer;)V" />
+		<method name="glUniform1uiv(II[II)V" />
+		<method name="glUniform2ui(III)V" />
+		<method name="glUniform2uiv(IILjava/nio/IntBuffer;)V" />
+		<method name="glUniform2uiv(II[II)V" />
+		<method name="glUniform3ui(IIII)V" />
+		<method name="glUniform3uiv(IILjava/nio/IntBuffer;)V" />
+		<method name="glUniform3uiv(II[II)V" />
+		<method name="glUniform4ui(IIIII)V" />
+		<method name="glUniform4uiv(IILjava/nio/IntBuffer;)V" />
+		<method name="glUniform4uiv(II[II)V" />
+		<method name="glUniformBlockBinding(III)V" />
+		<method name="glUniformMatrix2x3fv(IIZLjava/nio/FloatBuffer;)V" />
+		<method name="glUniformMatrix2x3fv(IIZ[FI)V" />
+		<method name="glUniformMatrix2x4fv(IIZLjava/nio/FloatBuffer;)V" />
+		<method name="glUniformMatrix2x4fv(IIZ[FI)V" />
+		<method name="glUniformMatrix3x2fv(IIZLjava/nio/FloatBuffer;)V" />
+		<method name="glUniformMatrix3x2fv(IIZ[FI)V" />
+		<method name="glUniformMatrix3x4fv(IIZLjava/nio/FloatBuffer;)V" />
+		<method name="glUniformMatrix3x4fv(IIZ[FI)V" />
+		<method name="glUniformMatrix4x2fv(IIZLjava/nio/FloatBuffer;)V" />
+		<method name="glUniformMatrix4x2fv(IIZ[FI)V" />
+		<method name="glUniformMatrix4x3fv(IIZLjava/nio/FloatBuffer;)V" />
+		<method name="glUniformMatrix4x3fv(IIZ[FI)V" />
+		<method name="glUnmapBuffer(I)Z" />
+		<method name="glVertexAttribDivisor(II)V" />
+		<method name="glVertexAttribI4i(IIIII)V" />
+		<method name="glVertexAttribI4iv(ILjava/nio/IntBuffer;)V" />
+		<method name="glVertexAttribI4iv(I[II)V" />
+		<method name="glVertexAttribI4ui(IIIII)V" />
+		<method name="glVertexAttribI4uiv(ILjava/nio/IntBuffer;)V" />
+		<method name="glVertexAttribI4uiv(I[II)V" />
+		<method name="glVertexAttribIPointer(IIIII)V" />
+		<method name="glVertexAttribIPointer(IIIILjava/nio/Buffer;)V" />
+		<method name="glWaitSync(JIJ)V" />
+		<field name="GL_ACTIVE_UNIFORM_BLOCKS" />
+		<field name="GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH" />
+		<field name="GL_ALREADY_SIGNALED" />
+		<field name="GL_ANY_SAMPLES_PASSED" />
+		<field name="GL_ANY_SAMPLES_PASSED_CONSERVATIVE" />
+		<field name="GL_BLUE" />
+		<field name="GL_BUFFER_ACCESS_FLAGS" />
+		<field name="GL_BUFFER_MAPPED" />
+		<field name="GL_BUFFER_MAP_LENGTH" />
+		<field name="GL_BUFFER_MAP_OFFSET" />
+		<field name="GL_BUFFER_MAP_POINTER" />
+		<field name="GL_COLOR" />
+		<field name="GL_COLOR_ATTACHMENT1" />
+		<field name="GL_COLOR_ATTACHMENT10" />
+		<field name="GL_COLOR_ATTACHMENT11" />
+		<field name="GL_COLOR_ATTACHMENT12" />
+		<field name="GL_COLOR_ATTACHMENT13" />
+		<field name="GL_COLOR_ATTACHMENT14" />
+		<field name="GL_COLOR_ATTACHMENT15" />
+		<field name="GL_COLOR_ATTACHMENT2" />
+		<field name="GL_COLOR_ATTACHMENT3" />
+		<field name="GL_COLOR_ATTACHMENT4" />
+		<field name="GL_COLOR_ATTACHMENT5" />
+		<field name="GL_COLOR_ATTACHMENT6" />
+		<field name="GL_COLOR_ATTACHMENT7" />
+		<field name="GL_COLOR_ATTACHMENT8" />
+		<field name="GL_COLOR_ATTACHMENT9" />
+		<field name="GL_COMPARE_REF_TO_TEXTURE" />
+		<field name="GL_COMPRESSED_R11_EAC" />
+		<field name="GL_COMPRESSED_RG11_EAC" />
+		<field name="GL_COMPRESSED_RGB8_ETC2" />
+		<field name="GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2" />
+		<field name="GL_COMPRESSED_RGBA8_ETC2_EAC" />
+		<field name="GL_COMPRESSED_SIGNED_R11_EAC" />
+		<field name="GL_COMPRESSED_SIGNED_RG11_EAC" />
+		<field name="GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC" />
+		<field name="GL_COMPRESSED_SRGB8_ETC2" />
+		<field name="GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2" />
+		<field name="GL_CONDITION_SATISFIED" />
+		<field name="GL_COPY_READ_BUFFER" />
+		<field name="GL_COPY_READ_BUFFER_BINDING" />
+		<field name="GL_COPY_WRITE_BUFFER" />
+		<field name="GL_COPY_WRITE_BUFFER_BINDING" />
+		<field name="GL_CURRENT_QUERY" />
+		<field name="GL_DEPTH" />
+		<field name="GL_DEPTH24_STENCIL8" />
+		<field name="GL_DEPTH32F_STENCIL8" />
+		<field name="GL_DEPTH_COMPONENT24" />
+		<field name="GL_DEPTH_COMPONENT32F" />
+		<field name="GL_DEPTH_STENCIL" />
+		<field name="GL_DEPTH_STENCIL_ATTACHMENT" />
+		<field name="GL_DRAW_BUFFER0" />
+		<field name="GL_DRAW_BUFFER1" />
+		<field name="GL_DRAW_BUFFER10" />
+		<field name="GL_DRAW_BUFFER11" />
+		<field name="GL_DRAW_BUFFER12" />
+		<field name="GL_DRAW_BUFFER13" />
+		<field name="GL_DRAW_BUFFER14" />
+		<field name="GL_DRAW_BUFFER15" />
+		<field name="GL_DRAW_BUFFER2" />
+		<field name="GL_DRAW_BUFFER3" />
+		<field name="GL_DRAW_BUFFER4" />
+		<field name="GL_DRAW_BUFFER5" />
+		<field name="GL_DRAW_BUFFER6" />
+		<field name="GL_DRAW_BUFFER7" />
+		<field name="GL_DRAW_BUFFER8" />
+		<field name="GL_DRAW_BUFFER9" />
+		<field name="GL_DRAW_FRAMEBUFFER" />
+		<field name="GL_DRAW_FRAMEBUFFER_BINDING" />
+		<field name="GL_DYNAMIC_COPY" />
+		<field name="GL_DYNAMIC_READ" />
+		<field name="GL_FLOAT_32_UNSIGNED_INT_24_8_REV" />
+		<field name="GL_FLOAT_MAT2x3" />
+		<field name="GL_FLOAT_MAT2x4" />
+		<field name="GL_FLOAT_MAT3x2" />
+		<field name="GL_FLOAT_MAT3x4" />
+		<field name="GL_FLOAT_MAT4x2" />
+		<field name="GL_FLOAT_MAT4x3" />
+		<field name="GL_FRAGMENT_SHADER_DERIVATIVE_HINT" />
+		<field name="GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE" />
+		<field name="GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE" />
+		<field name="GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING" />
+		<field name="GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE" />
+		<field name="GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE" />
+		<field name="GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE" />
+		<field name="GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE" />
+		<field name="GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE" />
+		<field name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER" />
+		<field name="GL_FRAMEBUFFER_DEFAULT" />
+		<field name="GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE" />
+		<field name="GL_FRAMEBUFFER_UNDEFINED" />
+		<field name="GL_GREEN" />
+		<field name="GL_HALF_FLOAT" />
+		<field name="GL_INTERLEAVED_ATTRIBS" />
+		<field name="GL_INT_2_10_10_10_REV" />
+		<field name="GL_INT_SAMPLER_2D" />
+		<field name="GL_INT_SAMPLER_2D_ARRAY" />
+		<field name="GL_INT_SAMPLER_3D" />
+		<field name="GL_INT_SAMPLER_CUBE" />
+		<field name="GL_INVALID_INDEX" />
+		<field name="GL_MAJOR_VERSION" />
+		<field name="GL_MAP_FLUSH_EXPLICIT_BIT" />
+		<field name="GL_MAP_INVALIDATE_BUFFER_BIT" />
+		<field name="GL_MAP_INVALIDATE_RANGE_BIT" />
+		<field name="GL_MAP_READ_BIT" />
+		<field name="GL_MAP_UNSYNCHRONIZED_BIT" />
+		<field name="GL_MAP_WRITE_BIT" />
+		<field name="GL_MAX" />
+		<field name="GL_MAX_3D_TEXTURE_SIZE" />
+		<field name="GL_MAX_ARRAY_TEXTURE_LAYERS" />
+		<field name="GL_MAX_COLOR_ATTACHMENTS" />
+		<field name="GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS" />
+		<field name="GL_MAX_COMBINED_UNIFORM_BLOCKS" />
+		<field name="GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS" />
+		<field name="GL_MAX_DRAW_BUFFERS" />
+		<field name="GL_MAX_ELEMENTS_INDICES" />
+		<field name="GL_MAX_ELEMENTS_VERTICES" />
+		<field name="GL_MAX_ELEMENT_INDEX" />
+		<field name="GL_MAX_FRAGMENT_INPUT_COMPONENTS" />
+		<field name="GL_MAX_FRAGMENT_UNIFORM_BLOCKS" />
+		<field name="GL_MAX_FRAGMENT_UNIFORM_COMPONENTS" />
+		<field name="GL_MAX_PROGRAM_TEXEL_OFFSET" />
+		<field name="GL_MAX_SAMPLES" />
+		<field name="GL_MAX_SERVER_WAIT_TIMEOUT" />
+		<field name="GL_MAX_TEXTURE_LOD_BIAS" />
+		<field name="GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS" />
+		<field name="GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS" />
+		<field name="GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS" />
+		<field name="GL_MAX_UNIFORM_BLOCK_SIZE" />
+		<field name="GL_MAX_UNIFORM_BUFFER_BINDINGS" />
+		<field name="GL_MAX_VARYING_COMPONENTS" />
+		<field name="GL_MAX_VERTEX_OUTPUT_COMPONENTS" />
+		<field name="GL_MAX_VERTEX_UNIFORM_BLOCKS" />
+		<field name="GL_MAX_VERTEX_UNIFORM_COMPONENTS" />
+		<field name="GL_MIN" />
+		<field name="GL_MINOR_VERSION" />
+		<field name="GL_MIN_PROGRAM_TEXEL_OFFSET" />
+		<field name="GL_NUM_EXTENSIONS" />
+		<field name="GL_NUM_PROGRAM_BINARY_FORMATS" />
+		<field name="GL_NUM_SAMPLE_COUNTS" />
+		<field name="GL_OBJECT_TYPE" />
+		<field name="GL_PACK_ROW_LENGTH" />
+		<field name="GL_PACK_SKIP_PIXELS" />
+		<field name="GL_PACK_SKIP_ROWS" />
+		<field name="GL_PIXEL_PACK_BUFFER" />
+		<field name="GL_PIXEL_PACK_BUFFER_BINDING" />
+		<field name="GL_PIXEL_UNPACK_BUFFER" />
+		<field name="GL_PIXEL_UNPACK_BUFFER_BINDING" />
+		<field name="GL_PRIMITIVE_RESTART_FIXED_INDEX" />
+		<field name="GL_PROGRAM_BINARY_FORMATS" />
+		<field name="GL_PROGRAM_BINARY_LENGTH" />
+		<field name="GL_PROGRAM_BINARY_RETRIEVABLE_HINT" />
+		<field name="GL_QUERY_RESULT" />
+		<field name="GL_QUERY_RESULT_AVAILABLE" />
+		<field name="GL_R11F_G11F_B10F" />
+		<field name="GL_R16F" />
+		<field name="GL_R16I" />
+		<field name="GL_R16UI" />
+		<field name="GL_R32F" />
+		<field name="GL_R32I" />
+		<field name="GL_R32UI" />
+		<field name="GL_R8" />
+		<field name="GL_R8I" />
+		<field name="GL_R8UI" />
+		<field name="GL_R8_SNORM" />
+		<field name="GL_RASTERIZER_DISCARD" />
+		<field name="GL_READ_BUFFER" />
+		<field name="GL_READ_FRAMEBUFFER" />
+		<field name="GL_READ_FRAMEBUFFER_BINDING" />
+		<field name="GL_RED" />
+		<field name="GL_RED_INTEGER" />
+		<field name="GL_RENDERBUFFER_SAMPLES" />
+		<field name="GL_RG" />
+		<field name="GL_RG16F" />
+		<field name="GL_RG16I" />
+		<field name="GL_RG16UI" />
+		<field name="GL_RG32F" />
+		<field name="GL_RG32I" />
+		<field name="GL_RG32UI" />
+		<field name="GL_RG8" />
+		<field name="GL_RG8I" />
+		<field name="GL_RG8UI" />
+		<field name="GL_RG8_SNORM" />
+		<field name="GL_RGB10_A2" />
+		<field name="GL_RGB10_A2UI" />
+		<field name="GL_RGB16F" />
+		<field name="GL_RGB16I" />
+		<field name="GL_RGB16UI" />
+		<field name="GL_RGB32F" />
+		<field name="GL_RGB32I" />
+		<field name="GL_RGB32UI" />
+		<field name="GL_RGB8" />
+		<field name="GL_RGB8I" />
+		<field name="GL_RGB8UI" />
+		<field name="GL_RGB8_SNORM" />
+		<field name="GL_RGB9_E5" />
+		<field name="GL_RGBA16F" />
+		<field name="GL_RGBA16I" />
+		<field name="GL_RGBA16UI" />
+		<field name="GL_RGBA32F" />
+		<field name="GL_RGBA32I" />
+		<field name="GL_RGBA32UI" />
+		<field name="GL_RGBA8" />
+		<field name="GL_RGBA8I" />
+		<field name="GL_RGBA8UI" />
+		<field name="GL_RGBA8_SNORM" />
+		<field name="GL_RGBA_INTEGER" />
+		<field name="GL_RGB_INTEGER" />
+		<field name="GL_RG_INTEGER" />
+		<field name="GL_SAMPLER_2D_ARRAY" />
+		<field name="GL_SAMPLER_2D_ARRAY_SHADOW" />
+		<field name="GL_SAMPLER_2D_SHADOW" />
+		<field name="GL_SAMPLER_3D" />
+		<field name="GL_SAMPLER_BINDING" />
+		<field name="GL_SAMPLER_CUBE_SHADOW" />
+		<field name="GL_SEPARATE_ATTRIBS" />
+		<field name="GL_SIGNALED" />
+		<field name="GL_SIGNED_NORMALIZED" />
+		<field name="GL_SRGB" />
+		<field name="GL_SRGB8" />
+		<field name="GL_SRGB8_ALPHA8" />
+		<field name="GL_STATIC_COPY" />
+		<field name="GL_STATIC_READ" />
+		<field name="GL_STENCIL" />
+		<field name="GL_STREAM_COPY" />
+		<field name="GL_STREAM_READ" />
+		<field name="GL_SYNC_CONDITION" />
+		<field name="GL_SYNC_FENCE" />
+		<field name="GL_SYNC_FLAGS" />
+		<field name="GL_SYNC_FLUSH_COMMANDS_BIT" />
+		<field name="GL_SYNC_GPU_COMMANDS_COMPLETE" />
+		<field name="GL_SYNC_STATUS" />
+		<field name="GL_TEXTURE_2D_ARRAY" />
+		<field name="GL_TEXTURE_3D" />
+		<field name="GL_TEXTURE_BASE_LEVEL" />
+		<field name="GL_TEXTURE_BINDING_2D_ARRAY" />
+		<field name="GL_TEXTURE_BINDING_3D" />
+		<field name="GL_TEXTURE_COMPARE_FUNC" />
+		<field name="GL_TEXTURE_COMPARE_MODE" />
+		<field name="GL_TEXTURE_IMMUTABLE_FORMAT" />
+		<field name="GL_TEXTURE_IMMUTABLE_LEVELS" />
+		<field name="GL_TEXTURE_MAX_LEVEL" />
+		<field name="GL_TEXTURE_MAX_LOD" />
+		<field name="GL_TEXTURE_MIN_LOD" />
+		<field name="GL_TEXTURE_SWIZZLE_A" />
+		<field name="GL_TEXTURE_SWIZZLE_B" />
+		<field name="GL_TEXTURE_SWIZZLE_G" />
+		<field name="GL_TEXTURE_SWIZZLE_R" />
+		<field name="GL_TEXTURE_WRAP_R" />
+		<field name="GL_TIMEOUT_EXPIRED" />
+		<field name="GL_TIMEOUT_IGNORED" />
+		<field name="GL_TRANSFORM_FEEDBACK" />
+		<field name="GL_TRANSFORM_FEEDBACK_ACTIVE" />
+		<field name="GL_TRANSFORM_FEEDBACK_BINDING" />
+		<field name="GL_TRANSFORM_FEEDBACK_BUFFER" />
+		<field name="GL_TRANSFORM_FEEDBACK_BUFFER_BINDING" />
+		<field name="GL_TRANSFORM_FEEDBACK_BUFFER_MODE" />
+		<field name="GL_TRANSFORM_FEEDBACK_BUFFER_SIZE" />
+		<field name="GL_TRANSFORM_FEEDBACK_BUFFER_START" />
+		<field name="GL_TRANSFORM_FEEDBACK_PAUSED" />
+		<field name="GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN" />
+		<field name="GL_TRANSFORM_FEEDBACK_VARYINGS" />
+		<field name="GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH" />
+		<field name="GL_UNIFORM_ARRAY_STRIDE" />
+		<field name="GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS" />
+		<field name="GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES" />
+		<field name="GL_UNIFORM_BLOCK_BINDING" />
+		<field name="GL_UNIFORM_BLOCK_DATA_SIZE" />
+		<field name="GL_UNIFORM_BLOCK_INDEX" />
+		<field name="GL_UNIFORM_BLOCK_NAME_LENGTH" />
+		<field name="GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER" />
+		<field name="GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER" />
+		<field name="GL_UNIFORM_BUFFER" />
+		<field name="GL_UNIFORM_BUFFER_BINDING" />
+		<field name="GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT" />
+		<field name="GL_UNIFORM_BUFFER_SIZE" />
+		<field name="GL_UNIFORM_BUFFER_START" />
+		<field name="GL_UNIFORM_IS_ROW_MAJOR" />
+		<field name="GL_UNIFORM_MATRIX_STRIDE" />
+		<field name="GL_UNIFORM_NAME_LENGTH" />
+		<field name="GL_UNIFORM_OFFSET" />
+		<field name="GL_UNIFORM_SIZE" />
+		<field name="GL_UNIFORM_TYPE" />
+		<field name="GL_UNPACK_IMAGE_HEIGHT" />
+		<field name="GL_UNPACK_ROW_LENGTH" />
+		<field name="GL_UNPACK_SKIP_IMAGES" />
+		<field name="GL_UNPACK_SKIP_PIXELS" />
+		<field name="GL_UNPACK_SKIP_ROWS" />
+		<field name="GL_UNSIGNALED" />
+		<field name="GL_UNSIGNED_INT_10F_11F_11F_REV" />
+		<field name="GL_UNSIGNED_INT_24_8" />
+		<field name="GL_UNSIGNED_INT_2_10_10_10_REV" />
+		<field name="GL_UNSIGNED_INT_5_9_9_9_REV" />
+		<field name="GL_UNSIGNED_INT_SAMPLER_2D" />
+		<field name="GL_UNSIGNED_INT_SAMPLER_2D_ARRAY" />
+		<field name="GL_UNSIGNED_INT_SAMPLER_3D" />
+		<field name="GL_UNSIGNED_INT_SAMPLER_CUBE" />
+		<field name="GL_UNSIGNED_INT_VEC2" />
+		<field name="GL_UNSIGNED_INT_VEC3" />
+		<field name="GL_UNSIGNED_INT_VEC4" />
+		<field name="GL_UNSIGNED_NORMALIZED" />
+		<field name="GL_VERTEX_ARRAY_BINDING" />
+		<field name="GL_VERTEX_ATTRIB_ARRAY_DIVISOR" />
+		<field name="GL_VERTEX_ATTRIB_ARRAY_INTEGER" />
+		<field name="GL_WAIT_FAILED" />
+	</class>
 	<class name="android/opengl/GLException" since="1">
 		<extends name="java/lang/RuntimeException" />
 		<method name="&lt;init>(I)V" />
@@ -15357,6 +16396,7 @@
 		<field name="ICE_CREAM_SANDWICH_MR1" since="15" />
 		<field name="JELLY_BEAN" since="16" />
 		<field name="JELLY_BEAN_MR1" since="17" />
+		<field name="JELLY_BEAN_MR2" since="18" />
 	</class>
 	<class name="android/os/Bundle" since="1">
 		<extends name="java/lang/Object" />
@@ -15369,6 +16409,7 @@
 		<method name="clear()V" />
 		<method name="containsKey(Ljava/lang/String;)Z" />
 		<method name="get(Ljava/lang/String;)Ljava/lang/Object;" />
+		<method name="getBinder(Ljava/lang/String;)Landroid/os/IBinder;" since="18" />
 		<method name="getBoolean(Ljava/lang/String;)Z" />
 		<method name="getBoolean(Ljava/lang/String;Z)Z" />
 		<method name="getBooleanArray(Ljava/lang/String;)[Z" />
@@ -15413,6 +16454,7 @@
 		<method name="isEmpty()Z" />
 		<method name="keySet()Ljava/util/Set;" />
 		<method name="putAll(Landroid/os/Bundle;)V" />
+		<method name="putBinder(Ljava/lang/String;Landroid/os/IBinder;)V" since="18" />
 		<method name="putBoolean(Ljava/lang/String;Z)V" />
 		<method name="putBooleanArray(Ljava/lang/String;[Z)V" />
 		<method name="putBundle(Ljava/lang/String;Landroid/os/Bundle;)V" />
@@ -15716,6 +16758,7 @@
 		<method name="getThreadId()I" />
 		<method name="onLooperPrepared()V" />
 		<method name="quit()Z" since="5" />
+		<method name="quitSafely()Z" since="18" />
 	</class>
 	<class name="android/os/IBinder" since="1">
 		<extends name="java/lang/Object" />
@@ -15757,6 +16800,7 @@
 		<method name="prepare()V" />
 		<method name="prepareMainLooper()V" />
 		<method name="quit()V" />
+		<method name="quitSafely()V" since="18" />
 		<method name="setMessageLogging(Landroid/util/Printer;)V" />
 	</class>
 	<class name="android/os/MemoryFile" since="1">
@@ -16119,9 +17163,16 @@
 		<extends name="java/lang/Object" />
 		<method name="&lt;init>(Ljava/lang/String;)V" />
 		<method name="getAvailableBlocks()I" />
+		<method name="getAvailableBlocksLong()J" since="18" />
+		<method name="getAvailableBytes()J" since="18" />
 		<method name="getBlockCount()I" />
+		<method name="getBlockCountLong()J" since="18" />
 		<method name="getBlockSize()I" />
+		<method name="getBlockSizeLong()J" since="18" />
 		<method name="getFreeBlocks()I" />
+		<method name="getFreeBlocksLong()J" since="18" />
+		<method name="getFreeBytes()J" since="18" />
+		<method name="getTotalBytes()J" since="18" />
 		<method name="restat(Ljava/lang/String;)V" />
 	</class>
 	<class name="android/os/StrictMode" since="9">
@@ -16175,6 +17226,7 @@
 		<method name="build()Landroid/os/StrictMode$VmPolicy;" />
 		<method name="detectActivityLeaks()Landroid/os/StrictMode$VmPolicy$Builder;" since="11" />
 		<method name="detectAll()Landroid/os/StrictMode$VmPolicy$Builder;" />
+		<method name="detectFileUriExposure()Landroid/os/StrictMode$VmPolicy$Builder;" since="18" />
 		<method name="detectLeakedClosableObjects()Landroid/os/StrictMode$VmPolicy$Builder;" since="11" />
 		<method name="detectLeakedRegistrationObjects()Landroid/os/StrictMode$VmPolicy$Builder;" since="16" />
 		<method name="detectLeakedSqlLiteObjects()Landroid/os/StrictMode$VmPolicy$Builder;" />
@@ -16205,6 +17257,12 @@
 		<method name="release(Landroid/os/IBinder;)V" />
 		<method name="released()V" />
 	</class>
+	<class name="android/os/Trace" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>()V" />
+		<method name="beginSection(Ljava/lang/String;)V" />
+		<method name="endSection()V" />
+	</class>
 	<class name="android/os/TransactionTooLargeException" since="15">
 		<extends name="android/os/RemoteException" />
 		<method name="&lt;init>()V" />
@@ -16220,13 +17278,29 @@
 	<class name="android/os/UserManager" since="17">
 		<extends name="java/lang/Object" />
 		<method name="&lt;init>()V" />
+		<method name="getApplicationRestrictions(Ljava/lang/String;)Landroid/os/Bundle;" since="18" />
 		<method name="getSerialNumberForUser(Landroid/os/UserHandle;)J" />
 		<method name="getUserCount()I" />
 		<method name="getUserForSerialNumber(J)Landroid/os/UserHandle;" />
 		<method name="getUserName()Ljava/lang/String;" />
+		<method name="getUserRestrictions()Landroid/os/Bundle;" since="18" />
+		<method name="getUserRestrictions(Landroid/os/UserHandle;)Landroid/os/Bundle;" since="18" />
 		<method name="isUserAGoat()Z" />
 		<method name="isUserRunning(Landroid/os/UserHandle;)Z" />
 		<method name="isUserRunningOrStopping(Landroid/os/UserHandle;)Z" />
+		<method name="setUserRestriction(Ljava/lang/String;Z)V" since="18" />
+		<method name="setUserRestrictions(Landroid/os/Bundle;)V" since="18" />
+		<method name="setUserRestrictions(Landroid/os/Bundle;Landroid/os/UserHandle;)V" since="18" />
+		<field name="DISALLOW_CONFIG_BLUETOOTH" since="18" />
+		<field name="DISALLOW_CONFIG_CREDENTIALS" since="18" />
+		<field name="DISALLOW_CONFIG_WIFI" since="18" />
+		<field name="DISALLOW_INSTALL_APPS" since="18" />
+		<field name="DISALLOW_INSTALL_UNKNOWN_SOURCES" since="18" />
+		<field name="DISALLOW_MODIFY_ACCOUNTS" since="18" />
+		<field name="DISALLOW_REMOVE_USER" since="18" />
+		<field name="DISALLOW_SHARE_LOCATION" since="18" />
+		<field name="DISALLOW_UNINSTALL_APPS" since="18" />
+		<field name="DISALLOW_USB_FILE_TRANSFER" since="18" />
 	</class>
 	<class name="android/os/Vibrator" since="1">
 		<extends name="java/lang/Object" />
@@ -17034,6 +18108,7 @@
 		<field name="CAN_PARTIALLY_UPDATE" />
 		<field name="DELETED" />
 		<field name="DIRTY" />
+		<field name="MUTATORS" since="18" />
 		<field name="_SYNC_ID" />
 	</class>
 	<class name="android/provider/CalendarContract$SyncState" since="14">
@@ -17458,6 +18533,15 @@
 		<field name="LABEL" />
 		<field name="TYPE" />
 	</class>
+	<class name="android/provider/ContactsContract$CommonDataKinds$Contactables" since="18">
+		<extends name="java/lang/Object" />
+		<implements name="android/provider/ContactsContract$CommonDataKinds$CommonColumns" />
+		<implements name="android/provider/ContactsContract$DataColumnsWithJoins" />
+		<method name="&lt;init>()V" />
+		<field name="CONTENT_FILTER_URI" />
+		<field name="CONTENT_URI" />
+		<field name="VISIBLE_CONTACTS_ONLY" />
+	</class>
 	<class name="android/provider/ContactsContract$CommonDataKinds$Email" since="5">
 		<extends name="java/lang/Object" />
 		<implements name="android/provider/ContactsContract$CommonDataKinds$CommonColumns" />
@@ -17808,6 +18892,7 @@
 	</class>
 	<class name="android/provider/ContactsContract$ContactsColumns" since="5">
 		<extends name="java/lang/Object" />
+		<field name="CONTACT_LAST_UPDATED_TIMESTAMP" since="18" />
 		<field name="DISPLAY_NAME" />
 		<field name="HAS_PHONE_NUMBER" />
 		<field name="IN_VISIBLE_GROUP" />
@@ -17825,6 +18910,7 @@
 		<method name="getContactLookupUri(Landroid/content/ContentResolver;Landroid/net/Uri;)Landroid/net/Uri;" />
 		<field name="CONTENT_TYPE" />
 		<field name="CONTENT_URI" />
+		<field name="VISIBLE_CONTACTS_ONLY" since="18" />
 	</class>
 	<class name="android/provider/ContactsContract$DataColumns" since="5">
 		<extends name="java/lang/Object" />
@@ -17862,6 +18948,7 @@
 		<implements name="android/provider/ContactsContract$ContactStatusColumns" />
 		<implements name="android/provider/ContactsContract$ContactsColumns" />
 		<implements name="android/provider/ContactsContract$DataColumns" />
+		<implements name="android/provider/ContactsContract$DataUsageStatColumns" since="18" />
 		<implements name="android/provider/ContactsContract$RawContactsColumns" />
 		<implements name="android/provider/ContactsContract$StatusColumns" />
 	</class>
@@ -17875,6 +18962,23 @@
 		<field name="USAGE_TYPE_LONG_TEXT" />
 		<field name="USAGE_TYPE_SHORT_TEXT" />
 	</class>
+	<class name="android/provider/ContactsContract$DataUsageStatColumns" since="18">
+		<extends name="java/lang/Object" />
+		<field name="LAST_TIME_USED" />
+		<field name="TIMES_USED" />
+	</class>
+	<class name="android/provider/ContactsContract$DeletedContacts" since="18">
+		<extends name="java/lang/Object" />
+		<implements name="android/provider/ContactsContract$DeletedContactsColumns" />
+		<method name="&lt;init>()V" />
+		<field name="CONTENT_URI" />
+		<field name="DAYS_KEPT_MILLISECONDS" />
+	</class>
+	<class name="android/provider/ContactsContract$DeletedContactsColumns" since="18">
+		<extends name="java/lang/Object" />
+		<field name="CONTACT_DELETED_TIMESTAMP" />
+		<field name="CONTACT_ID" />
+	</class>
 	<class name="android/provider/ContactsContract$Directory" since="11">
 		<extends name="java/lang/Object" />
 		<implements name="android/provider/BaseColumns" />
@@ -17962,6 +19066,7 @@
 		<extends name="java/lang/Object" />
 		<method name="&lt;init>()V" />
 		<field name="ATTACH_IMAGE" />
+		<field name="CONTACTS_DATABASE_CREATED" since="18" />
 		<field name="EXTRA_CREATE_DESCRIPTION" />
 		<field name="EXTRA_FORCE_CREATE" />
 		<field name="INVITE_CONTACT" since="14" />
@@ -18646,6 +19751,7 @@
 		<field name="ACTION_DATE_SETTINGS" />
 		<field name="ACTION_DEVICE_INFO_SETTINGS" since="8" />
 		<field name="ACTION_DISPLAY_SETTINGS" />
+		<field name="ACTION_DREAM_SETTINGS" since="18" />
 		<field name="ACTION_INPUT_METHOD_SETTINGS" since="3" />
 		<field name="ACTION_INPUT_METHOD_SUBTYPE_SETTINGS" since="11" />
 		<field name="ACTION_INTERNAL_STORAGE_SETTINGS" since="3" />
@@ -18669,6 +19775,7 @@
 		<field name="ACTION_WIFI_SETTINGS" />
 		<field name="ACTION_WIRELESS_SETTINGS" />
 		<field name="AUTHORITY" />
+		<field name="EXTRA_ACCOUNT_TYPES" since="18" />
 		<field name="EXTRA_AUTHORITIES" since="8" />
 		<field name="EXTRA_INPUT_METHOD_ID" since="11" />
 	</class>
@@ -19069,6 +20176,7 @@
 		<method name="copy2DRangeFrom(IIII[S)V" />
 		<method name="copy2DRangeFrom(IILandroid/graphics/Bitmap;)V" />
 		<method name="copyFrom(Landroid/graphics/Bitmap;)V" />
+		<method name="copyFrom(Landroid/renderscript/Allocation;)V" since="18" />
 		<method name="copyFrom([B)V" />
 		<method name="copyFrom([F)V" />
 		<method name="copyFrom([I)V" />
@@ -19117,6 +20225,7 @@
 		<field name="USAGE_IO_INPUT" since="16" />
 		<field name="USAGE_IO_OUTPUT" since="16" />
 		<field name="USAGE_SCRIPT" />
+		<field name="USAGE_SHARED" since="18" />
 	</class>
 	<class name="android/renderscript/Allocation$MipmapControl" since="11">
 		<extends name="java/lang/Enum" />
@@ -19297,6 +20406,7 @@
 		<field name="PIXEL_LA" />
 		<field name="PIXEL_RGB" />
 		<field name="PIXEL_RGBA" />
+		<field name="PIXEL_YUV" since="18" />
 		<field name="USER" />
 	</class>
 	<class name="android/renderscript/Element$DataType" since="11">
@@ -19336,6 +20446,7 @@
 	<class name="android/renderscript/FieldPacker" since="11">
 		<extends name="java/lang/Object" />
 		<method name="&lt;init>(I)V" />
+		<method name="&lt;init>([B)V" since="18" />
 		<method name="addBoolean(Z)V" />
 		<method name="addF32(F)V" />
 		<method name="addF32(Landroid/renderscript/Float2;)V" />
@@ -19386,6 +20497,35 @@
 		<method name="reset()V" />
 		<method name="reset(I)V" />
 		<method name="skip(I)V" />
+		<method name="subBoolean()Z" since="18" />
+		<method name="subByte2()Landroid/renderscript/Byte2;" since="18" />
+		<method name="subByte3()Landroid/renderscript/Byte3;" since="18" />
+		<method name="subByte4()Landroid/renderscript/Byte4;" since="18" />
+		<method name="subDouble2()Landroid/renderscript/Double2;" since="18" />
+		<method name="subDouble3()Landroid/renderscript/Double3;" since="18" />
+		<method name="subDouble4()Landroid/renderscript/Double4;" since="18" />
+		<method name="subF32()F" since="18" />
+		<method name="subF64()D" since="18" />
+		<method name="subFloat2()Landroid/renderscript/Float2;" since="18" />
+		<method name="subFloat3()Landroid/renderscript/Float3;" since="18" />
+		<method name="subFloat4()Landroid/renderscript/Float4;" since="18" />
+		<method name="subI16()S" since="18" />
+		<method name="subI32()I" since="18" />
+		<method name="subI64()J" since="18" />
+		<method name="subI8()B" since="18" />
+		<method name="subInt2()Landroid/renderscript/Int2;" since="18" />
+		<method name="subInt3()Landroid/renderscript/Int3;" since="18" />
+		<method name="subInt4()Landroid/renderscript/Int4;" since="18" />
+		<method name="subLong2()Landroid/renderscript/Long2;" since="18" />
+		<method name="subLong3()Landroid/renderscript/Long3;" since="18" />
+		<method name="subLong4()Landroid/renderscript/Long4;" since="18" />
+		<method name="subMatrix2f()Landroid/renderscript/Matrix2f;" since="18" />
+		<method name="subMatrix3f()Landroid/renderscript/Matrix3f;" since="18" />
+		<method name="subMatrix4f()Landroid/renderscript/Matrix4f;" since="18" />
+		<method name="subShort2()Landroid/renderscript/Short2;" since="18" />
+		<method name="subShort3()Landroid/renderscript/Short3;" since="18" />
+		<method name="subShort4()Landroid/renderscript/Short4;" since="18" />
+		<method name="subalign(I)V" since="18" />
 	</class>
 	<class name="android/renderscript/FileA3D" since="11">
 		<extends name="android/renderscript/BaseObj" />
@@ -19860,15 +21000,25 @@
 		<method name="&lt;init>()V" />
 		<method name="contextDump()V" />
 		<method name="create(Landroid/content/Context;)Landroid/renderscript/RenderScript;" />
+		<method name="create(Landroid/content/Context;Landroid/renderscript/RenderScript$ContextType;)Landroid/renderscript/RenderScript;" since="18" />
 		<method name="destroy()V" />
 		<method name="finish()V" />
 		<method name="getApplicationContext()Landroid/content/Context;" />
 		<method name="getErrorHandler()Landroid/renderscript/RenderScript$RSErrorHandler;" />
 		<method name="getMessageHandler()Landroid/renderscript/RenderScript$RSMessageHandler;" />
+		<method name="sendMessage(I[I)V" since="18" />
 		<method name="setErrorHandler(Landroid/renderscript/RenderScript$RSErrorHandler;)V" />
 		<method name="setMessageHandler(Landroid/renderscript/RenderScript$RSMessageHandler;)V" />
 		<method name="setPriority(Landroid/renderscript/RenderScript$Priority;)V" />
 	</class>
+	<class name="android/renderscript/RenderScript$ContextType" since="18">
+		<extends name="java/lang/Enum" />
+		<method name="valueOf(Ljava/lang/String;)Landroid/renderscript/RenderScript$ContextType;" />
+		<method name="values()[Landroid/renderscript/RenderScript$ContextType;" />
+		<field name="DEBUG" />
+		<field name="NORMAL" />
+		<field name="PROFILE" />
+	</class>
 	<class name="android/renderscript/RenderScript$Priority" since="11">
 		<extends name="java/lang/Enum" />
 		<method name="valueOf(Ljava/lang/String;)Landroid/renderscript/RenderScript$Priority;" />
@@ -19921,6 +21071,9 @@
 		<method name="CLAMP_LINEAR(Landroid/renderscript/RenderScript;)Landroid/renderscript/Sampler;" />
 		<method name="CLAMP_LINEAR_MIP_LINEAR(Landroid/renderscript/RenderScript;)Landroid/renderscript/Sampler;" />
 		<method name="CLAMP_NEAREST(Landroid/renderscript/RenderScript;)Landroid/renderscript/Sampler;" />
+		<method name="MIRRORED_REPEAT_LINEAR(Landroid/renderscript/RenderScript;)Landroid/renderscript/Sampler;" since="18" />
+		<method name="MIRRORED_REPEAT_LINEAR_MIP_LINEAR(Landroid/renderscript/RenderScript;)Landroid/renderscript/Sampler;" since="18" />
+		<method name="MIRRORED_REPEAT_NEAREST(Landroid/renderscript/RenderScript;)Landroid/renderscript/Sampler;" since="18" />
 		<method name="WRAP_LINEAR(Landroid/renderscript/RenderScript;)Landroid/renderscript/Sampler;" />
 		<method name="WRAP_LINEAR_MIP_LINEAR(Landroid/renderscript/RenderScript;)Landroid/renderscript/Sampler;" />
 		<method name="WRAP_NEAREST(Landroid/renderscript/RenderScript;)Landroid/renderscript/Sampler;" />
@@ -19948,6 +21101,7 @@
 		<field name="LINEAR" />
 		<field name="LINEAR_MIP_LINEAR" />
 		<field name="LINEAR_MIP_NEAREST" />
+		<field name="MIRRORED_REPEAT" since="18" />
 		<field name="NEAREST" />
 		<field name="WRAP" />
 	</class>
@@ -19958,6 +21112,13 @@
 		<method name="createFieldID(ILandroid/renderscript/Element;)Landroid/renderscript/Script$FieldID;" since="17" />
 		<method name="createKernelID(IILandroid/renderscript/Element;Landroid/renderscript/Element;)Landroid/renderscript/Script$KernelID;" since="17" />
 		<method name="forEach(ILandroid/renderscript/Allocation;Landroid/renderscript/Allocation;Landroid/renderscript/FieldPacker;)V" since="14" />
+		<method name="forEach(ILandroid/renderscript/Allocation;Landroid/renderscript/Allocation;Landroid/renderscript/FieldPacker;Landroid/renderscript/Script$LaunchOptions;)V" since="18" />
+		<method name="getVarB(I)Z" since="18" />
+		<method name="getVarD(I)D" since="18" />
+		<method name="getVarF(I)F" since="18" />
+		<method name="getVarI(I)I" since="18" />
+		<method name="getVarJ(I)J" since="18" />
+		<method name="getVarV(ILandroid/renderscript/FieldPacker;)V" since="18" />
 		<method name="invoke(I)V" />
 		<method name="invoke(ILandroid/renderscript/FieldPacker;)V" />
 		<method name="setTimeZone(Ljava/lang/String;)V" />
@@ -19994,6 +21155,19 @@
 		<extends name="android/renderscript/BaseObj" />
 		<method name="&lt;init>()V" />
 	</class>
+	<class name="android/renderscript/Script$LaunchOptions" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>()V" />
+		<method name="getXEnd()I" />
+		<method name="getXStart()I" />
+		<method name="getYEnd()I" />
+		<method name="getYStart()I" />
+		<method name="getZEnd()I" />
+		<method name="getZStart()I" />
+		<method name="setX(II)Landroid/renderscript/Script$LaunchOptions;" />
+		<method name="setY(II)Landroid/renderscript/Script$LaunchOptions;" />
+		<method name="setZ(II)Landroid/renderscript/Script$LaunchOptions;" />
+	</class>
 	<class name="android/renderscript/ScriptC" since="11">
 		<extends name="android/renderscript/Script" />
 		<method name="&lt;init>(ILandroid/renderscript/RenderScript;)V" />
@@ -20018,6 +21192,14 @@
 		<extends name="android/renderscript/Script" />
 		<method name="&lt;init>()V" />
 	</class>
+	<class name="android/renderscript/ScriptIntrinsic3DLUT" since="18">
+		<extends name="android/renderscript/ScriptIntrinsic" />
+		<method name="&lt;init>()V" />
+		<method name="create(Landroid/renderscript/RenderScript;Landroid/renderscript/Element;)Landroid/renderscript/ScriptIntrinsic3DLUT;" />
+		<method name="forEach(Landroid/renderscript/Allocation;Landroid/renderscript/Allocation;)V" />
+		<method name="getKernelID()Landroid/renderscript/Script$KernelID;" />
+		<method name="setLUT(Landroid/renderscript/Allocation;)V" />
+	</class>
 	<class name="android/renderscript/ScriptIntrinsicBlend" since="17">
 		<extends name="android/renderscript/ScriptIntrinsic" />
 		<method name="&lt;init>()V" />
@@ -20146,6 +21328,7 @@
 		<method name="getElement()Landroid/renderscript/Element;" />
 		<method name="getX()I" />
 		<method name="getY()I" />
+		<method name="getYuv()I" since="18" />
 		<method name="getZ()I" />
 		<method name="hasFaces()Z" />
 		<method name="hasMipmaps()Z" />
@@ -20158,6 +21341,8 @@
 		<method name="setMipmaps(Z)Landroid/renderscript/Type$Builder;" />
 		<method name="setX(I)Landroid/renderscript/Type$Builder;" />
 		<method name="setY(I)Landroid/renderscript/Type$Builder;" />
+		<method name="setYuvFormat(I)Landroid/renderscript/Type$Builder;" since="18" />
+		<method name="setZ(I)Landroid/renderscript/Type$Builder;" since="18" />
 	</class>
 	<class name="android/renderscript/Type$CubemapFace" since="11">
 		<extends name="java/lang/Enum" />
@@ -20214,10 +21399,40 @@
 		<implements name="android/sax/EndTextElementListener" />
 		<implements name="android/sax/StartElementListener" />
 	</class>
-	<class name="android/security/AndroidKeyPairGeneratorSpec" since="17">
+	<class name="android/security/AndroidKeyPairGeneratorSpec" since="18">
 		<extends name="java/lang/Object" />
 		<implements name="java/security/spec/AlgorithmParameterSpec" />
-		<method name="&lt;init>(Landroid/content/Context;Ljava/lang/String;Ljavax/security/auth/x500/X500Principal;Ljava/math/BigInteger;Ljava/util/Date;Ljava/util/Date;)V" />
+		<method name="&lt;init>()V" />
+		<method name="getContext()Landroid/content/Context;" />
+		<method name="getEndDate()Ljava/util/Date;" />
+		<method name="getKeystoreAlias()Ljava/lang/String;" />
+		<method name="getSerialNumber()Ljava/math/BigInteger;" />
+		<method name="getStartDate()Ljava/util/Date;" />
+		<method name="getSubjectDN()Ljavax/security/auth/x500/X500Principal;" />
+		<method name="isEncryptionRequired()Z" />
+	</class>
+	<class name="android/security/AndroidKeyPairGeneratorSpec$Builder" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>(Landroid/content/Context;)V" />
+		<method name="build()Landroid/security/AndroidKeyPairGeneratorSpec;" />
+		<method name="setAlias(Ljava/lang/String;)Landroid/security/AndroidKeyPairGeneratorSpec$Builder;" />
+		<method name="setEncryptionRequired()Landroid/security/AndroidKeyPairGeneratorSpec$Builder;" />
+		<method name="setEndDate(Ljava/util/Date;)Landroid/security/AndroidKeyPairGeneratorSpec$Builder;" />
+		<method name="setSerialNumber(Ljava/math/BigInteger;)Landroid/security/AndroidKeyPairGeneratorSpec$Builder;" />
+		<method name="setStartDate(Ljava/util/Date;)Landroid/security/AndroidKeyPairGeneratorSpec$Builder;" />
+		<method name="setSubject(Ljavax/security/auth/x500/X500Principal;)Landroid/security/AndroidKeyPairGeneratorSpec$Builder;" />
+	</class>
+	<class name="android/security/AndroidKeyStoreParameter" since="18">
+		<extends name="java/lang/Object" />
+		<implements name="java/security/KeyStore$ProtectionParameter" />
+		<method name="&lt;init>()V" />
+		<method name="isEncryptionRequired()Z" />
+	</class>
+	<class name="android/security/AndroidKeyStoreParameter$Builder" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>(Landroid/content/Context;)V" />
+		<method name="build()Landroid/security/AndroidKeyStoreParameter;" />
+		<method name="setEncryptionRequired()Landroid/security/AndroidKeyStoreParameter$Builder;" />
 	</class>
 	<class name="android/security/KeyChain" since="14">
 		<extends name="java/lang/Object" />
@@ -20226,6 +21441,8 @@
 		<method name="createInstallIntent()Landroid/content/Intent;" />
 		<method name="getCertificateChain(Landroid/content/Context;Ljava/lang/String;)[Ljava/security/cert/X509Certificate;" />
 		<method name="getPrivateKey(Landroid/content/Context;Ljava/lang/String;)Ljava/security/PrivateKey;" />
+		<method name="isBoundKeyAlgorithm(Ljava/lang/String;)Z" since="18" />
+		<method name="isKeyAlgorithmSupported(Ljava/lang/String;)Z" since="18" />
 		<field name="ACTION_STORAGE_CHANGED" since="16" />
 		<field name="EXTRA_CERTIFICATE" />
 		<field name="EXTRA_NAME" />
@@ -20242,31 +21459,40 @@
 		<method name="&lt;init>(Ljava/lang/String;Ljava/lang/Throwable;)V" />
 		<method name="&lt;init>(Ljava/lang/Throwable;)V" />
 	</class>
-	<class name="android/service/dreams/Dream" since="17">
-		<extends name="android/app/Service" />
-		<implements name="android/view/Window$Callback" />
+	<class name="android/security/KeyPairGeneratorSpec" since="18">
+		<extends name="java/lang/Object" />
+		<implements name="java/security/spec/AlgorithmParameterSpec" />
 		<method name="&lt;init>()V" />
-		<method name="addContentView(Landroid/view/View;Landroid/view/ViewGroup$LayoutParams;)V" />
-		<method name="findViewById(I)Landroid/view/View;" />
-		<method name="finish()V" />
-		<method name="getWindow()Landroid/view/Window;" />
-		<method name="getWindowManager()Landroid/view/WindowManager;" />
-		<method name="isFullscreen()Z" />
-		<method name="isInteractive()Z" />
-		<method name="isLowProfile()Z" />
-		<method name="isScreenBright()Z" />
-		<method name="onStart()V" />
-		<method name="setContentView(I)V" />
-		<method name="setContentView(Landroid/view/View;)V" />
-		<method name="setContentView(Landroid/view/View;Landroid/view/ViewGroup$LayoutParams;)V" />
-		<method name="setFullscreen(Z)V" />
-		<method name="setInteractive(Z)V" />
-		<method name="setLowProfile(Z)V" />
-		<method name="setScreenBright(Z)V" />
-		<field name="ACTION_DREAMING_STARTED" />
-		<field name="ACTION_DREAMING_STOPPED" />
-		<field name="CATEGORY_DREAM" />
-		<field name="DREAM_META_DATA" />
+		<method name="getContext()Landroid/content/Context;" />
+		<method name="getEndDate()Ljava/util/Date;" />
+		<method name="getKeystoreAlias()Ljava/lang/String;" />
+		<method name="getSerialNumber()Ljava/math/BigInteger;" />
+		<method name="getStartDate()Ljava/util/Date;" />
+		<method name="getSubjectDN()Ljavax/security/auth/x500/X500Principal;" />
+		<method name="isEncryptionRequired()Z" />
+	</class>
+	<class name="android/security/KeyPairGeneratorSpec$Builder" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>(Landroid/content/Context;)V" />
+		<method name="build()Landroid/security/KeyPairGeneratorSpec;" />
+		<method name="setAlias(Ljava/lang/String;)Landroid/security/KeyPairGeneratorSpec$Builder;" />
+		<method name="setEncryptionRequired()Landroid/security/KeyPairGeneratorSpec$Builder;" />
+		<method name="setEndDate(Ljava/util/Date;)Landroid/security/KeyPairGeneratorSpec$Builder;" />
+		<method name="setSerialNumber(Ljava/math/BigInteger;)Landroid/security/KeyPairGeneratorSpec$Builder;" />
+		<method name="setStartDate(Ljava/util/Date;)Landroid/security/KeyPairGeneratorSpec$Builder;" />
+		<method name="setSubject(Ljavax/security/auth/x500/X500Principal;)Landroid/security/KeyPairGeneratorSpec$Builder;" />
+	</class>
+	<class name="android/security/KeyStoreParameter" since="18">
+		<extends name="java/lang/Object" />
+		<implements name="java/security/KeyStore$ProtectionParameter" />
+		<method name="&lt;init>()V" />
+		<method name="isEncryptionRequired()Z" />
+	</class>
+	<class name="android/security/KeyStoreParameter$Builder" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>(Landroid/content/Context;)V" />
+		<method name="build()Landroid/security/KeyStoreParameter;" />
+		<method name="setEncryptionRequired(Z)Landroid/security/KeyStoreParameter$Builder;" />
 	</class>
 	<class name="android/service/dreams/DreamService" since="17">
 		<extends name="android/app/Service" />
@@ -20291,6 +21517,32 @@
 		<field name="DREAM_META_DATA" />
 		<field name="SERVICE_INTERFACE" />
 	</class>
+	<class name="android/service/notification/NotificationListenerService" since="18">
+		<extends name="android/app/Service" />
+		<method name="&lt;init>()V" />
+		<method name="cancelAllNotifications()V" />
+		<method name="cancelNotification(Ljava/lang/String;Ljava/lang/String;I)V" />
+		<method name="getActiveNotifications()[Landroid/service/notification/StatusBarNotification;" />
+		<method name="onNotificationPosted(Landroid/service/notification/StatusBarNotification;)V" />
+		<method name="onNotificationRemoved(Landroid/service/notification/StatusBarNotification;)V" />
+		<field name="SERVICE_INTERFACE" />
+	</class>
+	<class name="android/service/notification/StatusBarNotification" since="18">
+		<extends name="java/lang/Object" />
+		<implements name="android/os/Parcelable" />
+		<method name="&lt;init>(Landroid/os/Parcel;)V" />
+		<method name="&lt;init>(Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;IIILandroid/app/Notification;Landroid/os/UserHandle;J)V" />
+		<method name="clone()Landroid/service/notification/StatusBarNotification;" />
+		<method name="getId()I" />
+		<method name="getNotification()Landroid/app/Notification;" />
+		<method name="getPackageName()Ljava/lang/String;" />
+		<method name="getPostTime()J" />
+		<method name="getTag()Ljava/lang/String;" />
+		<method name="getUserId()I" />
+		<method name="isClearable()Z" />
+		<method name="isOngoing()Z" />
+		<field name="CREATOR" />
+	</class>
 	<class name="android/service/textservice/SpellCheckerService" since="14">
 		<extends name="android/app/Service" />
 		<method name="&lt;init>()V" />
@@ -20471,9 +21723,11 @@
 		<method name="addSpeech(Ljava/lang/String;Ljava/lang/String;I)I" />
 		<method name="areDefaultsEnforced()Z" since="8" />
 		<method name="getDefaultEngine()Ljava/lang/String;" since="8" />
+		<method name="getDefaultLanguage()Ljava/util/Locale;" since="18" />
 		<method name="getEngines()Ljava/util/List;" since="14" />
 		<method name="getFeatures(Ljava/util/Locale;)Ljava/util/Set;" since="15" />
 		<method name="getLanguage()Ljava/util/Locale;" />
+		<method name="getMaxSpeechInputLength()I" since="18" />
 		<method name="isLanguageAvailable(Ljava/util/Locale;)I" />
 		<method name="isSpeaking()Z" />
 		<method name="playEarcon(Ljava/lang/String;ILjava/util/HashMap;)I" />
@@ -20503,6 +21757,7 @@
 		<extends name="java/lang/Object" />
 		<method name="&lt;init>(Landroid/speech/tts/TextToSpeech;)V" />
 		<field name="ACTION_CHECK_TTS_DATA" />
+		<field name="ACTION_GET_SAMPLE_TEXT" since="18" />
 		<field name="ACTION_INSTALL_TTS_DATA" />
 		<field name="ACTION_TTS_DATA_INSTALLED" />
 		<field name="CHECK_VOICE_DATA_BAD_DATA" />
@@ -20513,6 +21768,7 @@
 		<field name="DEFAULT_STREAM" />
 		<field name="EXTRA_AVAILABLE_VOICES" since="8" />
 		<field name="EXTRA_CHECK_VOICE_DATA_FOR" since="8" />
+		<field name="EXTRA_SAMPLE_TEXT" since="18" />
 		<field name="EXTRA_TTS_DATA_INSTALLED" />
 		<field name="EXTRA_UNAVAILABLE_VOICES" since="8" />
 		<field name="EXTRA_VOICE_DATA_FILES" />
@@ -20559,12 +21815,6 @@
 		<method name="onError(Ljava/lang/String;)V" />
 		<method name="onStart(Ljava/lang/String;)V" />
 	</class>
-	<class name="android/telephony/CellIdentity" since="17">
-		<extends name="java/lang/Object" />
-		<implements name="android/os/Parcelable" />
-		<method name="&lt;init>()V" />
-		<field name="CREATOR" />
-	</class>
 	<class name="android/telephony/CellIdentityCdma" since="17">
 		<extends name="java/lang/Object" />
 		<implements name="android/os/Parcelable" />
@@ -20598,6 +21848,17 @@
 		<method name="getTac()I" />
 		<field name="CREATOR" />
 	</class>
+	<class name="android/telephony/CellIdentityWcdma" since="18">
+		<extends name="java/lang/Object" />
+		<implements name="android/os/Parcelable" />
+		<method name="&lt;init>()V" />
+		<method name="getCid()I" />
+		<method name="getLac()I" />
+		<method name="getMcc()I" />
+		<method name="getMnc()I" />
+		<method name="getPsc()I" />
+		<field name="CREATOR" />
+	</class>
 	<class name="android/telephony/CellInfo" since="17">
 		<extends name="java/lang/Object" />
 		<implements name="android/os/Parcelable" />
@@ -20630,6 +21891,14 @@
 		<method name="getCellSignalStrength()Landroid/telephony/CellSignalStrengthLte;" />
 		<field name="CREATOR" />
 	</class>
+	<class name="android/telephony/CellInfoWcdma" since="18">
+		<extends name="android/telephony/CellInfo" />
+		<implements name="android/os/Parcelable" />
+		<method name="&lt;init>()V" />
+		<method name="getCellIdentity()Landroid/telephony/CellIdentityWcdma;" />
+		<method name="getCellSignalStrength()Landroid/telephony/CellSignalStrengthWcdma;" />
+		<field name="CREATOR" />
+	</class>
 	<class name="android/telephony/CellLocation" since="1">
 		<extends name="java/lang/Object" />
 		<method name="&lt;init>()V" />
@@ -20669,6 +21938,12 @@
 		<method name="getTimingAdvance()I" />
 		<field name="CREATOR" />
 	</class>
+	<class name="android/telephony/CellSignalStrengthWcdma" since="18">
+		<extends name="android/telephony/CellSignalStrength" />
+		<implements name="android/os/Parcelable" />
+		<method name="&lt;init>()V" />
+		<field name="CREATOR" />
+	</class>
 	<class name="android/telephony/NeighboringCellInfo" since="3">
 		<extends name="java/lang/Object" />
 		<implements name="android/os/Parcelable" />
@@ -20886,6 +22161,7 @@
 		<method name="getDataState()I" />
 		<method name="getDeviceId()Ljava/lang/String;" />
 		<method name="getDeviceSoftwareVersion()Ljava/lang/String;" />
+		<method name="getGroupIdLevel1()Ljava/lang/String;" since="18" />
 		<method name="getLine1Number()Ljava/lang/String;" />
 		<method name="getNeighboringCellInfo()Ljava/util/List;" since="3" />
 		<method name="getNetworkCountryIso()Ljava/lang/String;" />
@@ -20905,6 +22181,7 @@
 		<method name="isNetworkRoaming()Z" />
 		<method name="listen(Landroid/telephony/PhoneStateListener;I)V" />
 		<field name="ACTION_PHONE_STATE_CHANGED" since="3" />
+		<field name="ACTION_RESPOND_VIA_MESSAGE" since="18" />
 		<field name="CALL_STATE_IDLE" />
 		<field name="CALL_STATE_OFFHOOK" />
 		<field name="CALL_STATE_RINGING" />
@@ -21153,6 +22430,7 @@
 		<method name="&lt;init>()V" />
 		<method name="getAllTests()Ljunit/framework/TestSuite;" />
 		<method name="getAndroidTestRunner()Landroid/test/AndroidTestRunner;" />
+		<method name="getArguments()Landroid/os/Bundle;" since="18" />
 		<method name="getLoader()Ljava/lang/ClassLoader;" />
 		<field name="REPORT_KEY_NAME_CLASS" />
 		<field name="REPORT_KEY_NAME_TEST" />
@@ -21362,6 +22640,7 @@
 	<class name="android/test/mock/MockContentResolver" since="1">
 		<extends name="android/content/ContentResolver" />
 		<method name="&lt;init>()V" />
+		<method name="&lt;init>(Landroid/content/Context;)V" since="18" />
 		<method name="addProvider(Ljava/lang/String;Landroid/content/ContentProvider;)V" />
 	</class>
 	<class name="android/test/mock/MockContext" since="1">
@@ -21488,6 +22767,29 @@
 		<method name="get(Ljava/lang/CharSequence;IILandroid/view/View;)Ljava/lang/String;" />
 		<method name="getSize(Landroid/view/View;)I" since="3" />
 	</class>
+	<class name="android/text/BidiFormatter" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>()V" />
+		<method name="getInstance()Landroid/text/BidiFormatter;" />
+		<method name="getInstance(Ljava/util/Locale;)Landroid/text/BidiFormatter;" />
+		<method name="getInstance(Z)Landroid/text/BidiFormatter;" />
+		<method name="getStereoReset()Z" />
+		<method name="isRtl(Ljava/lang/String;)Z" />
+		<method name="isRtlContext()Z" />
+		<method name="unicodeWrap(Ljava/lang/String;)Ljava/lang/String;" />
+		<method name="unicodeWrap(Ljava/lang/String;Landroid/text/TextDirectionHeuristic;)Ljava/lang/String;" />
+		<method name="unicodeWrap(Ljava/lang/String;Landroid/text/TextDirectionHeuristic;Z)Ljava/lang/String;" />
+		<method name="unicodeWrap(Ljava/lang/String;Z)Ljava/lang/String;" />
+	</class>
+	<class name="android/text/BidiFormatter$Builder" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>()V" />
+		<method name="&lt;init>(Ljava/util/Locale;)V" />
+		<method name="&lt;init>(Z)V" />
+		<method name="build()Landroid/text/BidiFormatter;" />
+		<method name="setTextDirectionHeuristic(Landroid/text/TextDirectionHeuristic;)Landroid/text/BidiFormatter$Builder;" />
+		<method name="stereoReset(Z)Landroid/text/BidiFormatter$Builder;" />
+	</class>
 	<class name="android/text/BoringLayout" since="1">
 		<extends name="android/text/Layout" />
 		<implements name="android/text/TextUtils$EllipsizeCallback" />
@@ -21846,6 +23148,21 @@
 		<method name="&lt;init>(Ljava/lang/CharSequence;IILandroid/text/TextPaint;ILandroid/text/Layout$Alignment;FFZLandroid/text/TextUtils$TruncateAt;I)V" />
 		<method name="&lt;init>(Ljava/lang/CharSequence;Landroid/text/TextPaint;ILandroid/text/Layout$Alignment;FFZ)V" />
 	</class>
+	<class name="android/text/TextDirectionHeuristic" since="18">
+		<extends name="java/lang/Object" />
+		<method name="isRtl(Ljava/lang/CharSequence;II)Z" />
+		<method name="isRtl([CII)Z" />
+	</class>
+	<class name="android/text/TextDirectionHeuristics" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>()V" />
+		<field name="ANYRTL_LTR" />
+		<field name="FIRSTSTRONG_LTR" />
+		<field name="FIRSTSTRONG_RTL" />
+		<field name="LOCALE" />
+		<field name="LTR" />
+		<field name="RTL" />
+	</class>
 	<class name="android/text/TextPaint" since="1">
 		<extends name="android/graphics/Paint" />
 		<method name="&lt;init>()V" />
@@ -21936,12 +23253,53 @@
 		<method name="beforeTextChanged(Ljava/lang/CharSequence;III)V" />
 		<method name="onTextChanged(Ljava/lang/CharSequence;III)V" />
 	</class>
+	<class name="android/text/bidi/BidiFormatter" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>()V" />
+		<method name="dirAttr(Ljava/lang/String;)Ljava/lang/String;" />
+		<method name="dirAttr(Ljava/lang/String;Landroid/text/TextDirectionHeuristic;)Ljava/lang/String;" />
+		<method name="dirAttr(Z)Ljava/lang/String;" />
+		<method name="dirAttrValue(Ljava/lang/String;)Ljava/lang/String;" />
+		<method name="dirAttrValue(Ljava/lang/String;Landroid/text/TextDirectionHeuristic;)Ljava/lang/String;" />
+		<method name="dirAttrValue(Z)Ljava/lang/String;" />
+		<method name="endEdge()Ljava/lang/String;" />
+		<method name="getInstance()Landroid/text/bidi/BidiFormatter;" />
+		<method name="getInstance(Ljava/util/Locale;)Landroid/text/bidi/BidiFormatter;" />
+		<method name="getInstance(Z)Landroid/text/bidi/BidiFormatter;" />
+		<method name="getStereoReset()Z" />
+		<method name="isRtl(Ljava/lang/String;)Z" />
+		<method name="isRtlContext()Z" />
+		<method name="mark()Ljava/lang/String;" />
+		<method name="markAfter(Ljava/lang/String;)Ljava/lang/String;" />
+		<method name="markAfter(Ljava/lang/String;Landroid/text/TextDirectionHeuristic;)Ljava/lang/String;" />
+		<method name="markBefore(Ljava/lang/String;)Ljava/lang/String;" />
+		<method name="markBefore(Ljava/lang/String;Landroid/text/TextDirectionHeuristic;)Ljava/lang/String;" />
+		<method name="spanWrap(Ljava/lang/String;)Ljava/lang/String;" />
+		<method name="spanWrap(Ljava/lang/String;Landroid/text/TextDirectionHeuristic;)Ljava/lang/String;" />
+		<method name="spanWrap(Ljava/lang/String;Landroid/text/TextDirectionHeuristic;Z)Ljava/lang/String;" />
+		<method name="spanWrap(Ljava/lang/String;Z)Ljava/lang/String;" />
+		<method name="startEdge()Ljava/lang/String;" />
+		<method name="unicodeWrap(Ljava/lang/String;)Ljava/lang/String;" />
+		<method name="unicodeWrap(Ljava/lang/String;Landroid/text/TextDirectionHeuristic;)Ljava/lang/String;" />
+		<method name="unicodeWrap(Ljava/lang/String;Landroid/text/TextDirectionHeuristic;Z)Ljava/lang/String;" />
+		<method name="unicodeWrap(Ljava/lang/String;Z)Ljava/lang/String;" />
+	</class>
+	<class name="android/text/bidi/BidiFormatter$Builder" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>()V" />
+		<method name="&lt;init>(Ljava/util/Locale;)V" />
+		<method name="&lt;init>(Z)V" />
+		<method name="build()Landroid/text/bidi/BidiFormatter;" />
+		<method name="setTextDirectionHeuristic(Landroid/text/TextDirectionHeuristic;)Landroid/text/bidi/BidiFormatter$Builder;" />
+		<method name="stereoReset(Z)Landroid/text/bidi/BidiFormatter$Builder;" />
+	</class>
 	<class name="android/text/format/DateFormat" since="3">
 		<extends name="java/lang/Object" />
 		<method name="&lt;init>()V" />
 		<method name="format(Ljava/lang/CharSequence;J)Ljava/lang/CharSequence;" />
 		<method name="format(Ljava/lang/CharSequence;Ljava/util/Calendar;)Ljava/lang/CharSequence;" />
 		<method name="format(Ljava/lang/CharSequence;Ljava/util/Date;)Ljava/lang/CharSequence;" />
+		<method name="getBestDateTimePattern(Ljava/util/Locale;Ljava/lang/String;)Ljava/lang/String;" since="18" />
 		<method name="getDateFormat(Landroid/content/Context;)Ljava/text/DateFormat;" />
 		<method name="getDateFormatOrder(Landroid/content/Context;)[C" />
 		<method name="getLongDateFormat(Landroid/content/Context;)Ljava/text/DateFormat;" />
@@ -22380,6 +23738,11 @@
 		<extends name="java/lang/Object" />
 		<implements name="android/text/ParcelableSpan" />
 		<method name="&lt;init>()V" />
+		<method name="&lt;init>(Landroid/app/PendingIntent;)V" since="18" />
+		<method name="&lt;init>(Landroid/os/Parcel;)V" since="18" />
+		<field name="EXTRA_TEXT_CHANGED_TYPE" since="18" />
+		<field name="TEXT_DELETED" since="18" />
+		<field name="TEXT_MODIFIED" since="18" />
 	</class>
 	<class name="android/text/style/ForegroundColorSpan" since="1">
 		<extends name="android/text/style/CharacterStyle" />
@@ -22760,6 +24123,7 @@
 		<field name="DENSITY_TV" since="13" />
 		<field name="DENSITY_XHIGH" since="9" />
 		<field name="DENSITY_XXHIGH" since="16" />
+		<field name="DENSITY_XXXHIGH" since="18" />
 		<field name="density" />
 		<field name="densityDpi" since="4" />
 		<field name="heightPixels" />
@@ -22869,11 +24233,6 @@
 		<method name="value(Ljava/lang/String;)Landroid/util/JsonWriter;" />
 		<method name="value(Z)Landroid/util/JsonWriter;" />
 	</class>
-	<class name="android/util/LocaleUtil" since="17">
-		<extends name="java/lang/Object" />
-		<method name="&lt;init>()V" />
-		<method name="getLayoutDirectionFromLocale(Ljava/util/Locale;)I" />
-	</class>
 	<class name="android/util/Log" since="1">
 		<extends name="java/lang/Object" />
 		<method name="&lt;init>()V" />
@@ -23019,7 +24378,7 @@
 		<method name="of(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/String;)Landroid/util/Property;" />
 		<method name="set(Ljava/lang/Object;Ljava/lang/Object;)V" />
 	</class>
-	<class name="android/util/PropertyValueModel" since="17">
+	<class name="android/util/PropertyValueModel" since="18">
 		<extends name="android/util/ValueModel" />
 		<method name="&lt;init>()V" />
 		<method name="getHost()Ljava/lang/Object;" />
@@ -23086,6 +24445,25 @@
 		<method name="size()I" />
 		<method name="valueAt(I)I" />
 	</class>
+	<class name="android/util/SparseLongArray" since="18">
+		<extends name="java/lang/Object" />
+		<implements name="java/lang/Cloneable" />
+		<method name="&lt;init>()V" />
+		<method name="&lt;init>(I)V" />
+		<method name="append(IJ)V" />
+		<method name="clear()V" />
+		<method name="clone()Landroid/util/SparseLongArray;" />
+		<method name="delete(I)V" />
+		<method name="get(I)J" />
+		<method name="get(IJ)J" />
+		<method name="indexOfKey(I)I" />
+		<method name="indexOfValue(J)I" />
+		<method name="keyAt(I)I" />
+		<method name="put(IJ)V" />
+		<method name="removeAt(I)V" />
+		<method name="size()I" />
+		<method name="valueAt(I)J" />
+	</class>
 	<class name="android/util/StateSet" since="1">
 		<extends name="java/lang/Object" />
 		<method name="&lt;init>()V" />
@@ -23182,7 +24560,7 @@
 		<field name="string" />
 		<field name="type" />
 	</class>
-	<class name="android/util/ValueModel" since="17">
+	<class name="android/util/ValueModel" since="18">
 		<extends name="java/lang/Object" />
 		<method name="&lt;init>()V" />
 		<method name="get()Ljava/lang/Object;" />
@@ -23475,6 +24853,7 @@
 		<field name="SOURCE_CLASS_BUTTON" />
 		<field name="SOURCE_CLASS_JOYSTICK" since="12" />
 		<field name="SOURCE_CLASS_MASK" />
+		<field name="SOURCE_CLASS_NONE" since="18" />
 		<field name="SOURCE_CLASS_POINTER" />
 		<field name="SOURCE_CLASS_POSITION" />
 		<field name="SOURCE_CLASS_TRACKBALL" />
@@ -23486,6 +24865,7 @@
 		<field name="SOURCE_STYLUS" since="14" />
 		<field name="SOURCE_TOUCHPAD" />
 		<field name="SOURCE_TOUCHSCREEN" />
+		<field name="SOURCE_TOUCH_NAVIGATION" since="18" />
 		<field name="SOURCE_TRACKBALL" />
 		<field name="SOURCE_UNKNOWN" />
 	</class>
@@ -23498,7 +24878,9 @@
 		<method name="getMax()F" />
 		<method name="getMin()F" />
 		<method name="getRange()F" />
+		<method name="getResolution()F" since="18" />
 		<method name="getSource()I" since="12" />
+		<method name="isFromSource(I)Z" since="18" />
 	</class>
 	<class name="android/view/InputEvent" since="9">
 		<extends name="java/lang/Object" />
@@ -23508,6 +24890,7 @@
 		<method name="getDeviceId()I" />
 		<method name="getEventTime()J" since="16" />
 		<method name="getSource()I" />
+		<method name="isFromSource(I)Z" since="18" />
 		<field name="CREATOR" />
 	</class>
 	<class name="android/view/InputQueue" since="9">
@@ -23670,6 +25053,8 @@
 		<field name="KEYCODE_BACKSLASH" />
 		<field name="KEYCODE_BOOKMARK" since="11" />
 		<field name="KEYCODE_BREAK" since="11" />
+		<field name="KEYCODE_BRIGHTNESS_DOWN" since="18" />
+		<field name="KEYCODE_BRIGHTNESS_UP" since="18" />
 		<field name="KEYCODE_BUTTON_1" since="12" />
 		<field name="KEYCODE_BUTTON_10" since="12" />
 		<field name="KEYCODE_BUTTON_11" since="12" />
@@ -24538,6 +25923,7 @@
 		<method name="getBottomFadingEdgeStrength()F" />
 		<method name="getBottomPaddingOffset()I" since="2" />
 		<method name="getCameraDistance()F" since="16" />
+		<method name="getClipBounds()Landroid/graphics/Rect;" since="18" />
 		<method name="getContentDescription()Ljava/lang/CharSequence;" since="4" />
 		<method name="getContext()Landroid/content/Context;" />
 		<method name="getContextMenuInfo()Landroid/view/ContextMenu$ContextMenuInfo;" />
@@ -24590,6 +25976,7 @@
 		<method name="getNextFocusUpId()I" />
 		<method name="getOnFocusChangeListener()Landroid/view/View$OnFocusChangeListener;" />
 		<method name="getOverScrollMode()I" since="9" />
+		<method name="getOverlay()Landroid/view/ViewOverlay;" since="18" />
 		<method name="getPaddingBottom()I" />
 		<method name="getPaddingEnd()I" since="17" />
 		<method name="getPaddingLeft()I" />
@@ -24638,6 +26025,7 @@
 		<method name="getVisibility()I" />
 		<method name="getWidth()I" />
 		<method name="getWindowAttachCount()I" />
+		<method name="getWindowId()Landroid/view/WindowId;" since="18" />
 		<method name="getWindowSystemUiVisibility()I" since="16" />
 		<method name="getWindowToken()Landroid/os/IBinder;" />
 		<method name="getWindowVisibility()I" />
@@ -24671,6 +26059,7 @@
 		<method name="isHorizontalScrollBarEnabled()Z" />
 		<method name="isHovered()Z" since="14" />
 		<method name="isInEditMode()Z" since="3" />
+		<method name="isInLayout()Z" since="18" />
 		<method name="isInTouchMode()Z" />
 		<method name="isLayoutRequested()Z" />
 		<method name="isLongClickable()Z" />
@@ -24781,6 +26170,7 @@
 		<method name="setBottom(I)V" since="11" />
 		<method name="setCameraDistance(F)V" since="12" />
 		<method name="setClickable(Z)V" />
+		<method name="setClipBounds(Landroid/graphics/Rect;)V" since="18" />
 		<method name="setContentDescription(Ljava/lang/CharSequence;)V" since="4" />
 		<method name="setDrawingCacheBackgroundColor(I)V" />
 		<method name="setDrawingCacheEnabled(Z)V" />
@@ -25218,11 +26608,14 @@
 		<method name="getChildDrawingOrder(II)I" />
 		<method name="getChildMeasureSpec(III)I" />
 		<method name="getChildStaticTransformation(Landroid/view/View;Landroid/view/animation/Transformation;)Z" />
+		<method name="getClipChildren()Z" since="18" />
 		<method name="getDescendantFocusability()I" />
 		<method name="getFocusedChild()Landroid/view/View;" />
 		<method name="getLayoutAnimation()Landroid/view/animation/LayoutAnimationController;" />
 		<method name="getLayoutAnimationListener()Landroid/view/animation/Animation$AnimationListener;" />
+		<method name="getLayoutMode()I" since="18" />
 		<method name="getLayoutTransition()Landroid/animation/LayoutTransition;" since="11" />
+		<method name="getOverlay()Landroid/view/ViewGroupOverlay;" since="18" />
 		<method name="getPersistentDrawingCache()I" />
 		<method name="indexOfChild(Landroid/view/View;)I" />
 		<method name="isAlwaysDrawnWithCacheEnabled()Z" />
@@ -25261,6 +26654,7 @@
 		<method name="setDescendantFocusability(I)V" />
 		<method name="setLayoutAnimation(Landroid/view/animation/LayoutAnimationController;)V" />
 		<method name="setLayoutAnimationListener(Landroid/view/animation/Animation$AnimationListener;)V" />
+		<method name="setLayoutMode(I)V" since="18" />
 		<method name="setLayoutTransition(Landroid/animation/LayoutTransition;)V" since="11" />
 		<method name="setMotionEventSplittingEnabled(Z)V" since="11" />
 		<method name="setOnHierarchyChangeListener(Landroid/view/ViewGroup$OnHierarchyChangeListener;)V" />
@@ -25274,6 +26668,8 @@
 		<field name="FOCUS_AFTER_DESCENDANTS" />
 		<field name="FOCUS_BEFORE_DESCENDANTS" />
 		<field name="FOCUS_BLOCK_DESCENDANTS" />
+		<field name="LAYOUT_MODE_CLIP_BOUNDS" since="18" />
+		<field name="LAYOUT_MODE_OPTICAL_BOUNDS" since="18" />
 		<field name="PERSISTENT_ALL_CACHES" />
 		<field name="PERSISTENT_ANIMATION_CACHE" />
 		<field name="PERSISTENT_NO_CACHE" />
@@ -25317,12 +26713,25 @@
 		<method name="onChildViewAdded(Landroid/view/View;Landroid/view/View;)V" />
 		<method name="onChildViewRemoved(Landroid/view/View;Landroid/view/View;)V" />
 	</class>
+	<class name="android/view/ViewGroupOverlay" since="18">
+		<extends name="android/view/ViewOverlay" />
+		<method name="&lt;init>()V" />
+		<method name="add(Landroid/view/View;)V" />
+		<method name="remove(Landroid/view/View;)V" />
+	</class>
 	<class name="android/view/ViewManager" since="1">
 		<extends name="java/lang/Object" />
 		<method name="addView(Landroid/view/View;Landroid/view/ViewGroup$LayoutParams;)V" />
 		<method name="removeView(Landroid/view/View;)V" />
 		<method name="updateViewLayout(Landroid/view/View;Landroid/view/ViewGroup$LayoutParams;)V" />
 	</class>
+	<class name="android/view/ViewOverlay" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>()V" />
+		<method name="add(Landroid/graphics/drawable/Drawable;)V" />
+		<method name="clear()V" />
+		<method name="remove(Landroid/graphics/drawable/Drawable;)V" />
+	</class>
 	<class name="android/view/ViewParent" since="1">
 		<extends name="java/lang/Object" />
 		<method name="bringChildToFront(Landroid/view/View;)V" />
@@ -25355,6 +26764,7 @@
 		<method name="alphaBy(F)Landroid/view/ViewPropertyAnimator;" />
 		<method name="cancel()V" since="14" />
 		<method name="getDuration()J" since="14" />
+		<method name="getInterpolator()Landroid/animation/TimeInterpolator;" since="18" />
 		<method name="getStartDelay()J" since="14" />
 		<method name="rotation(F)Landroid/view/ViewPropertyAnimator;" />
 		<method name="rotationBy(F)Landroid/view/ViewPropertyAnimator;" />
@@ -25411,6 +26821,8 @@
 		<method name="addOnPreDrawListener(Landroid/view/ViewTreeObserver$OnPreDrawListener;)V" />
 		<method name="addOnScrollChangedListener(Landroid/view/ViewTreeObserver$OnScrollChangedListener;)V" since="3" />
 		<method name="addOnTouchModeChangeListener(Landroid/view/ViewTreeObserver$OnTouchModeChangeListener;)V" />
+		<method name="addOnWindowAttachListener(Landroid/view/ViewTreeObserver$OnWindowAttachListener;)V" since="18" />
+		<method name="addOnWindowFocusChangeListener(Landroid/view/ViewTreeObserver$OnWindowFocusChangeListener;)V" since="18" />
 		<method name="dispatchOnDraw()V" since="16" />
 		<method name="dispatchOnGlobalLayout()V" />
 		<method name="dispatchOnPreDraw()Z" />
@@ -25422,6 +26834,8 @@
 		<method name="removeOnPreDrawListener(Landroid/view/ViewTreeObserver$OnPreDrawListener;)V" />
 		<method name="removeOnScrollChangedListener(Landroid/view/ViewTreeObserver$OnScrollChangedListener;)V" since="3" />
 		<method name="removeOnTouchModeChangeListener(Landroid/view/ViewTreeObserver$OnTouchModeChangeListener;)V" />
+		<method name="removeOnWindowAttachListener(Landroid/view/ViewTreeObserver$OnWindowAttachListener;)V" since="18" />
+		<method name="removeOnWindowFocusChangeListener(Landroid/view/ViewTreeObserver$OnWindowFocusChangeListener;)V" since="18" />
 	</class>
 	<class name="android/view/ViewTreeObserver$OnDrawListener" since="16">
 		<extends name="java/lang/Object" />
@@ -25447,6 +26861,15 @@
 		<extends name="java/lang/Object" />
 		<method name="onTouchModeChanged(Z)V" />
 	</class>
+	<class name="android/view/ViewTreeObserver$OnWindowAttachListener" since="18">
+		<extends name="java/lang/Object" />
+		<method name="onWindowAttached()V" />
+		<method name="onWindowDetached()V" />
+	</class>
+	<class name="android/view/ViewTreeObserver$OnWindowFocusChangeListener" since="18">
+		<extends name="java/lang/Object" />
+		<method name="onWindowFocusChanged(Z)V" />
+	</class>
 	<class name="android/view/Window" since="1">
 		<extends name="java/lang/Object" />
 		<method name="&lt;init>(Landroid/content/Context;)V" />
@@ -25573,6 +26996,21 @@
 		<method name="onWindowFocusChanged(Z)V" />
 		<method name="onWindowStartingActionMode(Landroid/view/ActionMode$Callback;)Landroid/view/ActionMode;" since="11" />
 	</class>
+	<class name="android/view/WindowId" since="18">
+		<extends name="java/lang/Object" />
+		<implements name="android/os/Parcelable" />
+		<method name="&lt;init>()V" />
+		<method name="isFocused()Z" />
+		<method name="registerFocusObserver(Landroid/view/WindowId$FocusObserver;)V" />
+		<method name="unregisterFocusObserver(Landroid/view/WindowId$FocusObserver;)V" />
+		<field name="CREATOR" />
+	</class>
+	<class name="android/view/WindowId$FocusObserver" since="18">
+		<extends name="java/lang/Object" />
+		<method name="&lt;init>()V" />
+		<method name="onFocusGained(Landroid/view/WindowId;)V" />
+		<method name="onFocusLost(Landroid/view/WindowId;)V" />
+	</class>
 	<class name="android/view/WindowManager" since="1">
 		<extends name="java/lang/Object" />
 		<implements name="android/view/ViewManager" />
@@ -25627,6 +27065,7 @@
 		<field name="FLAG_IGNORE_CHEEK_PRESSES" />
 		<field name="FLAG_KEEP_SCREEN_ON" />
 		<field name="FLAG_LAYOUT_INSET_DECOR" />
+		<field name="FLAG_LAYOUT_IN_OVERSCAN" since="18" />
 		<field name="FLAG_LAYOUT_IN_SCREEN" />
 		<field name="FLAG_LAYOUT_NO_LIMITS" />
 		<field name="FLAG_NOT_FOCUSABLE" />
@@ -25650,6 +27089,10 @@
 		<field name="MEMORY_TYPE_HARDWARE" />
 		<field name="MEMORY_TYPE_NORMAL" />
 		<field name="MEMORY_TYPE_PUSH_BUFFERS" />
+		<field name="ROTATION_ANIMATION_CHANGED" since="18" />
+		<field name="ROTATION_ANIMATION_CROSSFADE" since="18" />
+		<field name="ROTATION_ANIMATION_JUMPCUT" since="18" />
+		<field name="ROTATION_ANIMATION_ROTATE" since="18" />
 		<field name="SCREEN_BRIGHTNESS_CHANGED" since="3" />
 		<field name="SCREEN_ORIENTATION_CHANGED" since="3" />
 		<field name="SOFT_INPUT_ADJUST_NOTHING" since="11" />
@@ -25700,6 +27143,7 @@
 		<field name="horizontalWeight" />
 		<field name="memoryType" />
 		<field name="packageName" />
+		<field name="rotationAnimation" since="18" />
 		<field name="screenBrightness" since="3" />
 		<field name="screenOrientation" since="3" />
 		<field name="softInputMode" since="3" />
@@ -25820,6 +27264,7 @@
 		<method name="addChild(Landroid/view/View;)V" />
 		<method name="addChild(Landroid/view/View;I)V" since="16" />
 		<method name="findAccessibilityNodeInfosByText(Ljava/lang/String;)Ljava/util/List;" />
+		<method name="findAccessibilityNodeInfosByViewId(Ljava/lang/String;)Ljava/util/List;" since="18" />
 		<method name="findFocus(I)Landroid/view/accessibility/AccessibilityNodeInfo;" since="16" />
 		<method name="focusSearch(I)Landroid/view/accessibility/AccessibilityNodeInfo;" since="16" />
 		<method name="getActions()I" />
@@ -25835,11 +27280,15 @@
 		<method name="getPackageName()Ljava/lang/CharSequence;" />
 		<method name="getParent()Landroid/view/accessibility/AccessibilityNodeInfo;" />
 		<method name="getText()Ljava/lang/CharSequence;" />
+		<method name="getTextSelectionEnd()I" since="18" />
+		<method name="getTextSelectionStart()I" since="18" />
+		<method name="getViewIdResourceName()Ljava/lang/String;" since="18" />
 		<method name="getWindowId()I" />
 		<method name="isAccessibilityFocused()Z" since="16" />
 		<method name="isCheckable()Z" />
 		<method name="isChecked()Z" />
 		<method name="isClickable()Z" />
+		<method name="isEditable()Z" since="18" />
 		<method name="isEnabled()Z" />
 		<method name="isFocusable()Z" />
 		<method name="isFocused()Z" />
@@ -25855,6 +27304,7 @@
 		<method name="performAction(I)Z" />
 		<method name="performAction(ILandroid/os/Bundle;)Z" since="16" />
 		<method name="recycle()V" />
+		<method name="refresh()Z" since="18" />
 		<method name="setAccessibilityFocused(Z)V" since="16" />
 		<method name="setBoundsInParent(Landroid/graphics/Rect;)V" />
 		<method name="setBoundsInScreen(Landroid/graphics/Rect;)V" />
@@ -25863,6 +27313,7 @@
 		<method name="setClassName(Ljava/lang/CharSequence;)V" />
 		<method name="setClickable(Z)V" />
 		<method name="setContentDescription(Ljava/lang/CharSequence;)V" />
+		<method name="setEditable(Z)V" since="18" />
 		<method name="setEnabled(Z)V" />
 		<method name="setFocusable(Z)V" />
 		<method name="setFocused(Z)V" />
@@ -25881,23 +27332,32 @@
 		<method name="setSource(Landroid/view/View;)V" />
 		<method name="setSource(Landroid/view/View;I)V" since="16" />
 		<method name="setText(Ljava/lang/CharSequence;)V" />
+		<method name="setTextSelection(II)V" since="18" />
+		<method name="setViewIdResourceName(Ljava/lang/String;)V" since="18" />
 		<method name="setVisibleToUser(Z)V" since="16" />
 		<field name="ACTION_ACCESSIBILITY_FOCUS" since="16" />
+		<field name="ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN" since="18" />
 		<field name="ACTION_ARGUMENT_HTML_ELEMENT_STRING" since="16" />
 		<field name="ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT" since="16" />
+		<field name="ACTION_ARGUMENT_SELECTION_END_INT" since="18" />
+		<field name="ACTION_ARGUMENT_SELECTION_START_INT" since="18" />
 		<field name="ACTION_CLEAR_ACCESSIBILITY_FOCUS" since="16" />
 		<field name="ACTION_CLEAR_FOCUS" />
 		<field name="ACTION_CLEAR_SELECTION" />
 		<field name="ACTION_CLICK" since="16" />
+		<field name="ACTION_COPY" since="18" />
+		<field name="ACTION_CUT" since="18" />
 		<field name="ACTION_FOCUS" />
 		<field name="ACTION_LONG_CLICK" since="16" />
 		<field name="ACTION_NEXT_AT_MOVEMENT_GRANULARITY" since="16" />
 		<field name="ACTION_NEXT_HTML_ELEMENT" since="16" />
+		<field name="ACTION_PASTE" since="18" />
 		<field name="ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY" since="16" />
 		<field name="ACTION_PREVIOUS_HTML_ELEMENT" since="16" />
 		<field name="ACTION_SCROLL_BACKWARD" since="16" />
 		<field name="ACTION_SCROLL_FORWARD" since="16" />
 		<field name="ACTION_SELECT" />
+		<field name="ACTION_SET_SELECTION" since="18" />
 		<field name="CREATOR" />
 		<field name="FOCUS_ACCESSIBILITY" since="16" />
 		<field name="FOCUS_INPUT" since="16" />
@@ -27916,8 +29376,10 @@
 		<method name="setChildDivider(Landroid/graphics/drawable/Drawable;)V" />
 		<method name="setChildIndicator(Landroid/graphics/drawable/Drawable;)V" />
 		<method name="setChildIndicatorBounds(II)V" />
+		<method name="setChildIndicatorBoundsRelative(II)V" since="18" />
 		<method name="setGroupIndicator(Landroid/graphics/drawable/Drawable;)V" />
 		<method name="setIndicatorBounds(II)V" />
+		<method name="setIndicatorBoundsRelative(II)V" since="18" />
 		<method name="setOnChildClickListener(Landroid/widget/ExpandableListView$OnChildClickListener;)V" />
 		<method name="setOnGroupClickListener(Landroid/widget/ExpandableListView$OnGroupClickListener;)V" />
 		<method name="setOnGroupCollapseListener(Landroid/widget/ExpandableListView$OnGroupCollapseListener;)V" />
@@ -28393,6 +29855,7 @@
 		<method name="canPause()Z" since="5" />
 		<method name="canSeekBackward()Z" since="5" />
 		<method name="canSeekForward()Z" since="5" />
+		<method name="getAudioSessionId()I" since="18" />
 		<method name="getBufferPercentage()I" />
 		<method name="getCurrentPosition()I" />
 		<method name="getDuration()I" />
@@ -28592,7 +30055,9 @@
 		<method name="&lt;init>(Landroid/content/Context;Landroid/util/AttributeSet;)V" />
 		<method name="&lt;init>(Landroid/content/Context;Landroid/util/AttributeSet;I)V" />
 		<method name="assignContactFromEmail(Ljava/lang/String;Z)V" />
+		<method name="assignContactFromEmail(Ljava/lang/String;ZLandroid/os/Bundle;)V" since="18" />
 		<method name="assignContactFromPhone(Ljava/lang/String;Z)V" />
+		<method name="assignContactFromPhone(Ljava/lang/String;ZLandroid/os/Bundle;)V" since="18" />
 		<method name="assignContactUri(Landroid/net/Uri;)V" />
 		<method name="setExcludeMimes([Ljava/lang/String;)V" />
 		<method name="setImageToDefault()V" since="11" />
@@ -29467,7 +30932,7 @@
 		<method name="getText1()Landroid/widget/TextView;" />
 		<method name="getText2()Landroid/widget/TextView;" />
 	</class>
-	<class name="android/widget/ValueEditor" since="17">
+	<class name="android/widget/ValueEditor" since="18">
 		<extends name="java/lang/Object" />
 		<method name="getValueModel()Landroid/util/ValueModel;" />
 		<method name="setValueModel(Landroid/util/ValueModel;)V" />
diff --git a/sdk/build_tools_source.prop_template b/sdk/build_tools_source.prop_template
new file mode 100644
index 0000000..5d62307
--- /dev/null
+++ b/sdk/build_tools_source.prop_template
@@ -0,0 +1,3 @@
+Pkg.UserSrc=false
+Pkg.Revision=${PLATFORM_SDK_VERSION}.0.0
+
diff --git a/sdk/build_tools_source.properties b/sdk/build_tools_source.properties
deleted file mode 100644
index 3aa7a95..0000000
--- a/sdk/build_tools_source.properties
+++ /dev/null
@@ -1,3 +0,0 @@
-Pkg.UserSrc=false
-Pkg.Revision=17.0.0
-
diff --git a/sdk/plat_tools_source.prop_template b/sdk/plat_tools_source.prop_template
new file mode 100644
index 0000000..5d62307
--- /dev/null
+++ b/sdk/plat_tools_source.prop_template
@@ -0,0 +1,3 @@
+Pkg.UserSrc=false
+Pkg.Revision=${PLATFORM_SDK_VERSION}.0.0
+
diff --git a/sdk/plat_tools_source.properties b/sdk/plat_tools_source.properties
deleted file mode 100644
index 3aa7a95..0000000
--- a/sdk/plat_tools_source.properties
+++ /dev/null
@@ -1,3 +0,0 @@
-Pkg.UserSrc=false
-Pkg.Revision=17.0.0
-
diff --git a/sdk/support_source.properties b/sdk/support_source.prop_template
similarity index 82%
rename from sdk/support_source.properties
rename to sdk/support_source.prop_template
index fb611ec..ba7e6fb 100644
--- a/sdk/support_source.properties
+++ b/sdk/support_source.prop_template
@@ -1,5 +1,5 @@
 Pkg.UserSrc=false
-Pkg.Revision=11
+Pkg.Revision=${PLATFORM_SDK_VERSION}
 Extra.Vendor=android
 Extra.VendorId=android
 Extra.VendorDisplay=Android
diff --git a/sdk/usbdriver_source.properties b/sdk/usbdriver_source.properties
index bff71f9..c33d032 100755
--- a/sdk/usbdriver_source.properties
+++ b/sdk/usbdriver_source.properties
@@ -1,4 +1,4 @@
-Pkg.Revision=7

+Pkg.Revision=8

 Archive.Os=WINDOWS

 Archive.Arch=ANY

 Extra.Path=usb_driver

diff --git a/testrunner/android_build.py b/testrunner/android_build.py
index a10d43b..cacd67e 100644
--- a/testrunner/android_build.py
+++ b/testrunner/android_build.py
@@ -48,6 +48,25 @@
   return root_path
 
 
+def GetHostOutDir():
+  """Returns the full pathname of out/host/arch of the Android development tree.
+
+  Assumes build environment has been properly configured by envsetup &
+  lunch/choosecombo.
+
+  Returns:
+    the absolute file path of the Android host output directory.
+  Raises:
+    AbortError: if Android host output directory could not be found.
+  """
+  host_out_path = os.getenv("ANDROID_HOST_OUT")
+  if host_out_path is None:
+    logger.Log("Error: ANDROID_HOST_OUT not defined. Please run "
+               "envsetup.sh and lunch/choosecombo")
+    raise errors.AbortError
+  return host_out_path
+
+
 def GetHostOsArch():
   """Identify the host os and arch.
 
@@ -72,10 +91,25 @@
   return (host_os, host_arch, "%s-%s" % (host_os, host_arch))
 
 
+def GetOutDir():
+  """Returns the full pathname of the "out" of the Android development tree.
+
+  Assumes build environment has been properly configured by envsetup &
+  lunch/choosecombo.
+
+  Returns:
+    the absolute file path of the Android build output directory.
+  """
+  root_path = os.getenv("OUT_DIR")
+  if root_path is None:
+    root_path = os.path.join(GetTop(), "out")
+  return root_path
+
+
 def GetHostBin():
   """Compute the full pathname to the host binary directory.
 
-  Typically $ANDROID_BUILD_TOP/out/host/linux-x86/bin.
+  Typically $ANDROID_HOST_OUT/bin.
 
   Assumes build environment has been properly configured by envsetup &
   lunch/choosecombo.
@@ -86,8 +120,7 @@
   Raises:
     AbortError: if Android host binary directory could not be found.
   """
-  (_, _, os_arch) = GetHostOsArch()
-  path = os.path.join(GetTop(), "out", "host", os_arch, "bin")
+  path = os.path.join(GetHostOutDir(), "bin")
   if not os.path.exists(path):
     logger.Log("Error: Host bin path could not be found %s" % path)
     raise errors.AbortError
@@ -139,7 +172,7 @@
 def GetHostLibraryPath():
   """Returns the full pathname to the host java library output directory.
 
-  Typically $ANDROID_BUILD_TOP/out/host/<host_os>/framework.
+  Typically $ANDROID_HOST_OUT/framework.
 
   Assumes build environment has been properly configured by envsetup &
   lunch/choosecombo.
@@ -150,8 +183,7 @@
   Raises:
     AbortError: if Android host java library directory could not be found.
   """
-  (_, _, os_arch) = GetHostOsArch()
-  path = os.path.join(GetTop(), "out", "host", os_arch, "framework")
+  path = os.path.join(GetHostOutDir(), "framework")
   if not os.path.exists(path):
     logger.Log("Error: Host library path could not be found %s" % path)
     raise errors.AbortError
diff --git a/testrunner/coverage/coverage.py b/testrunner/coverage/coverage.py
index 570527d..824f5c5 100755
--- a/testrunner/coverage/coverage.py
+++ b/testrunner/coverage/coverage.py
@@ -43,7 +43,7 @@
   _EMMA_JAR = os.path.join("external", "emma", "lib", "emma.jar")
   _TEST_COVERAGE_EXT = "ec"
   # root path of generated coverage report files, relative to Android build root
-  _COVERAGE_REPORT_PATH = os.path.join("out", "emma")
+  _COVERAGE_REPORT_PATH = "emma"
   _TARGET_DEF_FILE = "coverage_targets.xml"
   _CORE_TARGET_PATH = os.path.join("development", "testrunner",
                                    _TARGET_DEF_FILE)
@@ -53,12 +53,13 @@
                                      _TARGET_DEF_FILE)
 
   # path to root of target build intermediates
-  _TARGET_INTERMEDIATES_BASE_PATH = os.path.join("out", "target", "common",
+  _TARGET_INTERMEDIATES_BASE_PATH = os.path.join("target", "common",
                                                  "obj")
 
   def __init__(self, adb_interface):
     self._root_path = android_build.GetTop()
-    self._output_root_path = os.path.join(self._root_path,
+    self._out_path = android_build.GetOut()
+    self._output_root_path = os.path.join(self._out_path,
                                           self._COVERAGE_REPORT_PATH)
     self._emma_jar_path = os.path.join(self._root_path, self._EMMA_JAR)
     self._adb = adb_interface
@@ -78,7 +79,7 @@
       target: the CoverageTarget to use as basis for coverage calculation
       device_coverage_path: location of coverage file on device
       output_path: path to place output files in. If None will use
-        <android_root_path>/<_COVERAGE_REPORT_PATH>/<target>/<test[-qualifier]>
+        <android_out_path>/<_COVERAGE_REPORT_PATH>/<target>/<test[-qualifier]>
       test_qualifier: designates mode test was run with. e.g size=small.
         If not None, this will be used to customize output_path as shown above.
 
@@ -89,7 +90,7 @@
       report_name = test_suite_name
       if test_qualifier:
         report_name = report_name + "-" + test_qualifier
-      output_path = os.path.join(self._root_path,
+      output_path = os.path.join(self._out_path,
                                  self._COVERAGE_REPORT_PATH,
                                  target.GetName(),
                                  report_name)
@@ -153,7 +154,7 @@
 
   def _GetBuildIntermediatePath(self, target):
     return os.path.join(
-        self._root_path, self._TARGET_INTERMEDIATES_BASE_PATH, target.GetType(),
+        self._out_path, self._TARGET_INTERMEDIATES_BASE_PATH, target.GetType(),
         "%s_intermediates" % target.GetName())
 
   def _GatherSrcs(self, targets):
diff --git a/testrunner/runtest.py b/testrunner/runtest.py
index ba09d97..470dc42 100755
--- a/testrunner/runtest.py
+++ b/testrunner/runtest.py
@@ -78,13 +78,15 @@
   # regular expression to match install: statements in make output
   _RE_MAKE_INSTALL = re.compile(r'Install:\s(.+)')
 
-  # regular expression to find remote device path from a file path relative
-  # to build root
-  _RE_MAKE_INSTALL_PATH = re.compile(r'out\/target\/product\/\w+\/(.+)$')
 
   def __init__(self):
     # disable logging of timestamp
     self._root_path = android_build.GetTop()
+    out_base_name = os.path.basename(android_build.GetOutDir())
+    # regular expression to find remote device path from a file path relative
+    # to build root
+    pattern = r'' + out_base_name + r'\/target\/product\/\w+\/(.+)$'
+    self._re_make_install_path = re.compile(pattern)
     logger.SetTimestampLogging(False)
     self._adb = None
     self._known_tests = None
@@ -298,7 +300,7 @@
           self._PushInstallFileToDevice(install_path)
 
   def _PushInstallFileToDevice(self, install_path):
-    m = self._RE_MAKE_INSTALL_PATH.match(install_path)
+    m = self._re_make_install_path.match(install_path)
     if m:
       remote_path = m.group(1)
       remote_dir = os.path.dirname(remote_path)
diff --git a/testrunner/test_defs.xml b/testrunner/test_defs.xml
index 147f06c..6dfb14b 100644
--- a/testrunner/test_defs.xml
+++ b/testrunner/test_defs.xml
@@ -85,10 +85,9 @@
     coverage_target="framework"
     continuous="true" />
 
-<test name="frameworks-support-v4"
-    build_path="frameworks/support/v4/tests"
-    package="android.support.v4.content.tests"
-    coverage_target="android-support-v4"
+<test name="frameworks-support"
+    build_path="frameworks/support/tests"
+    package="android.support.tests"
     continuous="true" />
 
 <test name="core"
@@ -138,9 +137,13 @@
     description="Framework libutils unit tests." />
 
 <test-native name="libinput"
-    build_path="frameworks/base/services/input/tests"
+    build_path="frameworks/native/libs/input/tests"
     description="Framework libinput unit tests." />
 
+<test-native name="libinputservice"
+    build_path="frameworks/base/services/input/tests"
+    description="Framework libinputservice unit tests." />
+
 <test name="volley"
     build_path="frameworks/support/volley/tests"
     package="com.android.volley.tests"
@@ -188,6 +191,19 @@
     runner=".MediaFrameworkUnitTestRunner"
     coverage_target="framework" />
 
+<test name="mediaintegrationtest"
+    build_path="frameworks/base/media/tests/MediaFrameworkTest"
+    package="com.android.mediaframeworktest"
+    runner=".MediaFrameworkIntegrationTestRunner"
+    coverage_target="framework" />
+
+<test-native name="camera-client-native"
+    build_path="frameworks/av/camera/tests/"
+    description="Camera client native tests." />
+
+<test-native name="camera-hal2-native"
+    build_path="hardware/libhardware/tests/camera2"
+    description="Camera hal2 native tests." />
 <!--  end of media framework tests -->
 
 <!--  targeted framework tests -->
diff --git a/testrunner/test_defs/native_test.py b/testrunner/test_defs/native_test.py
index dc26c73..caef877 100644
--- a/testrunner/test_defs/native_test.py
+++ b/testrunner/test_defs/native_test.py
@@ -154,7 +154,7 @@
 
     Args:
       binary: basename of the file to be run. It is expected to be under
-            out/host/<os>-<arch>/bin.
+            $ANDROID_HOST_OUT/bin.
       valgrind: If True the command will be run under valgrind.
 
     Returns:
diff --git a/tutorials/MoarRam/Android.mk b/tutorials/MoarRam/Android.mk
new file mode 100644
index 0000000..c3bace9
--- /dev/null
+++ b/tutorials/MoarRam/Android.mk
@@ -0,0 +1,31 @@
+# Copyright (C) 2013 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# We only want this apk build for tests.
+LOCAL_MODULE_TAGS := optional
+
+# Include all test java files.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := MoarRam
+
+include $(BUILD_PACKAGE)
+
+include $(CLEAR_VARS)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tutorials/MoarRam/AndroidManifest.xml b/tutorials/MoarRam/AndroidManifest.xml
new file mode 100644
index 0000000..ae48ace
--- /dev/null
+++ b/tutorials/MoarRam/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.benchmark.moarram"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/ic_launcher"
+        android:label="@string/app_name"
+        android:theme="@style/AppTheme" >
+        <activity
+            android:name="com.android.benchmark.moarram.MainActivity"
+            android:label="@string/app_name" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest>
diff --git a/tutorials/MoarRam/README.txt b/tutorials/MoarRam/README.txt
new file mode 100644
index 0000000..028389b
--- /dev/null
+++ b/tutorials/MoarRam/README.txt
@@ -0,0 +1,14 @@
+This is a simple app that can be used as a tutorial or reference benchmark
+for the development of the DDMS native heap tracker feature. It contains 3
+unique paths to allocate heap chunks:
+
+1) Java_com_android_benchmark_moarram_MainActivity_add32ByteBlocksNative in
+   foo.c (libmoarram-foo.so). Each invocation will allocate 32 bytes.
+2) Java_com_android_benchmark_moarram_MainActivity_add2MByteBlocksNative in
+   bar.c (libmoarram-bar.so). Each invocation will allocate 2M bytes.
+3) Java_com_android_benchmark_moarram_MainActivity_addVariableSizedBlocksNative
+   in baz.c (libmoarram-baz.so). Each invocation will allocate 17 or 71 bytes,
+   depending on the active button in a radio group.
+
+Each allocation can be freed by clicking the corresponding free button in the
+UI.
diff --git a/tutorials/MoarRam/jni/Android.mk b/tutorials/MoarRam/jni/Android.mk
new file mode 100644
index 0000000..933cbdf
--- /dev/null
+++ b/tutorials/MoarRam/jni/Android.mk
@@ -0,0 +1,43 @@
+# Copyright (C) 2013 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.
+#
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE    := libmoarram-32
+LOCAL_SRC_FILES := foo.c
+LOCAL_SHARED_LIBRARIES += liblog
+
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE    := libmoarram-2M
+LOCAL_SRC_FILES := bar.c
+LOCAL_SHARED_LIBRARIES += liblog
+
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE    := libmoarram-17_71
+LOCAL_SRC_FILES := baz.c
+LOCAL_SHARED_LIBRARIES += liblog
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/tutorials/MoarRam/jni/bar.c b/tutorials/MoarRam/jni/bar.c
new file mode 100644
index 0000000..7b00e62
--- /dev/null
+++ b/tutorials/MoarRam/jni/bar.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2013 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.
+ *
+ */
+
+#include <jni.h>
+#include <cutils/log.h>
+
+#if defined(LOG_TAG)
+#undef LOG_TAG
+#define LOG_TAG "MOARRAM"
+#endif
+
+char *gPtr2;
+static int num2MByteBlocks;
+
+void
+Java_com_android_benchmark_moarram_MainActivity_add2MByteBlocksNative(
+    JNIEnv*  env,
+    jobject  this)
+{
+    char **ptr = malloc(2*1024*1024);
+    *ptr = gPtr2;
+    gPtr2 = (char *) ptr;
+    num2MByteBlocks++;
+    ALOGW("%d 2M-byte blocks allocated so far (just allocated %p)",
+          num2MByteBlocks, gPtr2);
+}
+
+void
+Java_com_android_benchmark_moarram_MainActivity_free2MByteBlocksNative(
+    JNIEnv*  env,
+    jobject  this)
+{
+    if (gPtr2 == NULL) {
+        ALOGW("All 2M-byte blocks are freed");
+        return;
+    }
+
+    char **ptr = (char **) gPtr2;
+    gPtr2 = *ptr;
+    free(ptr);
+    num2MByteBlocks--;
+    ALOGW("%d 2M-byte blocks allocated so far (just freed %p)",
+          num2MByteBlocks, ptr);
+}
diff --git a/tutorials/MoarRam/jni/baz.c b/tutorials/MoarRam/jni/baz.c
new file mode 100644
index 0000000..1262e40
--- /dev/null
+++ b/tutorials/MoarRam/jni/baz.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2013 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.
+ *
+ */
+
+#include <jni.h>
+#include <cutils/log.h>
+
+#if defined(LOG_TAG)
+#undef LOG_TAG
+#define LOG_TAG "MOARRAM"
+#endif
+
+char *gPtr17;
+char *gPtr71;
+static int num17ByteBlocks;
+static int num71ByteBlocks;
+
+void
+Java_com_android_benchmark_moarram_MainActivity_addVariableSizedBlocksNative(
+    JNIEnv*  env,
+    jobject  this,
+    jint id)
+{
+    int size;
+    char **gPtr;
+    char **ptr;
+    if (id == 0) {
+        size = 17;
+        gPtr = &gPtr17;
+    } else {
+        size = 71;
+        gPtr = &gPtr71;
+    }
+    ptr = malloc(size);
+    *ptr = *gPtr;
+    *gPtr = (char *) ptr;
+    ALOGW("%d %d-byte blocks allocated so far (just allocated %p)",
+          id == 0 ? ++num17ByteBlocks : ++num71ByteBlocks,
+          size, ptr);
+}
+
+void
+Java_com_android_benchmark_moarram_MainActivity_freeVariableSizedBlocksNative(
+    JNIEnv*  env,
+    jobject  this,
+    jint id)
+{
+    int size;
+    char **ptr;
+    char **gPtr;
+    if (id == 0) {
+        size = 17;
+        gPtr = &gPtr17;
+    } else {
+        size = 71;
+        gPtr = &gPtr71;
+    }
+    if (*gPtr == NULL) {
+        ALOGW("All %d-byte blocks are freed", size);
+        return;
+    }
+    ptr = (char **) *gPtr;
+    *gPtr = *ptr;
+    free(ptr);
+    ALOGW("%d %d-byte blocks allocated so far (just freed %p)",
+          id == 0 ? --num17ByteBlocks : --num71ByteBlocks,
+          size, ptr);
+}
diff --git a/tutorials/MoarRam/jni/foo.c b/tutorials/MoarRam/jni/foo.c
new file mode 100644
index 0000000..a318c74
--- /dev/null
+++ b/tutorials/MoarRam/jni/foo.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2013 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.
+ *
+ */
+
+#include <jni.h>
+#include <cutils/log.h>
+
+#if defined(LOG_TAG)
+#undef LOG_TAG
+#define LOG_TAG "MOARRAM"
+#endif
+
+char *gPtr;
+static int num32ByteBlocks;
+
+void
+Java_com_android_benchmark_moarram_MainActivity_add32ByteBlocksNative(
+    JNIEnv*  env,
+    jobject  this)
+{
+    char **ptr = malloc(32);
+    *ptr = gPtr;
+    gPtr = (char *) ptr;
+    num32ByteBlocks++;
+    ALOGW("%d 32-byte blocks allocated so far (just allocated %p)",
+          num32ByteBlocks, gPtr);
+}
+
+void
+Java_com_android_benchmark_moarram_MainActivity_free32ByteBlocksNative(
+    JNIEnv*  env,
+    jobject  this)
+{
+    if (gPtr == NULL) {
+        ALOGW("All 32-byte blocks are freed");
+        return;
+    }
+
+    char **ptr = (char **) gPtr;
+    gPtr = *ptr;
+    free(ptr);
+    num32ByteBlocks--;
+    ALOGW("%d 32-byte blocks allocated so far (just freed %p)",
+          num32ByteBlocks, ptr);
+}
diff --git a/tutorials/MoarRam/res/drawable-hdpi/ic_launcher.png b/tutorials/MoarRam/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..288b665
--- /dev/null
+++ b/tutorials/MoarRam/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/tutorials/MoarRam/res/drawable-mdpi/ic_launcher.png b/tutorials/MoarRam/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..6ae570b
--- /dev/null
+++ b/tutorials/MoarRam/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/tutorials/MoarRam/res/drawable-xhdpi/ic_launcher.png b/tutorials/MoarRam/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..d4fb7cd
--- /dev/null
+++ b/tutorials/MoarRam/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/tutorials/MoarRam/res/drawable-xxhdpi/ic_launcher.png b/tutorials/MoarRam/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..85a6081
--- /dev/null
+++ b/tutorials/MoarRam/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/tutorials/MoarRam/res/layout/activity_main.xml b/tutorials/MoarRam/res/layout/activity_main.xml
new file mode 100644
index 0000000..8319bd7
--- /dev/null
+++ b/tutorials/MoarRam/res/layout/activity_main.xml
@@ -0,0 +1,104 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="fill_parent"
+    android:paddingBottom="@dimen/activity_vertical_margin"
+    android:paddingLeft="@dimen/activity_horizontal_margin"
+    android:paddingRight="@dimen/activity_horizontal_margin"
+    android:paddingTop="@dimen/activity_vertical_margin"
+    android:orientation="vertical"
+    tools:context=".MainActivity" >
+
+    <LinearLayout
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:layout_weight="1"
+    android:orientation="horizontal">
+
+    <Button
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        android:text="@string/add_32"
+        android:layout_weight="1"
+        android:onClick="add32ByteBlocks" />
+
+    <Button
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        android:text="@string/free_32"
+        android:layout_weight="1"
+        android:onClick="free32ByteBlocks" />
+    </LinearLayout>
+
+    <LinearLayout
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:layout_weight="1"
+    android:orientation="horizontal">
+
+    <Button
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        android:text="@string/add_2m"
+        android:layout_weight="1"
+        android:onClick="add2MByteBlocks" />
+
+    <Button
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        android:text="@string/free_2m"
+        android:layout_weight="1"
+        android:onClick="free2MByteBlocks" />
+    </LinearLayout>
+
+    <LinearLayout
+    android:id="@+id/linearLayout2"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:layout_weight="1"
+    android:orientation="horizontal">
+
+    <RadioGroup
+        android:id="@+id/blockSize"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:orientation="horizontal"
+        android:gravity="center" >
+
+        <RadioButton
+        android:id="@+id/radio17"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/_17byte"
+        android:checked="true" />
+
+        <RadioButton
+        android:id="@+id/radio71"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/_71byte" />
+    </RadioGroup>
+    </LinearLayout>
+
+    <LinearLayout
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:layout_weight="1"
+    android:orientation="horizontal">
+
+    <Button
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        android:text="@string/add_variable"
+        android:layout_weight="1"
+        android:onClick="addVariableSizedBlocks" />
+
+    <Button
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        android:text="@string/free_variable"
+        android:layout_weight="1"
+        android:onClick="freeVariableSizedBlocks" />
+    </LinearLayout>
+</LinearLayout>
diff --git a/tutorials/MoarRam/res/menu/main.xml b/tutorials/MoarRam/res/menu/main.xml
new file mode 100644
index 0000000..d227c49
--- /dev/null
+++ b/tutorials/MoarRam/res/menu/main.xml
@@ -0,0 +1,9 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <item
+        android:id="@+id/action_settings"
+        android:orderInCategory="100"
+        android:showAsAction="never"
+        android:title="@string/action_settings"/>
+
+</menu>
\ No newline at end of file
diff --git a/tutorials/MoarRam/res/values-sw600dp/dimens.xml b/tutorials/MoarRam/res/values-sw600dp/dimens.xml
new file mode 100644
index 0000000..1ba777d
--- /dev/null
+++ b/tutorials/MoarRam/res/values-sw600dp/dimens.xml
@@ -0,0 +1,8 @@
+<resources>
+
+    <!--
+         Customize dimensions originally defined in res/values/dimens.xml (such as
+         screen margins) for sw600dp devices (e.g. 7" tablets) here.
+    -->
+
+</resources>
\ No newline at end of file
diff --git a/tutorials/MoarRam/res/values-sw720dp-land/dimens.xml b/tutorials/MoarRam/res/values-sw720dp-land/dimens.xml
new file mode 100644
index 0000000..eee741a
--- /dev/null
+++ b/tutorials/MoarRam/res/values-sw720dp-land/dimens.xml
@@ -0,0 +1,9 @@
+<resources>
+
+    <!--
+         Customize dimensions originally defined in res/values/dimens.xml (such as
+         screen margins) for sw720dp devices (e.g. 10" tablets) in landscape here.
+    -->
+    <dimen name="activity_horizontal_margin">128dp</dimen>
+
+</resources>
\ No newline at end of file
diff --git a/tutorials/MoarRam/res/values-v11/styles.xml b/tutorials/MoarRam/res/values-v11/styles.xml
new file mode 100644
index 0000000..541752f
--- /dev/null
+++ b/tutorials/MoarRam/res/values-v11/styles.xml
@@ -0,0 +1,11 @@
+<resources>
+
+    <!--
+        Base application theme for API 11+. This theme completely replaces
+        AppBaseTheme from res/values/styles.xml on API 11+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+        <!-- API 11 theme customizations can go here. -->
+    </style>
+
+</resources>
\ No newline at end of file
diff --git a/tutorials/MoarRam/res/values-v14/styles.xml b/tutorials/MoarRam/res/values-v14/styles.xml
new file mode 100644
index 0000000..f20e015
--- /dev/null
+++ b/tutorials/MoarRam/res/values-v14/styles.xml
@@ -0,0 +1,12 @@
+<resources>
+
+    <!--
+        Base application theme for API 14+. This theme completely replaces
+        AppBaseTheme from BOTH res/values/styles.xml and
+        res/values-v11/styles.xml on API 14+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+        <!-- API 14 theme customizations can go here. -->
+    </style>
+
+</resources>
\ No newline at end of file
diff --git a/tutorials/MoarRam/res/values/dimens.xml b/tutorials/MoarRam/res/values/dimens.xml
new file mode 100644
index 0000000..a6dd140
--- /dev/null
+++ b/tutorials/MoarRam/res/values/dimens.xml
@@ -0,0 +1,7 @@
+<resources>
+
+    <!-- Default screen margins, per the Android Design guidelines. -->
+    <dimen name="activity_horizontal_margin">16dp</dimen>
+    <dimen name="activity_vertical_margin">16dp</dimen>
+
+</resources>
\ No newline at end of file
diff --git a/tutorials/MoarRam/res/values/strings.xml b/tutorials/MoarRam/res/values/strings.xml
new file mode 100644
index 0000000..0c0031d
--- /dev/null
+++ b/tutorials/MoarRam/res/values/strings.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <string name="app_name">MoarRam</string>
+    <string name="action_settings">Settings</string>
+    <string name="hello_world">Hello world!</string>
+    <string name="enter_num">Enter a number</string>
+    <string name="add_32">Add 32 bytes</string>
+    <string name="free_32">Free 32 bytes</string>
+    <string name="add_2m">Add 2M bytes</string>
+    <string name="free_2m">Free 2M bytes</string>
+    <string name="add_variable">Add 17 or 71 bytes</string>
+    <string name="free_variable">Free 17 or 71 bytes</string>
+    <string name="_17byte">17 bytes</string>
+    <string name="_71byte">71 bytes</string>
+</resources>
diff --git a/tutorials/MoarRam/res/values/styles.xml b/tutorials/MoarRam/res/values/styles.xml
new file mode 100644
index 0000000..4a10ca4
--- /dev/null
+++ b/tutorials/MoarRam/res/values/styles.xml
@@ -0,0 +1,20 @@
+<resources>
+
+    <!--
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Light">
+        <!--
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        -->
+    </style>
+
+    <!-- Application theme. -->
+    <style name="AppTheme" parent="AppBaseTheme">
+        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+    </style>
+
+</resources>
\ No newline at end of file
diff --git a/tutorials/MoarRam/src/com/android/benchmark/moarram/MainActivity.java b/tutorials/MoarRam/src/com/android/benchmark/moarram/MainActivity.java
new file mode 100644
index 0000000..aa83b8c
--- /dev/null
+++ b/tutorials/MoarRam/src/com/android/benchmark/moarram/MainActivity.java
@@ -0,0 +1,64 @@
+package com.android.benchmark.moarram;
+
+import android.os.Bundle;
+import android.app.Activity;
+import android.view.Menu;
+import android.view.View;
+import android.widget.RadioGroup;
+
+public class MainActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        System.loadLibrary("moarram-32");
+        System.loadLibrary("moarram-2M");
+        System.loadLibrary("moarram-17_71");
+        setContentView(R.layout.activity_main);
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        getMenuInflater().inflate(R.menu.main, menu);
+        return true;
+    }
+
+    public void add32ByteBlocks(View view) {
+        add32ByteBlocksNative();
+    }
+
+    public void free32ByteBlocks(View view) {
+        free32ByteBlocksNative();
+    }
+
+    public void add2MByteBlocks(View view) {
+        add2MByteBlocksNative();
+    }
+
+    public void free2MByteBlocks(View view) {
+        free2MByteBlocksNative();
+    }
+
+    public void addVariableSizedBlocks(View view) {
+
+        RadioGroup sizeGroup = (RadioGroup) findViewById(R.id.blockSize);
+
+        int sizeId = sizeGroup.getCheckedRadioButtonId();
+        addVariableSizedBlocksNative(sizeId == R.id.radio17 ? 0 : 1);
+    }
+
+    public void freeVariableSizedBlocks(View view) {
+
+        RadioGroup sizeGroup = (RadioGroup) findViewById(R.id.blockSize);
+
+        int sizeId = sizeGroup.getCheckedRadioButtonId();
+        freeVariableSizedBlocksNative(sizeId == R.id.radio17 ? 0 : 1);
+    }
+
+    public native void add32ByteBlocksNative();
+    public native void free32ByteBlocksNative();
+    public native void add2MByteBlocksNative();
+    public native void free2MByteBlocksNative();
+    public native void addVariableSizedBlocksNative(int sizeId);
+    public native void freeVariableSizedBlocksNative(int sizeId);
+}
diff --git a/tutorials/ReverseDebug/Android.mk b/tutorials/ReverseDebug/Android.mk
new file mode 100644
index 0000000..586daf8
--- /dev/null
+++ b/tutorials/ReverseDebug/Android.mk
@@ -0,0 +1,28 @@
+# Copyright (C) 2013 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.
+
+ifneq ($(filter arm ,$(TARGET_ARCH)),)
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= main.c.arm
+
+LOCAL_CFLAGS := -std=gnu99 -O0
+
+LOCAL_MODULE := reverse_debug
+
+include $(BUILD_EXECUTABLE)
+
+endif # arm in TARGET_ARCH
diff --git a/tutorials/ReverseDebug/README.txt b/tutorials/ReverseDebug/README.txt
new file mode 100644
index 0000000..2578a4d
--- /dev/null
+++ b/tutorials/ReverseDebug/README.txt
@@ -0,0 +1,137 @@
+This is a tutorial/unittest for gdb's reverse debugging feature. It is a new
+feature that allows users to take a snapshot of the machine state, continue
+until a later stage of the program, then return to the previously recorded
+state and execute again. An ideal usage case is to help track down the reason
+why a memory location is clobbered. 
+
+In the sample below, the "clobber" function trashes a neighboring variable "p"
+on the stack next to the "values" variable, and the program will crash at
+line 42 when "p" is being dereferenced.
+
+ 18 #include <stdio.h>
+ 19 #include <stdlib.h>
+ 20 
+ 21 #define ARRAY_LENGTH 10
+ 22 
+ 23 int flag;
+ 24 
+ 25 void clobber(int *array, int size) {
+ 26     /* Make sure it clobbers something. */
+ 27     array[-1] = 0x123;
+ 28     array[size] = 0x123;
+ 29 }
+ 30 
+ 31 int main(void) {
+ 32     int values[ARRAY_LENGTH];
+ 33     int *p = (int *) malloc(sizeof(int));
+ 34     *p = 10;
+ 35 
+ 36     while (!flag) {
+ 37         sleep(1);
+ 38     }
+ 39 
+ 40     /* Set a breakpint here: "b main.c:41" */
+ 41     clobber(values, ARRAY_LENGTH);
+ 42     printf("*p = %d\n", *p);
+ 43     free(p);
+ 44 
+ 45     return 0;
+ 46 }
+
+The test program can be built/installed on the device by doing:
+
+> mmm development/tutorials/ReverseDebug
+> adb sync
+> adb shell reverse_debug
+
+In another window the following command can be used to attach to the running
+program:
+
+> gdbclient reverse_debug :5039 reverse_debug
+[1] 12802
+Attached; pid = 1842
+Listening on port 5039
+GNU gdb (GDB) 7.6
+Copyright (C) 2013 Free Software Foundation, Inc.
+License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
+This is free software: you are free to change and redistribute it.
+There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
+and "show warranty" for details.
+This GDB was configured as "--host=x86_64-linux-gnu --target=arm-linux-android".
+For bug reporting instructions, please see:
+<http://source.android.com/source/report-bugs.html>...
+Reading symbols from /usr/local/google/work/master/out/target/product/manta/symbols/system/bin/reverse_debug...done.
+Remote debugging from host 127.0.0.1
+nanosleep () at bionic/libc/arch-arm/syscalls/nanosleep.S:10
+10      mov     r7, ip
+
+====
+
+Now set a breakpoint on line 41 and set flag to 1 so that the program can
+ continue. 
+
+(gdb) b main.c:41
+Breakpoint 1 at 0xb6f174a8: file development/tutorials/ReverseDebug/main.c, line 41.
+(gdb) p flag=1
+$1 = 1
+(gdb) c
+Continuing.
+
+====
+
+Now try the new "record" command to take a snapshot of the machine state.
+
+Breakpoint 1, main () at development/tutorials/ReverseDebug/main.c:41
+41      clobber(values, ARRAY_LENGTH);
+(gdb) record
+(gdb) c
+Continuing.
+
+====
+
+Now the program crashes as expected as "p" has been clobbered. The
+"reverse-continue" command will bring the program back to line 41 and let you
+replay each instruction from there.
+
+Program received signal SIGSEGV, Segmentation fault.
+0xb6f174bc in main () at development/tutorials/ReverseDebug/main.c:42
+42      printf("*p = %d\n", *p);
+(gdb) reverse-continue
+Continuing.
+
+No more reverse-execution history.
+main () at development/tutorials/ReverseDebug/main.c:41
+41      clobber(values, ARRAY_LENGTH);
+
+
+====
+
+Now let's add a watch point at "&p" to hopefully catch the clobber on the spot:
+ 
+(gdb) watch *(&p)
+Hardware watchpoint 2: *(&p)
+(gdb) c
+Continuing.
+Hardware watchpoint 2: *(&p)
+
+====
+
+And here it is:
+
+Old value = (int *) 0xb728c020
+New value = (int *) 0x123
+0xb6f17440 in clobber (array=0xbebcaab0, size=10)
+    at development/tutorials/ReverseDebug/main.c:28
+28      array[size] = 0x123;
+
+
+===============================
+
+That said, reverse debugging on ARM is still in the infant stage. Currently
+(as of gdb 7.6) it only recognizes ARM instructions and will punt on all
+Thumb(2) instructions. To give it a try you will need to recompile your
+program in ARM mode. To do that you have to add the ".arm" suffix to the
+desired file in Android.mk:
+
+LOCAL_SRC_FILES:= main.c.arm
+
diff --git a/tutorials/ReverseDebug/main.c b/tutorials/ReverseDebug/main.c
new file mode 100644
index 0000000..5ae1890
--- /dev/null
+++ b/tutorials/ReverseDebug/main.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2013 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.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define ARRAY_LENGTH 10
+
+int flag;
+
+void clobber(int *array, int size) {
+    /* Make sure it clobbers something. */
+    array[-1] = 0x123;
+    array[size] = 0x123;
+}
+
+int main(void) {
+    int values[ARRAY_LENGTH];
+    int *p = (int *) malloc(sizeof(int));
+    *p = 10;
+
+    while (!flag) {
+        sleep(1);
+    }
+
+    /* Set a breakpint here: "b main.c:41" */
+    clobber(values, ARRAY_LENGTH);
+    printf("*p = %d\n", *p);
+    free(p);
+
+    return 0;
+}