libgui: Add plumbing for active rectangle

This change adds the plumbing to SurfaceTextureClient, BufferQueue, and
SurfaceTexture to get the active rectangle passed to the ANativeWindow to
the buffer consumer.

Change-Id: I35da0889b266327ebb079b6a7136fa3e2e8b00e6
diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h
index 6c38cde..e7fac3d 100644
--- a/include/gui/BufferQueue.h
+++ b/include/gui/BufferQueue.h
@@ -170,6 +170,7 @@
            mFrameNumber(0),
            mBuf(INVALID_BUFFER_SLOT) {
              mCrop.makeInvalid();
+             mActiveRect.makeInvalid();
          }
         // mGraphicBuffer points to the buffer allocated for this slot or is NULL
         // if no buffer has been allocated.
@@ -191,9 +192,13 @@
         // mFrameNumber is the number of the queued frame for this slot.
         uint64_t mFrameNumber;
 
-        // buf is the slot index of this buffer
+        // mBuf is the slot index of this buffer
         int mBuf;
 
+        // mActiveRect is the active rectangle for the buffer.  Pixels outside
+        // this rectangle are considered completely transparent for the purposes
+        // of window composition.
+        Rect mActiveRect;
     };
 
     // The following public functions is the consumer facing interface
@@ -297,6 +302,7 @@
           mAcquireCalled(false),
           mNeedsCleanupOnRelease(false) {
             mCrop.makeInvalid();
+            mActiveRect.makeInvalid();
         }
 
         // mGraphicBuffer points to the buffer allocated for this slot or is NULL
@@ -353,6 +359,12 @@
         // mCrop is the current crop rectangle for this buffer slot.
         Rect mCrop;
 
+        // mActiveRect is the current active rectangle for this buffer slot.
+        // Pixels outside of this rectangle are to be treated as completely
+        // transparent during window composition.  The rectangle is in buffer
+        // pixel coordinates.
+        Rect mActiveRect;
+
         // mTransform is the current transform flags for this buffer slot.
         uint32_t mTransform;
 
diff --git a/include/gui/ISurfaceTexture.h b/include/gui/ISurfaceTexture.h
index 1e33764..7abc7db 100644
--- a/include/gui/ISurfaceTexture.h
+++ b/include/gui/ISurfaceTexture.h
@@ -86,21 +86,25 @@
     // QueueBufferInput must be a POD structure
     struct QueueBufferInput {
         inline QueueBufferInput(int64_t timestamp,
-                const Rect& crop, int scalingMode, uint32_t transform)
+                const Rect& crop, int scalingMode, uint32_t transform,
+                const Rect& activeRect)
         : timestamp(timestamp), crop(crop), scalingMode(scalingMode),
-          transform(transform) { }
+          transform(transform), activeRect(activeRect) { }
         inline void deflate(int64_t* outTimestamp, Rect* outCrop,
-                int* outScalingMode, uint32_t* outTransform) const {
+                int* outScalingMode, uint32_t* outTransform,
+                Rect* outActiveRect) const {
             *outTimestamp = timestamp;
             *outCrop = crop;
             *outScalingMode = scalingMode;
             *outTransform = transform;
+            *outActiveRect = activeRect;
         }
     private:
         int64_t timestamp;
         Rect crop;
         int scalingMode;
         uint32_t transform;
+        Rect activeRect;
     };
 
     // QueueBufferOutput must be a POD structure
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index f4ed226..7540ed8 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -151,13 +151,16 @@
     // texture as returned by updateTexImage().
     GLenum getCurrentTextureTarget() const;
 
-    // getCurrentCrop returns the cropping rectangle of the current buffer
+    // getCurrentCrop returns the cropping rectangle of the current buffer.
     Rect getCurrentCrop() const;
 
-    // getCurrentTransform returns the transform of the current buffer
+    // getCurrentActiveRect returns the active rectangle of the current buffer.
+    Rect getCurrentActiveRect() const;
+
+    // getCurrentTransform returns the transform of the current buffer.
     uint32_t getCurrentTransform() const;
 
