GVR Android SDK v1.140.0
diff --git a/.gitignore b/.gitignore
index 65e71c4..2fe78a1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,9 +2,11 @@
 *.iml
 .idea/
 
-# Gradle configuration.
+# Gradle build.
+.externalNativeBuild/
 .gradle/
 build/
+libraries/jni
 
 # User configuration.
 local.properties
diff --git a/apks/controller_emulator.apk b/apks/controller_emulator.apk
index ea89dbe..336b386 100644
--- a/apks/controller_emulator.apk
+++ b/apks/controller_emulator.apk
Binary files differ
diff --git a/build.gradle b/build.gradle
index 776eaac..570427e 100644
--- a/build.gradle
+++ b/build.gradle
@@ -3,10 +3,11 @@
 buildscript {
     // This configures the Gradle build system, but not the GVR components.
     repositories {
+        google()
         jcenter()
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle-experimental:0.9.3'
+        classpath 'com.android.tools.build:gradle:3.0.1'
 
         // NOTE: Do not place your application dependencies here; they belong
         // in the individual module build.gradle files
@@ -15,6 +16,7 @@
 
 allprojects {
     repositories {
+        google()
         // For GVR components, the official source of the .aars is JCenter.
         jcenter()
         maven {
@@ -33,13 +35,13 @@
 // The dependencies for NDK builds live inside the .aar files so they need to
 // be extracted before NDK targets can build.
 task extractAudioSo(type: Copy) {
-    from zipTree("${project.rootDir}/libraries/sdk-audio-1.130.0.aar")
+    from zipTree("${project.rootDir}/libraries/sdk-audio-1.140.0.aar")
     into "${project.rootDir}/libraries/"
     include "jni/**/libgvr_audio.so"
 }
 
 task extractGvrSo(type: Copy) {
-    from zipTree("${project.rootDir}/libraries/sdk-base-1.130.0.aar")
+    from zipTree("${project.rootDir}/libraries/sdk-base-1.140.0.aar")
     into "${project.rootDir}/libraries/"
     include "jni/**/libgvr.so"
 }
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index 7a3265e..c44b679 100644
--- a/gradle/wrapper/gradle-wrapper.jar
+++ b/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 354f763..0d0b041 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-bin.zip
diff --git a/libraries/headers/vr/gvr/capi/include/gvr_types.h b/libraries/headers/vr/gvr/capi/include/gvr_types.h
index c20a338..0eca488 100644
--- a/libraries/headers/vr/gvr/capi/include/gvr_types.h
+++ b/libraries/headers/vr/gvr/capi/include/gvr_types.h
@@ -254,15 +254,17 @@
 
 /// @}
 
-/// Event data associated with a system-initiated GVR_EVENT_RECENTER event. The
-/// client may wish to handle this event to provide custom recentering logic.
+/// Event data associated with a GVR_EVENT_RECENTER event, which indicates head
+/// tracking recentering. (Controller recentering is signaled separately
+/// through gvr_controller_state_get_recentered().) The client may wish to
+/// handle this event to provide custom recentering logic.
 typedef struct gvr_recenter_event_data {
   int32_t recenter_type;  // gvr_recenter_event_type
   gvr_flags recenter_event_flags;
 
-  /// The new transform that maps from "sensor" space to the recentered "start"
-  /// space. This transform can also be retrieved by querying for the
-  /// GVR_PROPERTY_RECENTER_TRANSFORM property.
+  /// The new transform that maps from headset's "sensor" space to the
+  /// recentered "start" space. This transform can also be retrieved by querying
+  /// for the GVR_PROPERTY_RECENTER_TRANSFORM property.
   gvr_mat4f start_space_from_tracking_space_transform;
 } gvr_recenter_event_data;
 
@@ -635,12 +637,12 @@
   /// Type: float
   GVR_PROPERTY_TRACKING_FLOOR_HEIGHT = 1,
 
-  /// The current transform that maps from "sensor" space to the recentered
-  /// "start" space. Apps can optionally undo or extend this transform to
-  /// perform custom recentering logic with the returned pose, but all poses
-  /// supplied during frame submission are assumed to be in start space. This
-  /// transform matches the one reported in the most
-  /// recent gvr_recenter_event_data.
+  /// The current transform that maps from headset's "sensor" space to the
+  /// recentered "start" space. Apps can optionally undo or extend this
+  /// transform to perform custom recentering logic with the SDK-provided poses,
+  /// but the SDK assumes poses supplied during frame submission are in start
+  /// space. This transform matches the one reported in the most recent
+  /// gvr_recenter_event_data.
   /// Type: gvr_mat4f
   GVR_PROPERTY_RECENTER_TRANSFORM = 2,
 
@@ -699,7 +701,9 @@
 
 /// The type of gvr_event.
 typedef enum {
-  /// Notification that a global recentering event has occurred.
+  /// Notification that head tracking has been recentered. (Note that controller
+  /// recentering is signaled separately through
+  /// gvr_controller_state_get_recentered().)
   /// Event data type: gvr_recenter_event_data
   GVR_EVENT_RECENTER = 1,
 
diff --git a/libraries/headers/vr/gvr/capi/include/gvr_version.h b/libraries/headers/vr/gvr/capi/include/gvr_version.h
index 4e30342..6a0d0ff 100644
--- a/libraries/headers/vr/gvr/capi/include/gvr_version.h
+++ b/libraries/headers/vr/gvr/capi/include/gvr_version.h
@@ -23,14 +23,14 @@
 /// A string representation of the current GVR build version. This is of
 /// the form "MAJOR.MINOR.PATCH". Note that this may differ from the runtime
 /// GVR version as reported by gvr_get_version_string().
-#define GVR_SDK_VERSION_STRING "1.130.0"
+#define GVR_SDK_VERSION_STRING "1.140.0"
 
 /// Semantic components for the current GVR build version. Note that these
 /// values may differ from the runtime GVR version as reported by
 /// gvr_get_version().
 enum {
   GVR_SDK_MAJOR_VERSION = 1,
-  GVR_SDK_MINOR_VERSION = 130,
+  GVR_SDK_MINOR_VERSION = 140,
   GVR_SDK_PATCH_VERSION = 0,
 };
 
diff --git a/libraries/sdk-audio-1.130.0.aar b/libraries/sdk-audio-1.130.0.aar
deleted file mode 100644
index e444858..0000000
--- a/libraries/sdk-audio-1.130.0.aar
+++ /dev/null
Binary files differ
diff --git a/libraries/sdk-audio-1.140.0.aar b/libraries/sdk-audio-1.140.0.aar
new file mode 100644
index 0000000..3cd99ea
--- /dev/null
+++ b/libraries/sdk-audio-1.140.0.aar
Binary files differ
diff --git a/libraries/sdk-audio-1.130.0.pom b/libraries/sdk-audio-1.140.0.pom
similarity index 91%
rename from libraries/sdk-audio-1.130.0.pom
rename to libraries/sdk-audio-1.140.0.pom
index 7e307bd..fb95f76 100644
--- a/libraries/sdk-audio-1.130.0.pom
+++ b/libraries/sdk-audio-1.140.0.pom
@@ -4,7 +4,7 @@
 
   <groupId>com.google.vr</groupId>
   <artifactId>sdk-audio</artifactId>
-  <version>1.130.0</version>
+  <version>1.140.0</version>
   <packaging>aar</packaging>
 
   <name>Google VR SDK-Audio</name>
@@ -19,7 +19,7 @@
       <groupId>com.google.vr</groupId>
       <artifactId>sdk-base</artifactId>
       <type>aar</type>
-      <version>1.130.0</version>
+      <version>1.140.0</version>
     </dependency>
   </dependencies>
 </project>
diff --git a/libraries/sdk-base-1.130.0.aar b/libraries/sdk-base-1.130.0.aar
deleted file mode 100644
index e57a3a2..0000000
--- a/libraries/sdk-base-1.130.0.aar
+++ /dev/null
Binary files differ
diff --git a/libraries/sdk-base-1.140.0.aar b/libraries/sdk-base-1.140.0.aar
new file mode 100644
index 0000000..15a73e8
--- /dev/null
+++ b/libraries/sdk-base-1.140.0.aar
Binary files differ
diff --git a/libraries/sdk-base-1.130.0.pom b/libraries/sdk-base-1.140.0.pom
similarity index 91%
rename from libraries/sdk-base-1.130.0.pom
rename to libraries/sdk-base-1.140.0.pom
index 7a2cce6..b111e98 100644
--- a/libraries/sdk-base-1.130.0.pom
+++ b/libraries/sdk-base-1.140.0.pom
@@ -4,7 +4,7 @@
 
   <groupId>com.google.vr</groupId>
   <artifactId>sdk-base</artifactId>
-  <version>1.130.0</version>
+  <version>1.140.0</version>
   <packaging>aar</packaging>
 
   <name>Google VR SDK-Base</name>
@@ -19,7 +19,7 @@
       <groupId>com.google.vr</groupId>
       <artifactId>sdk-common</artifactId>
       <type>aar</type>
-      <version>1.130.0</version>
+      <version>1.140.0</version>
     </dependency>
   </dependencies>
 </project>
diff --git a/libraries/sdk-common-1.130.0.aar b/libraries/sdk-common-1.130.0.aar
deleted file mode 100644
index ec5f8e6..0000000
--- a/libraries/sdk-common-1.130.0.aar
+++ /dev/null
Binary files differ
diff --git a/libraries/sdk-common-1.140.0.aar b/libraries/sdk-common-1.140.0.aar
new file mode 100644
index 0000000..be2fb61
--- /dev/null
+++ b/libraries/sdk-common-1.140.0.aar
Binary files differ
diff --git a/libraries/sdk-common-1.130.0.pom b/libraries/sdk-common-1.140.0.pom
similarity index 96%
rename from libraries/sdk-common-1.130.0.pom
rename to libraries/sdk-common-1.140.0.pom
index a943d42..0228bd8 100644
--- a/libraries/sdk-common-1.130.0.pom
+++ b/libraries/sdk-common-1.140.0.pom
@@ -4,7 +4,7 @@
 
   <groupId>com.google.vr</groupId>
   <artifactId>sdk-common</artifactId>
-  <version>1.130.0</version>
+  <version>1.140.0</version>
   <packaging>aar</packaging>
 
   <name>Google VR SDK-Common</name>
diff --git a/libraries/sdk-commonwidget-1.130.0.aar b/libraries/sdk-commonwidget-1.140.0.aar
similarity index 87%
rename from libraries/sdk-commonwidget-1.130.0.aar
rename to libraries/sdk-commonwidget-1.140.0.aar
index dcc9de6..fe63574 100644
--- a/libraries/sdk-commonwidget-1.130.0.aar
+++ b/libraries/sdk-commonwidget-1.140.0.aar
Binary files differ
diff --git a/libraries/sdk-commonwidget-1.130.0.pom b/libraries/sdk-commonwidget-1.140.0.pom
similarity index 91%
rename from libraries/sdk-commonwidget-1.130.0.pom
rename to libraries/sdk-commonwidget-1.140.0.pom
index 5a731fb..0a5e321 100644
--- a/libraries/sdk-commonwidget-1.130.0.pom
+++ b/libraries/sdk-commonwidget-1.140.0.pom
@@ -4,7 +4,7 @@
 
   <groupId>com.google.vr</groupId>
   <artifactId>sdk-commonwidget</artifactId>
-  <version>1.130.0</version>
+  <version>1.140.0</version>
   <packaging>aar</packaging>
 
   <name>Google VR SDK-CommonWidget</name>
@@ -19,7 +19,7 @@
       <groupId>com.google.vr</groupId>
       <artifactId>sdk-common</artifactId>
       <type>aar</type>
-      <version>1.130.0</version>
+      <version>1.140.0</version>
     </dependency>
   </dependencies>
 </project>
diff --git a/libraries/sdk-controller-1.130.0.aar b/libraries/sdk-controller-1.130.0.aar
deleted file mode 100644
index 6243253..0000000
--- a/libraries/sdk-controller-1.130.0.aar
+++ /dev/null
Binary files differ
diff --git a/libraries/sdk-controller-1.140.0.aar b/libraries/sdk-controller-1.140.0.aar
new file mode 100644
index 0000000..e6a280d
--- /dev/null
+++ b/libraries/sdk-controller-1.140.0.aar
Binary files differ
diff --git a/libraries/sdk-controller-1.130.0.pom b/libraries/sdk-controller-1.140.0.pom
similarity index 91%
rename from libraries/sdk-controller-1.130.0.pom
rename to libraries/sdk-controller-1.140.0.pom
index 717b2f7..115e2f6 100644
--- a/libraries/sdk-controller-1.130.0.pom
+++ b/libraries/sdk-controller-1.140.0.pom
@@ -4,7 +4,7 @@
 
   <groupId>com.google.vr</groupId>
   <artifactId>sdk-controller</artifactId>
-  <version>1.130.0</version>
+  <version>1.140.0</version>
   <packaging>aar</packaging>
 
   <name>Google VR SDK-Controller</name>
@@ -19,7 +19,7 @@
       <groupId>com.google.vr</groupId>
       <artifactId>sdk-base</artifactId>
       <type>aar</type>
-      <version>1.130.0</version>
+      <version>1.140.0</version>
     </dependency>
   </dependencies>
 </project>
diff --git a/libraries/sdk-panowidget-1.130.0.aar b/libraries/sdk-panowidget-1.130.0.aar
deleted file mode 100644
index ef509d1..0000000
--- a/libraries/sdk-panowidget-1.130.0.aar
+++ /dev/null
Binary files differ
diff --git a/libraries/sdk-panowidget-1.140.0.aar b/libraries/sdk-panowidget-1.140.0.aar
new file mode 100644
index 0000000..1163c45
--- /dev/null
+++ b/libraries/sdk-panowidget-1.140.0.aar
Binary files differ
diff --git a/libraries/sdk-panowidget-1.130.0.pom b/libraries/sdk-panowidget-1.140.0.pom
similarity index 91%
rename from libraries/sdk-panowidget-1.130.0.pom
rename to libraries/sdk-panowidget-1.140.0.pom
index f13fdfc..3386ea9 100644
--- a/libraries/sdk-panowidget-1.130.0.pom
+++ b/libraries/sdk-panowidget-1.140.0.pom
@@ -4,7 +4,7 @@
 
   <groupId>com.google.vr</groupId>
   <artifactId>sdk-panowidget</artifactId>
-  <version>1.130.0</version>
+  <version>1.140.0</version>
   <packaging>aar</packaging>
 
   <name>Google VR SDK-CommonWidget</name>
@@ -19,7 +19,7 @@
       <groupId>com.google.vr</groupId>
       <artifactId>sdk-commonwidget</artifactId>
       <type>aar</type>
-      <version>1.130.0</version>
+      <version>1.140.0</version>
     </dependency>
   </dependencies>
 </project>
diff --git a/libraries/sdk-videowidget-1.130.0.aar b/libraries/sdk-videowidget-1.130.0.aar
deleted file mode 100644
index 4cb4602..0000000
--- a/libraries/sdk-videowidget-1.130.0.aar
+++ /dev/null
Binary files differ
diff --git a/libraries/sdk-videowidget-1.140.0.aar b/libraries/sdk-videowidget-1.140.0.aar
new file mode 100644
index 0000000..5bc5420
--- /dev/null
+++ b/libraries/sdk-videowidget-1.140.0.aar
Binary files differ
diff --git a/libraries/sdk-videowidget-1.130.0.pom b/libraries/sdk-videowidget-1.140.0.pom
similarity index 94%
rename from libraries/sdk-videowidget-1.130.0.pom
rename to libraries/sdk-videowidget-1.140.0.pom
index 84cc3dd..23592ad 100644
--- a/libraries/sdk-videowidget-1.130.0.pom
+++ b/libraries/sdk-videowidget-1.140.0.pom
@@ -4,7 +4,7 @@
 
   <groupId>com.google.vr</groupId>
   <artifactId>sdk-videowidget</artifactId>
-  <version>1.130.0</version>
+  <version>1.140.0</version>
   <packaging>aar</packaging>
 
   <name>Google VR SDK-CommonWidget</name>
@@ -32,7 +32,7 @@
       <groupId>com.google.vr</groupId>
       <artifactId>sdk-commonwidget</artifactId>
       <type>aar</type>
-      <version>1.130.0</version>
+      <version>1.140.0</version>
     </dependency>
   </dependencies>
 </project>
diff --git a/samples/ndk-controllerpaint/CMakeLists.txt b/samples/ndk-controllerpaint/CMakeLists.txt
new file mode 100644
index 0000000..23e9ae7
--- /dev/null
+++ b/samples/ndk-controllerpaint/CMakeLists.txt
@@ -0,0 +1,33 @@
+# For more information about using CMake with Android Studio, read the
+# documentation: https://d.android.com/studio/projects/add-native-code.html
+
+cmake_minimum_required(VERSION 3.4.1)
+
+# Configure the sample code.
+file(GLOB native_srcs "src/main/jni/*.cc")
+add_library(controllerpaint_jni
+    SHARED
+    ${native_srcs})
+
+# Include the GVR headers & libraries.
+include_directories(${GVR_INCLUDE})
+
+add_library(gvr-lib SHARED IMPORTED)
+set_target_properties(
+    gvr-lib
+    PROPERTIES IMPORTED_LOCATION ${GVR_LIBPATH}/${ANDROID_ABI}/libgvr.so)
+
+# Include general Android libraries.
+find_library(android-lib android)
+find_library(EGL-lib EGL)
+find_library(GLESv2-lib GLESv2)
+find_library(log-lib log)
+
+# Build final libcontrollerpaint_jni.so
+target_link_libraries(controllerpaint_jni
+    gvr-lib
+
+    ${android-lib}
+    ${EGL-lib}
+    ${GLESv2-lib}
+    ${log-lib} )
diff --git a/samples/ndk-controllerpaint/build.gradle b/samples/ndk-controllerpaint/build.gradle
index 5f75bb6..7497381 100644
--- a/samples/ndk-controllerpaint/build.gradle
+++ b/samples/ndk-controllerpaint/build.gradle
@@ -1,59 +1,48 @@
-apply plugin: 'com.android.model.application'
+apply plugin: 'com.android.application'
 
-model {
-    android {
-        compileSdkVersion = 26
-        buildToolsVersion = "26.0.0"
-
-        defaultConfig.with {
-            applicationId = "com.google.vr.ndk.samples.controllerpaint"
-            minSdkVersion.apiLevel = 24
-            targetSdkVersion.apiLevel = 24
-            versionCode = 1
-            versionName = "1.0"
+android {
+    compileSdkVersion 26
+    defaultConfig {
+        applicationId "com.google.vr.ndk.samples.controllerpaint"
+        minSdkVersion 24
+        targetSdkVersion 24
+        versionCode 1
+        versionName "1.0"
+        externalNativeBuild {
+            cmake {
+                cppFlags "-std=gnu++11"
+                arguments "-DGVR_LIBPATH=${project.rootDir}/libraries/jni",
+                          "-DGVR_INCLUDE=${project.rootDir}/libraries/headers"
+            }
         }
-    }
-    android.buildTypes {
-        release {
-            minifyEnabled = true
-            proguardFiles.add(file('../../proguard-gvr.txt'))
+        buildTypes {
+            release {
+                minifyEnabled = true
+                proguardFiles.add(file("${project.rootDir}/proguard-gvr.txt"))
+            }
         }
-    }
-    android.ndk {
-        moduleName = "controllerpaint_jni"
-        cppFlags.add("-std=c++11")
-        cppFlags.add("-I" + file("src/main/jni").absolutePath)
-        // Add the necessary GVR headers.
-        cppFlags.add("-I" + file("${project.rootDir}/libraries/headers").absolutePath)
-
-        stl = "gnustl_shared"
-        // Add the necessary GVR .so files for all architectures.
-        ldFlags.add("-L" + file("${project.rootDir}/libraries/jni/arm64-v8a").absolutePath)
-        ldFlags.add("-L" + file("${project.rootDir}/libraries/jni/armeabi-v7a").absolutePath)
-        ldFlags.add("-L" + file("${project.rootDir}/libraries/jni/x86").absolutePath)
-
-        ldLibs.addAll(["log", "android", "EGL", "GLESv2"])
-
-        // Specific the particular .so files this sample links against.
-        ldLibs.add("gvr")
-    }
-    android.productFlavors {
-        create ("fat") {
+        ndk {
             // This sample builds all architectures by default. Note that if you
             // only want to build for a specific architecture, you need to
             // remove the appropriate lines below. You also need to remove the
             // .so files from the apk using
             // "packagingOptions {exclude('lib/armeabi-v7a/*')}" in the android
             // section.
-            ndk.abiFilters.add("arm64-v8a")
-            ndk.abiFilters.add("armeabi-v7a")
-            ndk.abiFilters.add("x86")
+            abiFilters "arm64-v8a"
+            abiFilters "armeabi-v7a"
+            abiFilters "x86"
+        }
+    }
+    externalNativeBuild {
+        cmake {
+            path "CMakeLists.txt"
         }
     }
 }
 
+
 dependencies {
-    compile 'com.google.vr:sdk-base:1.130.0'
+    compile 'com.google.vr:sdk-base:1.140.0'
 }
 
-build.dependsOn(':extractNdk')
\ No newline at end of file
+build.dependsOn(':extractNdk')
diff --git a/samples/ndk-controllerpaint/src/main/AndroidManifest.xml b/samples/ndk-controllerpaint/src/main/AndroidManifest.xml
index 414a40e..8cd84c0 100644
--- a/samples/ndk-controllerpaint/src/main/AndroidManifest.xml
+++ b/samples/ndk-controllerpaint/src/main/AndroidManifest.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
       package="com.google.vr.ndk.samples.controllerpaint"
-      android:versionCode="180130033"
-      android:versionName="1.130.0">
+      android:versionCode="180313033"
+      android:versionName="1.140.0">
 
   <!-- The Daydream SDK requires API 24+ and OpenGL ES 3.2+. -->
   <uses-sdk android:minSdkVersion="24" android:targetSdkVersion="24" />
diff --git a/samples/ndk-treasurehunt/CMakeLists.txt b/samples/ndk-treasurehunt/CMakeLists.txt
new file mode 100644
index 0000000..89427ba
--- /dev/null
+++ b/samples/ndk-treasurehunt/CMakeLists.txt
@@ -0,0 +1,39 @@
+# For more information about using CMake with Android Studio, read the
+# documentation: https://d.android.com/studio/projects/add-native-code.html
+
+cmake_minimum_required(VERSION 3.4.1)
+
+# Configure the sample code.
+file(GLOB native_srcs "src/main/jni/*.cc")
+add_library(treasurehunt_jni
+    SHARED
+    ${native_srcs})
+
+# Include the GVR headers & libraries.
+include_directories(${GVR_INCLUDE})
+
+add_library(gvr-lib SHARED IMPORTED)
+set_target_properties(
+    gvr-lib
+    PROPERTIES IMPORTED_LOCATION ${GVR_LIBPATH}/${ANDROID_ABI}/libgvr.so)
+
+add_library(gvraudio-lib SHARED IMPORTED)
+set_target_properties(
+    gvraudio-lib
+    PROPERTIES IMPORTED_LOCATION ${GVR_LIBPATH}/${ANDROID_ABI}/libgvr_audio.so)
+
+# Include general Android libraries.
+find_library(android-lib android)
+find_library(EGL-lib EGL)
+find_library(GLESv2-lib GLESv2)
+find_library(log-lib log)
+
+# Build final libtreasurehunt_jni.so
+target_link_libraries(treasurehunt_jni
+    gvr-lib
+    gvraudio-lib
+
+    ${android-lib}
+    ${EGL-lib}
+    ${GLESv2-lib}
+    ${log-lib} )
diff --git a/samples/ndk-treasurehunt/build.gradle b/samples/ndk-treasurehunt/build.gradle
index 3471887..b270db4 100644
--- a/samples/ndk-treasurehunt/build.gradle
+++ b/samples/ndk-treasurehunt/build.gradle
@@ -1,61 +1,49 @@
-apply plugin: 'com.android.model.application'
+apply plugin: 'com.android.application'
 
-model {
-    android {
-        compileSdkVersion = 26
-        buildToolsVersion = "26.0.0"
-
-        defaultConfig.with {
-            applicationId = "com.google.vr.ndk.samples.treasurehunt"
-            minSdkVersion.apiLevel = 19
-            targetSdkVersion.apiLevel = 24
-            versionCode = 1
-            versionName = "1.0"
+android {
+    compileSdkVersion 26
+    defaultConfig {
+        applicationId "com.google.vr.ndk.samples.treasurehunt"
+        minSdkVersion 19
+        targetSdkVersion 24
+        versionCode 1
+        versionName "1.0"
+        externalNativeBuild {
+            cmake {
+                cppFlags "-std=gnu++11"
+                arguments "-DGVR_LIBPATH=${project.rootDir}/libraries/jni",
+                          "-DGVR_INCLUDE=${project.rootDir}/libraries/headers"
+            }
         }
-    }
-    android.buildTypes {
-        release {
-            minifyEnabled = true
-            proguardFiles.add(file('../../proguard-gvr.txt'))
+        buildTypes {
+            release {
+                minifyEnabled = true
+                proguardFiles.add(file("${project.rootDir}/proguard-gvr.txt"))
+            }
         }
-    }
-    android.ndk {
-        moduleName = "treasurehunt_jni"
-        cppFlags.add("-std=c++11")
-        cppFlags.add("-I" + file("src/main/jni").absolutePath)
-        // Add the necessary GVR headers.
-        cppFlags.add("-I" + file("${project.rootDir}/libraries/headers").absolutePath)
-
-        stl = "gnustl_shared"
-        // Add the necessary GVR .so files for all architectures.
-        ldFlags.add("-L" + file("${project.rootDir}/libraries/jni/arm64-v8a").absolutePath)
-        ldFlags.add("-L" + file("${project.rootDir}/libraries/jni/armeabi-v7a").absolutePath)
-        ldFlags.add("-L" + file("${project.rootDir}/libraries/jni/x86").absolutePath)
-
-        ldLibs.addAll(["log", "android", "EGL", "GLESv2"])
-
-        // Specific the particular .so files this sample links against.
-        ldLibs.add("gvr")
-        ldLibs.add("gvr_audio")
-    }
-    android.productFlavors {
-        create ("fat") {
+        ndk {
             // This sample builds all architectures by default. Note that if you
             // only want to build for a specific architecture, you need to
             // remove the appropriate lines below. You also need to remove the
             // .so files from the apk using
             // "packagingOptions {exclude('lib/armeabi-v7a/*')}" in the android
             // section.
-            ndk.abiFilters.add("arm64-v8a")
-            ndk.abiFilters.add("armeabi-v7a")
-            ndk.abiFilters.add("x86")
+            abiFilters "arm64-v8a"
+            abiFilters "armeabi-v7a"
+            abiFilters "x86"
+        }
+    }
+    externalNativeBuild {
+        cmake {
+            path "CMakeLists.txt"
         }
     }
 }
 
+
 dependencies {
-    compile 'com.google.vr:sdk-audio:1.130.0'
-    compile 'com.google.vr:sdk-base:1.130.0'
+    compile 'com.google.vr:sdk-audio:1.140.0'
+    compile 'com.google.vr:sdk-base:1.140.0'
 }
 
 build.dependsOn(':extractNdk')
diff --git a/samples/ndk-treasurehunt/src/main/AndroidManifest.xml b/samples/ndk-treasurehunt/src/main/AndroidManifest.xml
index e819cf5..2ecc0ec 100644
--- a/samples/ndk-treasurehunt/src/main/AndroidManifest.xml
+++ b/samples/ndk-treasurehunt/src/main/AndroidManifest.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.google.vr.ndk.samples.treasurehunt"
-    android:versionCode="180130033"
-    android:versionName="1.130.0">
+    android:versionCode="180313033"
+    android:versionName="1.140.0">
 
   <!-- The GVR SDK requires API 19+ and OpenGL ES 2+. -->
   <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="24" />
diff --git a/samples/sdk-controllerclient/build.gradle b/samples/sdk-controllerclient/build.gradle
index 71f1b07..93163f3 100644
--- a/samples/sdk-controllerclient/build.gradle
+++ b/samples/sdk-controllerclient/build.gradle
@@ -13,30 +13,28 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-apply plugin: 'com.android.model.application'
+apply plugin: 'com.android.application'
 
-model {
-    android {
-        compileSdkVersion 26
-        buildToolsVersion "26.0.0"
+android {
+    compileSdkVersion 26
 
-        defaultConfig {
-            minSdkVersion.apiLevel 24
-            targetSdkVersion.apiLevel 24
-            versionCode 1
-            versionName "1.0"
+    defaultConfig {
+        minSdkVersion 24
+        targetSdkVersion 24
+        versionCode 1
+        versionName "1.0"
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled true
+            proguardFiles.add(file('../../proguard-gvr.txt'))
         }
 
-        buildTypes {
-            release {
-                minifyEnabled true
-                proguardFiles.add(file('../../proguard-gvr.txt'))
-            }
-        }
     }
 }
 
 dependencies {
-    compile 'com.google.vr:sdk-base:1.130.0'
-    compile 'com.google.vr:sdk-controller:1.130.0'
+    compile 'com.google.vr:sdk-base:1.140.0'
+    compile 'com.google.vr:sdk-controller:1.140.0'
 }
diff --git a/samples/sdk-controllerclient/src/main/AndroidManifest.xml b/samples/sdk-controllerclient/src/main/AndroidManifest.xml
index f16c325..7b14738 100644
--- a/samples/sdk-controllerclient/src/main/AndroidManifest.xml
+++ b/samples/sdk-controllerclient/src/main/AndroidManifest.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="com.google.vr.sdk.samples.controllerclient"
-  android:versionCode="180130033"
-  android:versionName="1.130.0">
+  android:versionCode="180313033"
+  android:versionName="1.140.0">
   <uses-sdk android:minSdkVersion="24" android:targetSdkVersion="24" />
   <uses-feature android:glEsVersion="0x00030002" android:required="true" />
 
diff --git a/samples/sdk-simplepanowidget/build.gradle b/samples/sdk-simplepanowidget/build.gradle
index 07db98e..27e1d8c 100644
--- a/samples/sdk-simplepanowidget/build.gradle
+++ b/samples/sdk-simplepanowidget/build.gradle
@@ -13,29 +13,27 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-apply plugin: 'com.android.model.application'
+apply plugin: 'com.android.application'
 
-model {
-    android {
-        compileSdkVersion 26
-        buildToolsVersion "26.0.0"
+android {
+    compileSdkVersion 26
 
-        defaultConfig {
-            minSdkVersion.apiLevel 19
-            targetSdkVersion.apiLevel 22
-            versionCode 1
-            versionName "1.0"
+    defaultConfig {
+        minSdkVersion 19
+        targetSdkVersion 22
+        versionCode 1
+        versionName "1.0"
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled true
+            proguardFiles.add(file('../../proguard-gvr.txt'))
         }
 
-        buildTypes {
-            release {
-                minifyEnabled true
-                proguardFiles.add(file('../../proguard-gvr.txt'))
-            }
-        }
     }
 }
 
 dependencies {
-    compile 'com.google.vr:sdk-panowidget:1.130.0'
+    compile 'com.google.vr:sdk-panowidget:1.140.0'
 }
diff --git a/samples/sdk-simplepanowidget/src/main/AndroidManifest.xml b/samples/sdk-simplepanowidget/src/main/AndroidManifest.xml
index 16ed5c0..a349322 100644
--- a/samples/sdk-simplepanowidget/src/main/AndroidManifest.xml
+++ b/samples/sdk-simplepanowidget/src/main/AndroidManifest.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
       package="com.google.vr.sdk.samples.simplepanowidget"
-      android:versionCode="180130033"
-      android:versionName="1.130.0">
+      android:versionCode="180313033"
+      android:versionName="1.140.0">
     <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="22" />
     <uses-feature android:glEsVersion="0x00020000" android:required="true" />
 
diff --git a/samples/sdk-simplevideowidget/build.gradle b/samples/sdk-simplevideowidget/build.gradle
index ddfdf49..edd1470 100644
--- a/samples/sdk-simplevideowidget/build.gradle
+++ b/samples/sdk-simplevideowidget/build.gradle
@@ -13,29 +13,27 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-apply plugin: 'com.android.model.application'
+apply plugin: 'com.android.application'
 
-model {
-    android {
-        compileSdkVersion 26
-        buildToolsVersion "26.0.0"
+android {
+    compileSdkVersion 26
 
-        defaultConfig {
-            minSdkVersion.apiLevel 19
-            targetSdkVersion.apiLevel 22
-            versionCode 1
-            versionName "1.0"
+    defaultConfig {
+        minSdkVersion 19
+        targetSdkVersion 22
+        versionCode 1
+        versionName "1.0"
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled true
+            proguardFiles.add(file('../../proguard-gvr.txt'))
         }
 
-        buildTypes {
-            release {
-                minifyEnabled true
-                proguardFiles.add(file('../../proguard-gvr.txt'))
-            }
-        }
     }
 }
 
 dependencies {
-    compile 'com.google.vr:sdk-videowidget:1.130.0'
+    compile 'com.google.vr:sdk-videowidget:1.140.0'
 }
diff --git a/samples/sdk-simplevideowidget/src/main/AndroidManifest.xml b/samples/sdk-simplevideowidget/src/main/AndroidManifest.xml
index 5a85720..608f917 100644
--- a/samples/sdk-simplevideowidget/src/main/AndroidManifest.xml
+++ b/samples/sdk-simplevideowidget/src/main/AndroidManifest.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
       package="com.google.vr.sdk.samples.simplevideowidget"
-      android:versionCode="180130033"
-      android:versionName="1.130.0">
+      android:versionCode="180313033"
+      android:versionName="1.140.0">
 
     <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="22" />
     <uses-feature android:glEsVersion="0x00020000" android:required="true" />
diff --git a/samples/sdk-treasurehunt/build.gradle b/samples/sdk-treasurehunt/build.gradle
index 53510f0..1655a8c 100644
--- a/samples/sdk-treasurehunt/build.gradle
+++ b/samples/sdk-treasurehunt/build.gradle
@@ -13,30 +13,28 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-apply plugin: 'com.android.model.application'
+apply plugin: 'com.android.application'
 
-model {
-    android {
-        compileSdkVersion 26
-        buildToolsVersion "26.0.0"
+android {
+    compileSdkVersion 26
 
-        defaultConfig {
-            minSdkVersion.apiLevel 19
-            targetSdkVersion.apiLevel 24
-            versionCode 1
-            versionName "1.0"
+    defaultConfig {
+        minSdkVersion 19
+        targetSdkVersion 24
+        versionCode 1
+        versionName "1.0"
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled true
+            proguardFiles.add(file('../../proguard-gvr.txt'))
         }
 
-        buildTypes {
-            release {
-                minifyEnabled true
-                proguardFiles.add(file('../../proguard-gvr.txt'))
-            }
-        }
     }
 }
 
 dependencies {
-    compile 'com.google.vr:sdk-audio:1.130.0'
-    compile 'com.google.vr:sdk-base:1.130.0'
+    compile 'com.google.vr:sdk-audio:1.140.0'
+    compile 'com.google.vr:sdk-base:1.140.0'
 }
diff --git a/samples/sdk-treasurehunt/src/main/AndroidManifest.xml b/samples/sdk-treasurehunt/src/main/AndroidManifest.xml
index 189c6e0..3e16561 100644
--- a/samples/sdk-treasurehunt/src/main/AndroidManifest.xml
+++ b/samples/sdk-treasurehunt/src/main/AndroidManifest.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
       package="com.google.vr.sdk.samples.treasurehunt"
-      android:versionCode="180130033"
-      android:versionName="1.130.0">
+      android:versionCode="180313033"
+      android:versionName="1.140.0">
 
     <!-- The GVR SDK requires API 19+ and OpenGL ES 2+. -->
     <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="24" />
diff --git a/samples/sdk-video360/build.gradle b/samples/sdk-video360/build.gradle
index 40e7711..e4a4735 100644
--- a/samples/sdk-video360/build.gradle
+++ b/samples/sdk-video360/build.gradle
@@ -13,31 +13,29 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-apply plugin: 'com.android.model.application'
+apply plugin: 'com.android.application'
 
-model {
-    android {
-        compileSdkVersion 26
-        buildToolsVersion "26.0.0"
+android {
+    compileSdkVersion 26
 
-        defaultConfig {
-            minSdkVersion.apiLevel 24
-            targetSdkVersion.apiLevel 24
-            versionCode 1
-            versionName "1.0"
+    defaultConfig {
+        minSdkVersion 24
+        targetSdkVersion 24
+        versionCode 1
+        versionName "1.0"
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled true
+            proguardFiles.add(file('../../proguard-gvr.txt'))
         }
 
-        buildTypes {
-            release {
-                minifyEnabled true
-                proguardFiles.add(file('../../proguard-gvr.txt'))
-            }
-        }
     }
 }
 
 dependencies {
     compile 'com.android.support:appcompat-v7:26.1.0'
-    compile 'com.google.vr:sdk-base:1.130.0'
-    compile 'com.google.vr:sdk-controller:1.130.0'
+    compile 'com.google.vr:sdk-base:1.140.0'
+    compile 'com.google.vr:sdk-controller:1.140.0'
 }
diff --git a/samples/sdk-video360/src/main/AndroidManifest.xml b/samples/sdk-video360/src/main/AndroidManifest.xml
index 8bffce6..938bb73 100644
--- a/samples/sdk-video360/src/main/AndroidManifest.xml
+++ b/samples/sdk-video360/src/main/AndroidManifest.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.google.vr.sdk.samples.video360"
-    android:versionCode="180130033"
-    android:versionName="1.130.0">
+    android:versionCode="180313033"
+    android:versionName="1.140.0">
 
   <!-- The VR app is Daydream-only since it uses the controller. -->
   <uses-sdk android:minSdkVersion="24" android:targetSdkVersion="24"/>
diff --git a/samples/sdk-video360/src/main/java/com/google/vr/sdk/samples/video360/VrVideoActivity.java b/samples/sdk-video360/src/main/java/com/google/vr/sdk/samples/video360/VrVideoActivity.java
index 2216550..1d7878e 100644
--- a/samples/sdk-video360/src/main/java/com/google/vr/sdk/samples/video360/VrVideoActivity.java
+++ b/samples/sdk-video360/src/main/java/com/google/vr/sdk/samples/video360/VrVideoActivity.java
@@ -189,6 +189,7 @@
       launch2dActivity();
     } else {
       // This should contain a VR UI to handle the user declining the exit request.
+      Log.e(TAG, "Declining the exit request isn't implemented in this sample.");
     }
   }
 
diff --git a/samples/sdk-videoplayer/build.gradle b/samples/sdk-videoplayer/build.gradle
index 955cac6..417d525 100644
--- a/samples/sdk-videoplayer/build.gradle
+++ b/samples/sdk-videoplayer/build.gradle
@@ -13,26 +13,24 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-apply plugin: 'com.android.model.application'
+apply plugin: 'com.android.application'
 
-model {
-    android {
-        compileSdkVersion 26
-        buildToolsVersion "26.0.0"
+android {
+    compileSdkVersion 26
 
-        defaultConfig {
-            minSdkVersion.apiLevel 24
-            targetSdkVersion.apiLevel 24
-            versionCode 1
-            versionName "1.0"
+    defaultConfig {
+        minSdkVersion 24
+        targetSdkVersion 24
+        versionCode 1
+        versionName "1.0"
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled true
+            proguardFiles.add(file('../../proguard-gvr.txt'))
         }
 
-        buildTypes {
-            release {
-                minifyEnabled true
-                proguardFiles.add(file('../../proguard-gvr.txt'))
-            }
-        }
     }
 }
 
@@ -40,6 +38,6 @@
     compile 'com.google.android.exoplayer:exoplayer:2.6.1'
     compile 'com.google.android.exoplayer:extension-gvr:2.6.1'
 
-    compile 'com.google.vr:sdk-base:1.130.0'
-    compile 'com.google.vr:sdk-common:1.130.0'
+    compile 'com.google.vr:sdk-base:1.140.0'
+    compile 'com.google.vr:sdk-common:1.140.0'
 }
diff --git a/samples/sdk-videoplayer/src/main/AndroidManifest.xml b/samples/sdk-videoplayer/src/main/AndroidManifest.xml
index 7d3f11b..46dd60b 100644
--- a/samples/sdk-videoplayer/src/main/AndroidManifest.xml
+++ b/samples/sdk-videoplayer/src/main/AndroidManifest.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.google.vr.sdk.samples.videoplayer"
-    android:versionCode="180130033"
-    android:versionName="1.130.0">
+    android:versionCode="180313033"
+    android:versionName="1.140.0">
 
     <!-- The video API works on Daydream-ready devices with Asynchronous
          Reprojection on Android N+ and OpenGL ES 3+ -->
diff --git a/samples/sdk-videoplayer/src/main/java/com/google/vr/sdk/samples/videoplayer/Settings.java b/samples/sdk-videoplayer/src/main/java/com/google/vr/sdk/samples/videoplayer/Settings.java
index 86d9245..da4f509 100644
--- a/samples/sdk-videoplayer/src/main/java/com/google/vr/sdk/samples/videoplayer/Settings.java
+++ b/samples/sdk-videoplayer/src/main/java/com/google/vr/sdk/samples/videoplayer/Settings.java
@@ -15,9 +15,9 @@
   private static final String TAG = "Settings";
 
   private static final String LOCAL_PREFERENCE_FILE = "videoplayerPrefs";
-  private static final String USE_DRM_VIDEO_SAMPLE = "use_drm_video_sample";
-  private static final String SHOW_FRAME_RATE_BAR = "show_frame_rate_bar";
-  private static final String VIDEO_LENGTH_SECONDS = "video_length_seconds";
+  public static final String USE_DRM_VIDEO_SAMPLE = "use_drm_video_sample";
+  public static final String SHOW_FRAME_RATE_BAR = "show_frame_rate_bar";
+  public static final String VIDEO_LENGTH_SECONDS = "video_length_seconds";
 
   private final Activity activity;
   // When true, a DRM-protected sample is played back in a protected compositor GL context. When
diff --git a/samples/sdk-videoplayer/src/main/java/com/google/vr/sdk/samples/videoplayer/VideoExoPlayer2.java b/samples/sdk-videoplayer/src/main/java/com/google/vr/sdk/samples/videoplayer/VideoExoPlayer2.java
index 2f5f2e5..f1938c0 100644
--- a/samples/sdk-videoplayer/src/main/java/com/google/vr/sdk/samples/videoplayer/VideoExoPlayer2.java
+++ b/samples/sdk-videoplayer/src/main/java/com/google/vr/sdk/samples/videoplayer/VideoExoPlayer2.java
@@ -198,6 +198,11 @@
     return buildDataSourceFactory(useBandwidthMeter ? BANDWIDTH_METER : null);
   }
 
+  private DataSource.Factory buildDataSourceFactory(DefaultBandwidthMeter bandwidthMeter) {
+    return new DefaultDataSourceFactory(
+        context, bandwidthMeter, buildHttpDataSourceFactory(bandwidthMeter));
+  }
+
   /**
    * Returns a new HttpDataSource factory.
    *
@@ -209,6 +214,10 @@
     return buildHttpDataSourceFactory(useBandwidthMeter ? BANDWIDTH_METER : null);
   }
 
+  private HttpDataSource.Factory buildHttpDataSourceFactory(DefaultBandwidthMeter bandwidthMeter) {
+    return new DefaultHttpDataSourceFactory(userAgent, bandwidthMeter);
+  }
+
   private DrmSessionManager<FrameworkMediaCrypto> buildDrmSessionManager(
       UUID uuid, String licenseUrl) throws UnsupportedDrmException {
     if (Util.SDK_INT < 18) {
@@ -249,15 +258,6 @@
     }
   }
 
-  private DataSource.Factory buildDataSourceFactory(DefaultBandwidthMeter bandwidthMeter) {
-    return new DefaultDataSourceFactory(
-        context, bandwidthMeter, buildHttpDataSourceFactory(bandwidthMeter));
-  }
-
-  public HttpDataSource.Factory buildHttpDataSourceFactory(DefaultBandwidthMeter bandwidthMeter) {
-    return new DefaultHttpDataSourceFactory(userAgent, bandwidthMeter);
-  }
-
   private static final class GvrRenderersFactory extends DefaultRenderersFactory {
 
     private final GvrAudioProcessor gvrAudioProcessor;
@@ -279,36 +279,41 @@
   @Override
   public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
     if (playbackState == Player.STATE_ENDED) {
-      DecoderCounters counters = player.getVideoDecoderCounters();
-      counters.ensureUpdated();
-      Log.i(TAG, "Total video frames decoded: " + counters.renderedOutputBufferCount);
+      pause();
+      Log.i(TAG, "Total video frames decoded: " + getRenderedOutputBufferCount());
     }
   }
 
+  protected int getRenderedOutputBufferCount() {
+    DecoderCounters counters = player.getVideoDecoderCounters();
+    counters.ensureUpdated();
+    return counters.renderedOutputBufferCount;
+  }
+
   @Override
   public void onLoadingChanged(boolean isLoading) {}
   @Override
   public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {}
   @Override
   public void onPlayerError(ExoPlaybackException error) {}
-  // Remove when this is part of a stable ExoPlayer release.
-  public void onPositionDiscontinuity() {}
-  // Uncomment when this is part of a stable ExoPlayer release.
-  // @Override
+
+  @Override
   public void onPositionDiscontinuity(int reason) {}
+
   @Override
   public void onRepeatModeChanged(int repeatMode) {}
-  // Uncomment when this is part of a stable ExoPlayer release.
-  // @Override
+
+  @Override
   public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {}
-  // Remove when this is part of a stable ExoPlayer release.
+
+  // Old API.
   public void onTimelineChanged(Timeline timeline, Object manifest) {}
-  // Uncomment when this is part of a stable ExoPlayer release.
-  // @Override
+  // New API.
   public void onTimelineChanged(Timeline timeline, Object manifest, int reason) {}
+
   @Override
   public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {}
-  // Uncomment when this is part of a stable ExoPlayer release
-  // @Override
+
+  @Override
   public void onSeekProcessed() {}
 }
diff --git a/samples/sdk-videoplayer/src/main/java/com/google/vr/sdk/samples/videoplayer/WatchVideoActivity.java b/samples/sdk-videoplayer/src/main/java/com/google/vr/sdk/samples/videoplayer/WatchVideoActivity.java
index 569ef9d..714fc08 100644
--- a/samples/sdk-videoplayer/src/main/java/com/google/vr/sdk/samples/videoplayer/WatchVideoActivity.java
+++ b/samples/sdk-videoplayer/src/main/java/com/google/vr/sdk/samples/videoplayer/WatchVideoActivity.java
@@ -26,6 +26,7 @@
 import android.view.MotionEvent;
 import android.view.Surface;
 import android.view.View;
+import com.google.android.exoplayer2.Format;
 import com.google.android.exoplayer2.drm.UnsupportedDrmException;
 import com.google.vr.ndk.base.AndroidCompat;
 import com.google.vr.ndk.base.GvrLayout;
@@ -53,6 +54,7 @@
   private VideoExoPlayer2 videoPlayer;
   private Settings settings;
   private boolean hasFirstFrame;
+  private int displayedFrameCount;
 
   // Transform a quad that fills the clip box at Z=0 to a 16:9 screen at Z=-4. Note that the matrix
   // is column-major, so the translation is on the last row rather than the last column in this
@@ -133,18 +135,19 @@
 
           @Override
           public void onFrameAvailable() {
+            displayedFrameCount++;
             // If this is the first frame, and the Activity is still in the foreground, signal to
             // remove the loading splash screen, and draw alpha 0 in the color buffer where the
             // video will be drawn by the GvrApi.
             if (!hasFirstFrame && videoPlayer != null) {
               surfaceView.queueEvent(
-                new Runnable() {
-                  @Override
-                  public void run() {
-                    Log.i(TAG, "Video has started playback, update renderer.");
-                    renderer.setHasVideoPlaybackStarted(true);
-                  }
-                });
+                  new Runnable() {
+                    @Override
+                    public void run() {
+                      Log.i(TAG, "Video has started playback, update renderer.");
+                      renderer.setHasVideoPlaybackStarted(true);
+                    }
+                  });
 
               hasFirstFrame = true;
             }
@@ -215,6 +218,7 @@
     } catch (UnsupportedDrmException e) {
       Log.e(TAG, "Error initializing video player", e);
     }
+    displayedFrameCount = 0;
   }
 
   @Override
@@ -317,6 +321,36 @@
   }
 
   /**
+   * Get the number of frames displayed by the ExternalSurface.
+   */
+  public int getDisplayedFrameCount() {
+    return displayedFrameCount;
+  }
+
+  /**
+   * Get the number of frames decoded by the video decoder.
+   */
+  public int getDecodedFrameCount() {
+    if (videoPlayer != null) {
+      return videoPlayer.getRenderedOutputBufferCount();
+    }
+    return 0;
+  }
+
+  /**
+   * Get the frames per second of the video source.
+   */
+  public float getVideoFrameRate() {
+    if (videoPlayer != null) {
+      Format videoFormat = videoPlayer.getPlayer().getVideoFormat();
+      if (videoFormat != null) {
+        return videoFormat.frameRate;
+      }
+    }
+    return -1;
+  }
+
+  /**
    * Returns true if video is currently playing. This method should only be called in the UI thread.
    */
   public boolean isVideoPlaying() {