From dff6c8722db09c334809a96c2f90e95ea44360f5 Mon Sep 17 00:00:00 2001 From: James Willcox Date: Thu, 4 Jun 2020 23:40:01 +0000 Subject: [PATCH] Bug 1641064 - Fail screenshot captures immediately if we pause the compositor r=geckoview-reviewers,agi Differential Revision: https://phabricator.services.mozilla.com/D78373 --- .../mozilla/geckoview/test/ScreenshotTest.kt | 13 ++++++++ widget/android/nsWindow.cpp | 31 +++++++++++++------ 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ScreenshotTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ScreenshotTest.kt index 72c216c01c5a..95d03095f82c 100644 --- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ScreenshotTest.kt +++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ScreenshotTest.kt @@ -27,6 +27,7 @@ import kotlin.math.max import android.graphics.BitmapFactory import android.graphics.Bitmap import androidx.test.platform.app.InstrumentationRegistry +import java.lang.IllegalStateException import java.lang.NullPointerException @@ -141,6 +142,18 @@ class ScreenshotTest : BaseSessionTest() { } } + @WithDisplay(height = SCREEN_HEIGHT, width = SCREEN_WIDTH) + @Test(expected = IllegalStateException::class) + fun capturePixelsFailsCompositorPaused() { + sessionRule.display?.let { + it.surfaceDestroyed() + val result = it.capturePixels() + it.surfaceDestroyed() + + sessionRule.waitForResult(result) + } + } + @WithDisplay(height = SCREEN_HEIGHT, width = SCREEN_WIDTH) @Test fun screenshotToBitmap() { diff --git a/widget/android/nsWindow.cpp b/widget/android/nsWindow.cpp index 68ff28adc31f..87924633283a 100644 --- a/widget/android/nsWindow.cpp +++ b/widget/android/nsWindow.cpp @@ -1037,6 +1037,20 @@ class nsWindow::LayerViewSupport final mCompositorPaused = true; child->Pause(); } + + if (LockedWindowPtr lock{mWindow}) { + while (!mCapturePixelsResults.empty()) { + auto result = + java::GeckoResult::LocalRef(mCapturePixelsResults.front().mResult); + if (result) { + result->CompleteExceptionally( + java::sdk::IllegalStateException::New( + "The compositor has detached from the session") + .Cast()); + } + mCapturePixelsResults.pop(); + } + } } void SyncResumeCompositor() { @@ -1205,22 +1219,21 @@ class nsWindow::LayerViewSupport final void RecvScreenPixels(Shmem&& aMem, const ScreenIntSize& aSize) { MOZ_ASSERT(AndroidBridge::IsJavaUiThread()); - CaptureRequest aCaptureRequest; - java::GeckoResult::LocalRef aResult = nullptr; + CaptureRequest request; + java::GeckoResult::LocalRef result = nullptr; if (LockedWindowPtr window{mWindow}) { - aCaptureRequest = mCapturePixelsResults.front(); - aResult = java::GeckoResult::LocalRef(aCaptureRequest.mResult); - if (aResult) { + request = mCapturePixelsResults.front(); + result = java::GeckoResult::LocalRef(request.mResult); + if (result) { mCapturePixelsResults.pop(); } } - if (aResult) { + if (result) { auto pixels = mozilla::jni::ByteBuffer::New( - FlipScreenPixels(aMem, aSize, aCaptureRequest.mSource, - aCaptureRequest.mOutputSize), + FlipScreenPixels(aMem, aSize, request.mSource, request.mOutputSize), aMem.Size()); - aResult->Complete(pixels); + result->Complete(pixels); } // Pixels have been copied, so Dealloc Shmem