-    // getCurrentScalingMode returns the scaling mode of the current buffer
+    // getCurrentScalingMode returns the scaling mode of the current buffer.
     uint32_t getCurrentScalingMode() const;
 
     // isSynchronousMode returns whether the SurfaceTexture is currently in
@@ -270,6 +273,12 @@
     // It gets set each time updateTexImage is called.
     Rect mCurrentCrop;
 
+    // mCurrentActiveRect is the active rectangle that applies to the current
+    // texture.  It gets set each time updateTexImage is called.  All pixels
+    // outside the active rectangle are be considered completely transparent for
+    // the purpose of window composition.
+    Rect mCurrentActiveRect;
+
     // mCurrentTransform is the transform identifier for the current texture. It
     // gets set each time updateTexImage is called.
     uint32_t mCurrentTransform;
diff --git a/include/gui/SurfaceTextureClient.h b/include/gui/SurfaceTextureClient.h
index 7fd9be5..c4d4320 100644
--- a/include/gui/SurfaceTextureClient.h
+++ b/include/gui/SurfaceTextureClient.h
@@ -83,6 +83,7 @@
     int dispatchSetUsage(va_list args);
     int dispatchLock(va_list args);
     int dispatchUnlockAndPost(va_list args);
+    int dispatchSetActiveRect(va_list args);
 
 protected:
     virtual int cancelBuffer(ANativeWindowBuffer* buffer);
@@ -106,6 +107,7 @@
     virtual int setUsage(uint32_t reqUsage);
     virtual int lock(ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds);
     virtual int unlockAndPost();
+    virtual int setActiveRect(Rect const* rect);
 
     enum { NUM_BUFFER_SLOTS = BufferQueue::NUM_BUFFER_SLOTS };
     enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 };
@@ -165,6 +167,10 @@
     // buffer that gets queued. It is set by calling setTransform.
     uint32_t mTransform;
 
+    // mActiveRect is the active rectangle that will be used for the next buffer
+    // that gets queued.  It is set by calling setActiveRect.
+    Rect mActiveRect;
+
      // mDefaultWidth is default width of the buffers, regardless of the
      // native_window_set_buffers_dimensions call.
      uint32_t mDefaultWidth;
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index 39e9724..5095ebd 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -536,12 +536,19 @@
     ATRACE_CALL();
     ATRACE_BUFFER_INDEX(buf);
 
-    ST_LOGV("queueBuffer: slot=%d time=%lld crop=[%d,%d,%d,%d]", buf,
-            mSlots[buf].mTimestamp,
-            mSlots[buf].mCrop.left,
-            mSlots[buf].mCrop.top,
-            mSlots[buf].mCrop.right,
-            mSlots[buf].mCrop.bottom);
+    Rect crop;
+    uint32_t transform;
+    int scalingMode;
+    int64_t timestamp;
+    Rect activeRect;
+
+    input.deflate(&timestamp, &crop, &scalingMode, &transform,
+            &activeRect);
+
+    ST_LOGV("queueBuffer: slot=%d time=%lld crop=[%d,%d,%d,%d] "
+            "active=[%d,%d,%d,%d]", buf, timestamp, crop.left, crop.top,
+            crop.right, crop.bottom, activeRect.left, activeRect.top,
+            activeRect.right, activeRect.bottom);
 
     sp<ConsumerListener> listener;
 
@@ -590,14 +597,10 @@
             }
         }
 
