Merge "Handle Surface::lock errors in TextureView Bug #8689535"
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index 5c3934d..f0acba1 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -648,13 +648,19 @@
      * rectangle. Every pixel within that rectangle must be written; however
      * pixels outside the dirty rectangle will be preserved by the next call
      * to lockCanvas().
+     *
+     * This method can return null if the underlying surface texture is not
+     * available (see {@link #isAvailable()} or if the surface texture is
+     * already connected to an image producer (for instance: the camera,
+     * OpenGL, a media player, etc.)
      * 
      * @param dirty Area of the surface that will be modified.
 
      * @return A Canvas used to draw into the surface.
      * 
      * @see #lockCanvas() 
-     * @see #unlockCanvasAndPost(android.graphics.Canvas) 
+     * @see #unlockCanvasAndPost(android.graphics.Canvas)
+     * @see #isAvailable()
      */
     public Canvas lockCanvas(Rect dirty) {
         if (!isAvailable()) return null;
@@ -664,7 +670,9 @@
         }
 
         synchronized (mNativeWindowLock) {
-            nLockCanvas(mNativeWindow, mCanvas, dirty);
+            if (!nLockCanvas(mNativeWindow, mCanvas, dirty)) {
+                return null;
+            }
         }
         mSaveCount = mCanvas.save();
 
@@ -803,6 +811,6 @@
     private static native void nSetDefaultBufferSize(SurfaceTexture surfaceTexture,
             int width, int height);
 
-    private static native void nLockCanvas(int nativeWindow, Canvas canvas, Rect dirty);
+    private static native boolean nLockCanvas(int nativeWindow, Canvas canvas, Rect dirty);
     private static native void nUnlockCanvasAndPost(int nativeWindow, Canvas canvas);
 }
diff --git a/core/jni/android_view_TextureView.cpp b/core/jni/android_view_TextureView.cpp
index 5baae84..a1985bc 100644
--- a/core/jni/android_view_TextureView.cpp
+++ b/core/jni/android_view_TextureView.cpp
@@ -134,11 +134,11 @@
   SkSafeUnref(previousCanvas);
 }
 
-static void android_view_TextureView_lockCanvas(JNIEnv* env, jobject,
+static jboolean android_view_TextureView_lockCanvas(JNIEnv* env, jobject,
         jint nativeWindow, jobject canvas, jobject dirtyRect) {
 
     if (!nativeWindow) {
-        return;
+        return false;
     }
 
     ANativeWindow_Buffer buffer;
@@ -154,7 +154,8 @@
     }
 
     sp<ANativeWindow> window((ANativeWindow*) nativeWindow);
-    native_window_lock(window.get(), &buffer, &rect);
+    int32_t status = native_window_lock(window.get(), &buffer, &rect);
+    if (status) return false;
 
     ssize_t bytesCount = buffer.stride * bytesPerPixel(buffer.format);
 
@@ -184,6 +185,8 @@
         INVOKEV(dirtyRect, gRectClassInfo.set,
                 int(rect.left), int(rect.top), int(rect.right), int(rect.bottom));
     }
+
+    return true;
 }
 
 static void android_view_TextureView_unlockCanvasAndPost(JNIEnv* env, jobject,
@@ -213,7 +216,7 @@
     {   "nDestroyNativeWindow", "()V",
             (void*) android_view_TextureView_destroyNativeWindow },
 
-    {   "nLockCanvas", "(ILandroid/graphics/Canvas;Landroid/graphics/Rect;)V",
+    {   "nLockCanvas", "(ILandroid/graphics/Canvas;Landroid/graphics/Rect;)Z",
             (void*) android_view_TextureView_lockCanvas },
     {   "nUnlockCanvasAndPost", "(ILandroid/graphics/Canvas;)V",
             (void*) android_view_TextureView_unlockCanvasAndPost },
@@ -241,7 +244,8 @@
     GET_FIELD_ID(gRectClassInfo.bottom, clazz, "bottom", "I");
 
     FIND_CLASS(clazz, "android/graphics/Canvas");
-    GET_FIELD_ID(gCanvasClassInfo.mFinalizer, clazz, "mFinalizer", "Landroid/graphics/Canvas$CanvasFinalizer;");
+    GET_FIELD_ID(gCanvasClassInfo.mFinalizer, clazz, "mFinalizer",
+            "Landroid/graphics/Canvas$CanvasFinalizer;");
     GET_FIELD_ID(gCanvasClassInfo.mNativeCanvas, clazz, "mNativeCanvas", "I");
     GET_FIELD_ID(gCanvasClassInfo.mSurfaceFormat, clazz, "mSurfaceFormat", "I");