-        int scalingMode;
-
-        input.deflate(
-                &mSlots[buf].mTimestamp,
-                &mSlots[buf].mCrop,
-                &scalingMode,
-                &mSlots[buf].mTransform);
-
+        mSlots[buf].mTimestamp = timestamp;
+        mSlots[buf].mCrop = crop;
+        mSlots[buf].mTransform = transform;
+        mSlots[buf].mActiveRect = activeRect;
 
         switch (scalingMode) {
             case NATIVE_WINDOW_SCALING_MODE_FREEZE:
@@ -856,6 +859,7 @@
         buffer->mFrameNumber = mSlots[buf].mFrameNumber;
         buffer->mTimestamp = mSlots[buf].mTimestamp;
         buffer->mBuf = buf;
+        buffer->mActiveRect = mSlots[buf].mActiveRect;
         mSlots[buf].mAcquireCalled = true;
 
         mSlots[buf].mBufferState = BufferSlot::ACQUIRED;
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 8141227..c103e14 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -294,6 +294,7 @@
         mCurrentTransform = item.mTransform;
         mCurrentScalingMode = item.mScalingMode;
         mCurrentTimestamp = item.mTimestamp;
+        mCurrentActiveRect = item.mActiveRect;
         computeCurrentTransformMatrix();
     } else  {
         if (err < 0) {
@@ -655,11 +656,14 @@
             outCrop.right,outCrop.bottom);
     }
 
-
-
     return outCrop;
 }
 
+Rect SurfaceTexture::getCurrentActiveRect() const {
+    Mutex::Autolock lock(mMutex);
+    return mCurrentActiveRect;
+}
+
 uint32_t SurfaceTexture::getCurrentTransform() const {
     Mutex::Autolock lock(mMutex);
     return mCurrentTransform;
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index 788524b..fdd14c8 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -78,6 +78,7 @@
     mCrop.clear();
     mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
     mTransform = 0;
+    mActiveRect.clear();
     mDefaultWidth = 0;
     mDefaultHeight = 0;
     mUserWidth = 0;
@@ -239,7 +240,7 @@
 
     ISurfaceTexture::QueueBufferOutput output;
     ISurfaceTexture::QueueBufferInput input(timestamp,
-            mCrop, mScalingMode, mTransform);
+            mCrop, mScalingMode, mTransform, mActiveRect);
     status_t err = mSurfaceTexture->queueBuffer(i, input, &output);
     if (err != OK)  {
         ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
@@ -356,6 +357,9 @@
     case NATIVE_WINDOW_API_DISCONNECT:
         res = dispatchDisconnect(args);
         break;
+    case NATIVE_WINDOW_SET_ACTIVE_RECT:
+        res = dispatchSetActiveRect(args);
+        break;
     default:
         res = NAME_NOT_FOUND;
         break;
@@ -426,6 +430,11 @@
     return setBuffersTransform(transform);
 }
 
+int SurfaceTextureClient::dispatchSetActiveRect(va_list args) {
+    android_native_rect_t const* rect = va_arg(args, android_native_rect_t*);
+    return setActiveRect(reinterpret_cast<Rect const*>(rect));
+}
+
 int SurfaceTextureClient::dispatchSetBuffersTimestamp(va_list args) {
     int64_t timestamp = va_arg(args, int64_t);
     return setBuffersTimestamp(timestamp);
@@ -502,7 +511,7 @@
     }
 
     Mutex::Autolock lock(mMutex);
-    mCrop = *rect;
+    mCrop = realRect;
     return NO_ERROR;
 }
 
@@ -600,6 +609,23 @@
     return NO_ERROR;
 }
 
+int SurfaceTextureClient::setActiveRect(Rect const* rect)
+{
+    ATRACE_CALL();
+    ALOGV("SurfaceTextureClient::setActiveRect");
+
+    Rect realRect;
+    if (rect == NULL || rect->isEmpty()) {
+        realRect.clear();
+    } else {
+        realRect = *rect;
+    }
+
+    Mutex::Autolock lock(mMutex);
+    mActiveRect = realRect;
+    return NO_ERROR;
+}
+
 int SurfaceTextureClient::setBuffersTimestamp(int64_t timestamp)
 {
     ALOGV("SurfaceTextureClient::setBuffersTimestamp");
diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp
index cfe89bc..cff4476 100644
--- a/libs/gui/tests/SurfaceTexture_test.cpp
+++ b/libs/gui/tests/SurfaceTexture_test.cpp
@@ -389,6 +389,8 @@
         mANW = mSTC;
         mTextureRenderer = new TextureRenderer(TEX_ID, mST);
         ASSERT_NO_FATAL_FAILURE(mTextureRenderer->SetUp());
+        mFW = new FrameWaiter;
+        mST->setFrameAvailableListener(mFW);
     }
 
     virtual void TearDown() {
@@ -577,6 +579,7 @@
     sp<SurfaceTextureClient> mSTC;
     sp<ANativeWindow> mANW;
     sp<TextureRenderer> mTextureRenderer;
+    sp<FrameWaiter> mFW;
 };
 
 // Fill a YV12 buffer with a multi-colored checkerboard pattern
@@ -941,9 +944,6 @@
         const TestPixel* mTestPixels;
     };
 
-    sp<FrameWaiter> fw(new FrameWaiter);
-    mST->setFrameAvailableListener(fw);
-
     sp<Thread> pt(new ProducerThread(mANW, testPixels));
     pt->run();
 
@@ -954,8 +954,8 @@
 
     // We wait for the first two frames up front so that the producer will be
     // likely to dequeue the buffer that's currently being textured from.
-    fw->waitForFrame();
-    fw->waitForFrame();
+    mFW->waitForFrame();
+    mFW->waitForFrame();
 
     for (int i = 0; i < numFrames; i++) {
         SCOPED_TRACE(String8::format("frame %d", i).string());
@@ -965,7 +965,7 @@
         // then the producer and consumer will get out of sync, which will cause
         // a deadlock.
         if (i > 1) {
-            fw->waitForFrame();
+            mFW->waitForFrame();
         }
         mST->updateTexImage();
         drawTexture();
@@ -1142,7 +1142,8 @@
 TEST_F(SurfaceTextureGLTest, DisconnectClearsCurrentTexture) {
     ASSERT_EQ(OK, mST->setSynchronousMode(true));
 
-    native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_EGL);
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(),
+            NATIVE_WINDOW_API_EGL));
 
     ANativeWindowBuffer *anb;
 
@@ -1155,16 +1156,22 @@
     EXPECT_EQ(OK,mST->updateTexImage());
     EXPECT_EQ(OK,mST->updateTexImage());
 
-    native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_EGL);
-    native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_EGL);
+    ASSERT_EQ(OK, native_window_api_disconnect(mANW.get(),
+            NATIVE_WINDOW_API_EGL));
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(),
+            NATIVE_WINDOW_API_EGL));
 
     ASSERT_EQ(OK, mST->setSynchronousMode(true));
 
-    EXPECT_EQ (OK, mANW->dequeueBuffer(mANW.get(), &anb));
+    EXPECT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &anb));
     EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb));
 
     // Will fail here if mCurrentTexture is not cleared properly
+    mFW->waitForFrame();
     EXPECT_EQ(OK,mST->updateTexImage());
+
+    ASSERT_EQ(OK, native_window_api_disconnect(mANW.get(),
+            NATIVE_WINDOW_API_EGL));
 }
 
 TEST_F(SurfaceTextureGLTest, ScaleToWindowMode) {
@@ -1179,7 +1186,8 @@
     // The consumer image size (16 x 9) ratio
     mST->setDefaultBufferSize(1280, 720);
 
-    native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU);
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(),
+            NATIVE_WINDOW_API_CPU));
 
     ANativeWindowBuffer *anb;
 
@@ -1187,11 +1195,13 @@
     ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &odd));
     EXPECT_EQ (OK, mANW->dequeueBuffer(mANW.get(), &anb));
     EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb));
+    mFW->waitForFrame();
     EXPECT_EQ(OK,mST->updateTexImage());
     Rect r = mST->getCurrentCrop();
     assertRectEq(Rect(23, 78, 123, 477), r);
 
-    native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_EGL);
+    ASSERT_EQ(OK, native_window_api_disconnect(mANW.get(),
+            NATIVE_WINDOW_API_CPU));
 }
 
 // This test ensures the scaling mode does the right thing
@@ -1219,6 +1229,7 @@
     ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &standard));
     EXPECT_EQ (OK, mANW->dequeueBuffer(mANW.get(), &anb));
     EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb));
+    mFW->waitForFrame();
     EXPECT_EQ(OK,mST->updateTexImage());
     Rect r = mST->getCurrentCrop();
     // crop should be the same as crop (same aspect ratio)
@@ -1229,6 +1240,7 @@
     ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &wide));
     EXPECT_EQ (OK, mANW->dequeueBuffer(mANW.get(), &anb));
     EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb));
+    mFW->waitForFrame();
     EXPECT_EQ(OK,mST->updateTexImage());
     r = mST->getCurrentCrop();
     // crop should be the same height, but have cropped left and right borders
@@ -1240,6 +1252,7 @@
     ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &narrow));
     EXPECT_EQ (OK, mANW->dequeueBuffer(mANW.get(), &anb));
     EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb));
+    mFW->waitForFrame();
     EXPECT_EQ(OK,mST->updateTexImage());
     r = mST->getCurrentCrop();
     // crop should be the same width, but have cropped top and bottom borders
@@ -1249,6 +1262,28 @@
     native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_CPU);
 }
 
+TEST_F(SurfaceTextureGLTest, GetCurrentActiveRectWorks) {
+    ASSERT_EQ(OK, mST->setSynchronousMode(true));
+
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(),
+            NATIVE_WINDOW_API_CPU));
+
+    ANativeWindowBuffer *anb;
+
+    android_native_rect_t odd = {23, 78, 123, 477};
+    ASSERT_EQ(OK, native_window_set_active_rect(mANW.get(), &odd));
+    EXPECT_EQ (OK, mANW->dequeueBuffer(mANW.get(), &anb));
+    EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb));
+    mFW->waitForFrame();
+    EXPECT_EQ(OK,mST->updateTexImage());
+    Rect r = mST->getCurrentCrop();
+    assertRectEq(Rect(23, 78, 123, 477), r);
+
+    ASSERT_EQ(OK, native_window_api_disconnect(mANW.get(),
+            NATIVE_WINDOW_API_CPU));
+}
+
+
 TEST_F(SurfaceTextureGLTest, AbandonUnblocksDequeueBuffer) {
     class ProducerThread : public Thread {
     public:
@@ -1304,16 +1339,14 @@
         Mutex mMutex;
     };
 
-    sp<FrameWaiter> fw(new FrameWaiter);
-    mST->setFrameAvailableListener(fw);
     ASSERT_EQ(OK, mST->setSynchronousMode(true));
     ASSERT_EQ(OK, mST->setBufferCountServer(2));
 
     sp<Thread> pt(new ProducerThread(mANW));
     pt->run();
 
-    fw->waitForFrame();
-    fw->waitForFrame();
+    mFW->waitForFrame();
+    mFW->waitForFrame();
 
     // Sleep for 100ms to allow the producer thread's dequeueBuffer call to
     // block waiting for a buffer to become available.
@@ -1471,9 +1504,6 @@
 TEST_F(SurfaceTextureGLToGLTest, EglDestroySurfaceUnrefsBuffers) {
     sp<GraphicBuffer> buffers[2];
 
-    sp<FrameWaiter> fw(new FrameWaiter);
-    mST->setFrameAvailableListener(fw);
-
     // This test requires async mode to run on a single thread.
     EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
             mProducerEglSurface, mProducerEglContext));
@@ -1493,7 +1523,7 @@
         EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
                 mEglContext));
         ASSERT_EQ(EGL_SUCCESS, eglGetError());
-        fw->waitForFrame();
+        mFW->waitForFrame();
         mST->updateTexImage();
         buffers[i] = mST->getCurrentBuffer();
     }
@@ -1519,9 +1549,6 @@
 TEST_F(SurfaceTextureGLToGLTest, EglDestroySurfaceAfterAbandonUnrefsBuffers) {
     sp<GraphicBuffer> buffers[3];
 
-    sp<FrameWaiter> fw(new FrameWaiter);
-    mST->setFrameAvailableListener(fw);
-
     // This test requires async mode to run on a single thread.
     EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
             mProducerEglSurface, mProducerEglContext));
@@ -1542,7 +1569,7 @@
         EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
                 mEglContext));
         ASSERT_EQ(EGL_SUCCESS, eglGetError());
-        fw->waitForFrame();
+        mFW->waitForFrame();
         ASSERT_EQ(NO_ERROR, mST->updateTexImage());
         buffers[i] = mST->getCurrentBuffer();
     }
@@ -2239,13 +2266,10 @@
 };
 
 TEST_F(SurfaceTextureMultiContextGLTest, UpdateFromMultipleContextsFails) {
-    sp<FrameWaiter> fw(new FrameWaiter);
-    mST->setFrameAvailableListener(fw);
-
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
-    fw->waitForFrame();
+    mFW->waitForFrame();
     ASSERT_EQ(OK, mST->updateTexImage());
 
     // Attempt to latch the texture on the secondary context.
@@ -2256,13 +2280,10 @@
 }
 
 TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextSucceeds) {
-    sp<FrameWaiter> fw(new FrameWaiter);
-    mST->setFrameAvailableListener(fw);
-
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
-    fw->waitForFrame();
+    mFW->waitForFrame();
     ASSERT_EQ(OK, mST->updateTexImage());
 
     // Detach from the primary context.
@@ -2274,13 +2295,10 @@
 
 TEST_F(SurfaceTextureMultiContextGLTest,
         DetachFromContextSucceedsAfterProducerDisconnect) {
-    sp<FrameWaiter> fw(new FrameWaiter);
-    mST->setFrameAvailableListener(fw);
-
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
-    fw->waitForFrame();
+    mFW->waitForFrame();
     ASSERT_EQ(OK, mST->updateTexImage());
 
     // Detach from the primary context.
@@ -2292,13 +2310,10 @@
 }
 
 TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWhenAbandoned) {
-    sp<FrameWaiter> fw(new FrameWaiter);
-    mST->setFrameAvailableListener(fw);
-
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
-    fw->waitForFrame();
+    mFW->waitForFrame();
     ASSERT_EQ(OK, mST->updateTexImage());
 
     // Attempt to detach from the primary context.
@@ -2307,13 +2322,10 @@
 }
 
 TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWhenDetached) {
-    sp<FrameWaiter> fw(new FrameWaiter);
-    mST->setFrameAvailableListener(fw);
-
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
-    fw->waitForFrame();
+    mFW->waitForFrame();
     ASSERT_EQ(OK, mST->updateTexImage());
 
     // Detach from the primary context.
@@ -2324,13 +2336,10 @@
 }
 
 TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWithNoDisplay) {
-    sp<FrameWaiter> fw(new FrameWaiter);
-    mST->setFrameAvailableListener(fw);
-
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
-    fw->waitForFrame();
+    mFW->waitForFrame();
     ASSERT_EQ(OK, mST->updateTexImage());
 
     // Make there be no current display.
@@ -2343,13 +2352,10 @@
 }
 
 TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWithNoContext) {
-    sp<FrameWaiter> fw(new FrameWaiter);
-    mST->setFrameAvailableListener(fw);
-
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
-    fw->waitForFrame();
+    mFW->waitForFrame();
     ASSERT_EQ(OK, mST->updateTexImage());
 
     // Make current context be incorrect.
@@ -2362,27 +2368,21 @@
 }
 
 TEST_F(SurfaceTextureMultiContextGLTest, UpdateTexImageFailsWhenDetached) {
-    sp<FrameWaiter> fw(new FrameWaiter);
-    mST->setFrameAvailableListener(fw);
-
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Detach from the primary context.
     ASSERT_EQ(OK, mST->detachFromContext());
 
     // Attempt to latch the texture contents on the primary context.
-    fw->waitForFrame();
+    mFW->waitForFrame();
     ASSERT_EQ(INVALID_OPERATION, mST->updateTexImage());
 }
 
 TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextSucceeds) {
-    sp<FrameWaiter> fw(new FrameWaiter);
-    mST->setFrameAvailableListener(fw);
-
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
-    fw->waitForFrame();
+    mFW->waitForFrame();
     ASSERT_EQ(OK, mST->updateTexImage());
 
     // Detach from the primary context.
@@ -2409,13 +2409,10 @@
 
 TEST_F(SurfaceTextureMultiContextGLTest,
         AttachToContextSucceedsAfterProducerDisconnect) {
-    sp<FrameWaiter> fw(new FrameWaiter);
-    mST->setFrameAvailableListener(fw);
-
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
-    fw->waitForFrame();
+    mFW->waitForFrame();
     ASSERT_EQ(OK, mST->updateTexImage());
 
     // Detach from the primary context.
@@ -2443,9 +2440,6 @@
 
 TEST_F(SurfaceTextureMultiContextGLTest,
         AttachToContextSucceedsBeforeUpdateTexImage) {
-    sp<FrameWaiter> fw(new FrameWaiter);
-    mST->setFrameAvailableListener(fw);
-
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Detach from the primary context.
@@ -2463,7 +2457,7 @@
     EXPECT_EQ(SECOND_TEX_ID, texBinding);
 
     // Latch the texture contents on the primary context.
-    fw->waitForFrame();
+    mFW->waitForFrame();
     ASSERT_EQ(OK, mST->updateTexImage());
 
     // Try to use the texture from the secondary context.
@@ -2476,13 +2470,10 @@
 }
 
 TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextFailsWhenAbandoned) {
-    sp<FrameWaiter> fw(new FrameWaiter);
-    mST->setFrameAvailableListener(fw);
-
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
-    fw->waitForFrame();
+    mFW->waitForFrame();
     ASSERT_EQ(OK, mST->updateTexImage());
 
     // Detach from the primary context.
@@ -2496,13 +2487,10 @@
 }
 
 TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextFailsWhenAttached) {
-    sp<FrameWaiter> fw(new FrameWaiter);
-    mST->setFrameAvailableListener(fw);
-
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
-    fw->waitForFrame();
+    mFW->waitForFrame();
     ASSERT_EQ(OK, mST->updateTexImage());
 
     // Attempt to attach to the primary context.
@@ -2511,9 +2499,6 @@
 
 TEST_F(SurfaceTextureMultiContextGLTest,
         AttachToContextFailsWhenAttachedBeforeUpdateTexImage) {
-    sp<FrameWaiter> fw(new FrameWaiter);
-    mST->setFrameAvailableListener(fw);
-
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Attempt to attach to the primary context.
@@ -2521,13 +2506,10 @@
 }
 
 TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextFailsWithNoDisplay) {
-    sp<FrameWaiter> fw(new FrameWaiter);
-    mST->setFrameAvailableListener(fw);
-
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
-    fw->waitForFrame();
+    mFW->waitForFrame();
     ASSERT_EQ(OK, mST->updateTexImage());
 
     // Detach from the primary context.
@@ -2543,13 +2525,10 @@
 }
 
 TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextSucceedsTwice) {
-    sp<FrameWaiter> fw(new FrameWaiter);
-    mST->setFrameAvailableListener(fw);
-
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
-    fw->waitForFrame();
+    mFW->waitForFrame();
     ASSERT_EQ(OK, mST->updateTexImage());
 
     // Detach from the primary context.
@@ -2584,9 +2563,6 @@
 
 TEST_F(SurfaceTextureMultiContextGLTest,
         AttachToContextSucceedsTwiceBeforeUpdateTexImage) {
-    sp<FrameWaiter> fw(new FrameWaiter);
-    mST->setFrameAvailableListener(fw);
-
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Detach from the primary context.
@@ -2611,7 +2587,7 @@
     EXPECT_EQ(THIRD_TEX_ID, texBinding);
 
     // Latch the texture contents on the tertiary context.
-    fw->waitForFrame();
+    mFW->waitForFrame();
     ASSERT_EQ(OK, mST->updateTexImage());
 
     // Try to use the texture from the tertiary context.