Bug 922510 - Extend GonkNativeWindow to support android JB 4.2.2, r=sotaro,gps
authorPeter Chang <pchang@mozilla.com>
Fri, 18 Oct 2013 10:42:43 +0800
changeset 151332 62c49e2095d330e807b3b1a856463051707721ec
parent 151331 6838df0041b3880e43a4c103aea1bff79ae63113
child 151333 fe28224ef7193714374c6f7c7c514500b6a66691
push id25484
push userryanvm@gmail.com
push dateFri, 18 Oct 2013 19:14:25 +0000
treeherdermozilla-central@3daff401c7ab [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssotaro, gps
bugs922510
milestone27.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 922510 - Extend GonkNativeWindow to support android JB 4.2.2, r=sotaro,gps
b2g/app/Makefile.in
configure.in
content/media/omx/OmxDecoder.cpp
dom/camera/GonkCameraHwMgr.cpp
dom/camera/GonkCameraSource.cpp
widget/gonk/nativewindow/GonkBufferQueue.cpp
widget/gonk/nativewindow/GonkBufferQueue.h
widget/gonk/nativewindow/GonkConsumerBase.cpp
widget/gonk/nativewindow/GonkConsumerBase.h
widget/gonk/nativewindow/GonkNativeWindow.h
widget/gonk/nativewindow/GonkNativeWindowClient.h
widget/gonk/nativewindow/GonkNativeWindowClientJB.cpp
widget/gonk/nativewindow/GonkNativeWindowClientJB.h
widget/gonk/nativewindow/GonkNativeWindowJB.cpp
widget/gonk/nativewindow/GonkNativeWindowJB.h
widget/gonk/nativewindow/moz.build
--- a/b2g/app/Makefile.in
+++ b/b2g/app/Makefile.in
@@ -19,17 +19,17 @@ LIBS += \
   -lEGL \
   -lhardware_legacy \
   -lhardware \
   -lcutils \
   $(DEPTH)/media/libpng/$(LIB_PREFIX)mozpng.$(LIB_SUFFIX) \
   $(DEPTH)/widget/gonk/libdisplay/$(LIB_PREFIX)display.$(LIB_SUFFIX) \
   $(MOZ_ZLIB_LIBS) \
   $(NULL)
-ifeq (18,$(ANDROID_VERSION))
+ifeq ($(ANDROID_VERSION),$(findstring $(ANDROID_VERSION),17 18))
 LIBS += \
   -lgui \
   -lsuspend \
   $(NULL)
 endif
 OS_LDFLAGS += -Wl,--export-dynamic
 LOCAL_INCLUDES += -I$(topsrcdir)/widget/gonk/libdisplay
 endif
--- a/configure.in
+++ b/configure.in
@@ -222,17 +222,17 @@ if test -n "$gonkdir" ; then
     15)
         GONK_INCLUDES="-I$gonkdir/frameworks/base/opengl/include -I$gonkdir/frameworks/base/native/include -I$gonkdir/frameworks/base/include -I$gonkdir/frameworks/base/services/camera -I$gonkdir/frameworks/base/include/media/stagefright -I$gonkdir/frameworks/base/include/media/stagefright/openmax -I$gonkdir/frameworks/base/media/libstagefright/rtsp -I$gonkdir/frameworks/base/media/libstagefright/include -I$gonkdir/external/dbus -I$gonkdir/external/bluetooth/bluez/lib -I$gonkdir/dalvik/libnativehelper/include/nativehelper"
         MOZ_B2G_BT=1
         MOZ_B2G_CAMERA=1
         MOZ_OMX_DECODER=1
         AC_SUBST(MOZ_OMX_DECODER)
         MOZ_RTSP=1
         ;;
-    18)
+    17|18)
         GONK_INCLUDES="-I$gonkdir/frameworks/native/include -I$gonkdir/frameworks/av/include -I$gonkdir/frameworks/av/include/media -I$gonkdir/frameworks/av/include/camera -I$gonkdir/frameworks/native/include/media/openmax -I$gonkdir/frameworks/av/media/libstagefright/include"
         if test -d "$gonkdir/external/bluetooth/bluez"; then
             GONK_INCLUDES+=" -I$gonkdir/external/dbus -I$gonkdir/external/bluetooth/bluez/lib"
             MOZ_B2G_BT=1
         fi
         MOZ_B2G_CAMERA=1
         MOZ_OMX_DECODER=1
         AC_SUBST(MOZ_OMX_DECODER)
--- a/content/media/omx/OmxDecoder.cpp
+++ b/content/media/omx/OmxDecoder.cpp
@@ -462,17 +462,17 @@ bool OmxDecoder::AllocateMediaResources(
   // it can't connect.
   OMXClient client;
   DebugOnly<status_t> err = client.connect();
   NS_ASSERTION(err == OK, "Failed to connect to OMX in mediaserver.");
   sp<IOMX> omx = client.interface();
 
   if ((mVideoTrack != nullptr) && (mVideoSource == nullptr)) {
     mNativeWindow = new GonkNativeWindow();
-#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 18
+#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
     mNativeWindowClient = new GonkNativeWindowClient(mNativeWindow->getBufferQueue());
 #else
     mNativeWindowClient = new GonkNativeWindowClient(mNativeWindow);
 #endif
 
     // Experience with OMX codecs is that only the HW decoders are
     // worth bothering with, at least on the platforms where this code
     // is currently used, and for formats this code is currently used
--- a/dom/camera/GonkCameraHwMgr.cpp
+++ b/dom/camera/GonkCameraHwMgr.cpp
@@ -178,17 +178,17 @@ GonkCameraHardware::Init()
   DOM_CAMERA_LOGI("Sensor orientation: base=%d, offset=%d, final=%d\n", info.orientation, offset, mSensorOrientation);
 
   // Disable shutter sound in android CameraService because gaia camera app will play it
   mCamera->sendCommand(CAMERA_CMD_ENABLE_SHUTTER_SOUND, 0, 0);
 
   mNativeWindow = new GonkNativeWindow();
   mNativeWindow->setNewFrameCallback(this);
   mCamera->setListener(this);
-#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 18
+#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
   mCamera->setPreviewTexture(mNativeWindow->getBufferQueue());
 #else
   mCamera->setPreviewTexture(mNativeWindow);
 #endif
   mInitialized = true;
 }
 
 sp<GonkCameraHardware>
--- a/dom/camera/GonkCameraSource.cpp
+++ b/dom/camera/GonkCameraSource.cpp
@@ -125,17 +125,17 @@ static int32_t getColorFormat(const char
 
     if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_RGB565)) {
        return OMX_COLOR_Format16bitRGB565;
     }
 
     if (!strcmp(colorFormat, "OMX_TI_COLOR_FormatYUV420PackedSemiPlanar")) {
        return OMX_TI_COLOR_FormatYUV420PackedSemiPlanar;
     }
-#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 18
+#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
     if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_ANDROID_OPAQUE)) {
         return OMX_COLOR_FormatAndroidOpaque;
     }
 #endif
     CS_LOGE("Uknown color format (%s), please add it to "
          "GonkCameraSource::getColorFormat", colorFormat);
 
     CHECK(!"Unknown color format");
@@ -537,17 +537,17 @@ status_t GonkCameraSource::start(MetaDat
 
     mStartTimeUs = 0;
     mNumInputBuffers = 0;
     if (meta) {
         int64_t startTimeUs;
         if (meta->findInt64(kKeyTime, &startTimeUs)) {
             mStartTimeUs = startTimeUs;
         }
-#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 18
+#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
         int32_t nBuffers;
         if (meta->findInt32(kKeyNumBuffers, &nBuffers)) {
             CHECK_GT(nBuffers, 0);
             mNumInputBuffers = nBuffers;
         }
 #endif
     }
 
--- a/widget/gonk/nativewindow/GonkBufferQueue.cpp
+++ b/widget/gonk/nativewindow/GonkBufferQueue.cpp
@@ -475,20 +475,22 @@ status_t GonkBufferQueue::queueBuffer(in
     Rect crop;
     uint32_t transform;
     int scalingMode;
     int64_t timestamp;
     sp<Fence> fence;
 
     input.deflate(&timestamp, &crop, &scalingMode, &transform, &fence);
 
+#if ANDROID_VERSION >= 18
     if (fence == NULL) {
         ST_LOGE("queueBuffer: fence is NULL");
         return BAD_VALUE;
     }
+#endif
 
     ST_LOGV("queueBuffer: slot=%d time=%#llx crop=[%d,%d,%d,%d] tr=%#x "
             "scale=%s",
             buf, timestamp, crop.left, crop.top, crop.right, crop.bottom,
             transform, scalingModeName(scalingMode));
 
     sp<ConsumerListener> listener;
 
@@ -578,17 +580,22 @@ status_t GonkBufferQueue::queueBuffer(in
 
     // call back without lock held
     if (listener != 0) {
         listener->onFrameAvailable();
     }
     return NO_ERROR;
 }
 
+#if ANDROID_VERSION == 17
+void GonkBufferQueue::cancelBuffer(int buf, sp<Fence> fence) {
+#else
 void GonkBufferQueue::cancelBuffer(int buf, const sp<Fence>& fence) {
+#endif
+
     ST_LOGV("cancelBuffer: slot=%d", buf);
     Mutex::Autolock lock(mMutex);
 
     if (mAbandoned) {
         ST_LOGW("cancelBuffer: GonkBufferQueue has been abandoned!");
         return;
     }
 
@@ -596,19 +603,21 @@ void GonkBufferQueue::cancelBuffer(int b
     if (buf < 0 || buf >= maxBufferCount) {
         ST_LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
                 maxBufferCount, buf);
         return;
     } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
         ST_LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
                 buf, mSlots[buf].mBufferState);
         return;
+#if ANDROID_VERSION >= 18
     } else if (fence == NULL) {
         ST_LOGE("cancelBuffer: fence is NULL");
         return;
+#endif
     }
     mSlots[buf].mBufferState = BufferSlot::FREE;
     mSlots[buf].mFrameNumber = 0;
     mSlots[buf].mFence = fence;
     mDequeueCondition.broadcast();
 }
 
 status_t GonkBufferQueue::connect(int api, QueueBufferOutput* output) {
@@ -867,17 +876,21 @@ status_t GonkBufferQueue::acquireBuffer(
     }
 
     return NO_ERROR;
 }
 
 status_t GonkBufferQueue::releaseBuffer(int buf, const sp<Fence>& fence) {
     Mutex::Autolock _l(mMutex);
 
+#if ANDROID_VERSION == 17
+    if (buf == INVALID_BUFFER_SLOT) {
+#else
     if (buf == INVALID_BUFFER_SLOT || fence == NULL) {
+#endif
         return BAD_VALUE;
     }
 
     mSlots[buf].mFence = fence;
 
     // The buffer can now only be released if its in the acquired state
     if (mSlots[buf].mBufferState == BufferSlot::ACQUIRED) {
         mSlots[buf].mBufferState = BufferSlot::FREE;
--- a/widget/gonk/nativewindow/GonkBufferQueue.h
+++ b/widget/gonk/nativewindow/GonkBufferQueue.h
@@ -14,31 +14,43 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 #ifndef NATIVEWINDOW_GONKBUFFERQUEUE_H
 #define NATIVEWINDOW_GONKBUFFERQUEUE_H
 
 #include <gui/IGraphicBufferAlloc.h>
+#if ANDROID_VERSION == 17
+#include <gui/ISurfaceTexture.h>
+#else
 #include <gui/IGraphicBufferProducer.h>
+#endif
 
 #include <ui/Fence.h>
 #include <ui/GraphicBuffer.h>
 
 #include <utils/String8.h>
 #include <utils/Vector.h>
 #include <utils/threads.h>
 
 #include "mozilla/layers/LayersSurfaces.h"
 
+#if ANDROID_VERSION == 17
+#define IGraphicBufferProducer ISurfaceTexture
+#endif
+
 namespace android {
 // ----------------------------------------------------------------------------
 
+#if ANDROID_VERSION == 17
+class GonkBufferQueue : public BnSurfaceTexture {
+#else
 class GonkBufferQueue : public BnGraphicBufferProducer {
+#endif
     typedef mozilla::layers::SurfaceDescriptor SurfaceDescriptor;
 
 public:
     enum { MIN_UNDEQUEUED_BUFFERS = 2 };
     enum { NUM_BUFFER_SLOTS = 32 };
     enum { NO_CONNECTED_API = 0 };
     enum { INVALID_BUFFER_SLOT = -1 };
     enum { STALE_BUFFER_SLOT = 1, NO_BUFFER_AVAILABLE };
@@ -166,16 +178,23 @@ public:
     // If IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION is set, the
     // producer must discard cached GraphicBuffer references for the slot
     // returned in buf.
     // If IGraphicBufferProducer::RELEASE_ALL_BUFFERS is set, the producer
     // must discard cached GraphicBuffer references for all slots.
     //
     // In both cases, the producer will need to call requestBuffer to get a
     // GraphicBuffer handle for the returned slot.
+#if ANDROID_VERSION == 17
+    virtual status_t dequeueBuffer(int *buf, sp<Fence>& fence,
+            uint32_t width, uint32_t height, uint32_t format, uint32_t usage) {
+        return dequeueBuffer(buf, &fence, width, height, format, usage);
+    }
+#endif
+
     virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence,
             uint32_t width, uint32_t height, uint32_t format, uint32_t usage);
 
     // queueBuffer returns a filled buffer to the GonkBufferQueue.
     //
     // Additional data is provided in the QueueBufferInput struct.  Notably,
     // a timestamp must be provided for the buffer. The timestamp is in
     // nanoseconds, and must be monotonically increasing. Its other semantics
@@ -192,17 +211,21 @@ public:
     virtual status_t queueBuffer(int buf,
             const QueueBufferInput& input, QueueBufferOutput* output);
 
     // cancelBuffer returns a dequeued buffer to the GonkBufferQueue, but doesn't
     // queue it for use by the consumer.
     //
     // The buffer will not be overwritten until the fence signals.  The fence
     // will usually be the one obtained from dequeueBuffer.
+#if ANDROID_VERSION == 17
+    virtual void cancelBuffer(int buf, sp<Fence> fence);
+#else
     virtual void cancelBuffer(int buf, const sp<Fence>& fence);
+#endif
 
     // setSynchronousMode sets whether dequeueBuffer is synchronous or
     // asynchronous. In synchronous mode, dequeueBuffer blocks until
     // a buffer is available, the currently bound buffer can be dequeued and
     // queued buffers will be acquired in order.  In asynchronous mode,
     // a queued buffer may be replaced by a subsequently queued buffer.
     //
     // The default mode is asynchronous.
--- a/widget/gonk/nativewindow/GonkConsumerBase.cpp
+++ b/widget/gonk/nativewindow/GonkConsumerBase.cpp
@@ -97,17 +97,21 @@ sp<GonkBufferQueue> GonkConsumerBase::ge
 }
 
 void GonkConsumerBase::onFrameAvailable() {
     CB_LOGV("onFrameAvailable");
 
     sp<FrameAvailableListener> listener;
     { // scope for the lock
         Mutex::Autolock lock(mMutex);
+#if ANDROID_VERSION == 17
+        listener = mFrameAvailableListener;
+#else
         listener = mFrameAvailableListener.promote();
+#endif
     }
 
     if (listener != NULL) {
         CB_LOGV("actually calling onFrameAvailable");
         listener->onFrameAvailable();
     }
 }
 
@@ -146,17 +150,21 @@ void GonkConsumerBase::abandonLocked() {
         freeBufferLocked(i);
     }
     // disconnect from the GonkBufferQueue
     mBufferQueue->consumerDisconnect();
     mBufferQueue.clear();
 }
 
 void GonkConsumerBase::setFrameAvailableListener(
+#if ANDROID_VERSION == 17
+        const sp<FrameAvailableListener>& listener) {
+#else
         const wp<FrameAvailableListener>& listener) {
+#endif
     CB_LOGV("setFrameAvailableListener");
     Mutex::Autolock lock(mMutex);
     mFrameAvailableListener = listener;
 }
 
 void GonkConsumerBase::dump(String8& result) const {
     char buffer[1024];
     dump(result, "", buffer, 1024);
--- a/widget/gonk/nativewindow/GonkConsumerBase.h
+++ b/widget/gonk/nativewindow/GonkConsumerBase.h
@@ -73,17 +73,21 @@ public:
     // dump writes the current state to a string. Child classes should add
     // their state to the dump by overriding the dumpLocked method, which is
     // called by these methods after locking the mutex.
     void dump(String8& result) const;
     void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const;
 
     // setFrameAvailableListener sets the listener object that will be notified
     // when a new frame becomes available.
+#if ANDROID_VERSION == 17
+    void setFrameAvailableListener(const sp<FrameAvailableListener>& listener);
+#else
     void setFrameAvailableListener(const wp<FrameAvailableListener>& listener);
+#endif
 
 private:
     GonkConsumerBase(const GonkConsumerBase&);
     void operator=(const GonkConsumerBase&);
 
 protected:
 
     // GonkConsumerBase constructs a new GonkConsumerBase object to consume image
@@ -205,17 +209,21 @@ protected:
 
     // mName is a string used to identify the GonkConsumerBase in log messages.
     // It can be set by the setName method.
     String8 mName;
 
     // mFrameAvailableListener is the listener object that will be called when a
     // new frame becomes available. If it is not NULL it will be called from
     // queueBuffer.
+#if ANDROID_VERSION == 17
+    sp<FrameAvailableListener> mFrameAvailableListener;
+#else
     wp<FrameAvailableListener> mFrameAvailableListener;
+#endif
 
     // The GonkConsumerBase has-a GonkBufferQueue and is responsible for creating this object
     // if none is supplied
     sp<GonkBufferQueue> mBufferQueue;
 
     // mMutex is the mutex used to prevent concurrent access to the member
     // variables of GonkConsumerBase objects. It must be locked whenever the
     // member variables are accessed or when any of the *Locked methods are
--- a/widget/gonk/nativewindow/GonkNativeWindow.h
+++ b/widget/gonk/nativewindow/GonkNativeWindow.h
@@ -8,13 +8,13 @@
  *
  * 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.
  */
 
-#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >=  18
+#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
 # include "GonkNativeWindowJB.h"
 #elif defined(MOZ_WIDGET_GONK) && ANDROID_VERSION == 15
 # include "GonkNativeWindowICS.h"
 #endif
--- a/widget/gonk/nativewindow/GonkNativeWindowClient.h
+++ b/widget/gonk/nativewindow/GonkNativeWindowClient.h
@@ -8,13 +8,13 @@
  *
  * 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.
  */
 
-#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >=  18
+#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >=  17
 # include "GonkNativeWindowClientJB.h"
 #elif defined(MOZ_WIDGET_GONK) && ANDROID_VERSION == 15
 # include "GonkNativeWindowClientICS.h"
 #endif
--- a/widget/gonk/nativewindow/GonkNativeWindowClientJB.cpp
+++ b/widget/gonk/nativewindow/GonkNativeWindowClientJB.cpp
@@ -15,29 +15,33 @@
  * limitations under the License.
  */
 
 #define LOG_TAG "GonkNativeWindowClient"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 //#define LOG_NDEBUG 0
 
 #include <android/native_window.h>
+#if ANDROID_VERSION == 17
+#include <utils/Trace.h>
+#else
 #include <cutils/trace.h>
+#endif
 
 #include <binder/Parcel.h>
 #include <utils/Log.h>
 #include <ui/Fence.h>
 
 #include "GonkNativeWindowClientJB.h"
 
 namespace android {
 
 GonkNativeWindowClient::GonkNativeWindowClient(
         const sp<IGraphicBufferProducer>& bufferProducer)
-    : mGraphicBufferProducer(bufferProducer)
+    : mBufferProducer(bufferProducer)
 {
     // Initialize the ANativeWindow function pointers.
     ANativeWindow::setSwapInterval  = hook_setSwapInterval;
     ANativeWindow::dequeueBuffer    = hook_dequeueBuffer;
     ANativeWindow::cancelBuffer     = hook_cancelBuffer;
     ANativeWindow::queueBuffer      = hook_queueBuffer;
     ANativeWindow::query            = hook_query;
     ANativeWindow::perform          = hook_perform;
@@ -68,18 +72,22 @@ GonkNativeWindowClient::GonkNativeWindow
 }
 
 GonkNativeWindowClient::~GonkNativeWindowClient() {
     if (mConnectedToCpu) {
         GonkNativeWindowClient::disconnect(NATIVE_WINDOW_API_CPU);
     }
 }
 
+#if ANDROID_VERSION == 17
+sp<IGraphicBufferProducer> GonkNativeWindowClient::getISurfaceTexture() const {
+#else
 sp<IGraphicBufferProducer> GonkNativeWindowClient::getIGraphicBufferProducer() const {
-    return mGraphicBufferProducer;
+#endif
+    return mBufferProducer;
 }
 
 int GonkNativeWindowClient::hook_setSwapInterval(ANativeWindow* window, int interval) {
     GonkNativeWindowClient* c = getSelf(window);
     return c->setSwapInterval(interval);
 }
 
 int GonkNativeWindowClient::hook_dequeueBuffer(ANativeWindow* window,
@@ -102,17 +110,21 @@ int GonkNativeWindowClient::hook_queueBu
 
 int GonkNativeWindowClient::hook_dequeueBuffer_DEPRECATED(ANativeWindow* window,
         ANativeWindowBuffer** buffer) {
     GonkNativeWindowClient* c = getSelf(window);
     ANativeWindowBuffer* buf;
     int fenceFd = -1;
     int result = c->dequeueBuffer(&buf, &fenceFd);
     sp<Fence> fence(new Fence(fenceFd));
+#if ANDROID_VERSION == 17
+    int waitResult = fence->waitForever(1000, "dequeueBuffer_DEPRECATED");
+#else
     int waitResult = fence->waitForever("dequeueBuffer_DEPRECATED");
+#endif
     if (waitResult != OK) {
         ALOGE("dequeueBuffer_DEPRECATED: Fence::wait returned an error: %d",
                 waitResult);
         c->cancelBuffer(buf, -1);
         return waitResult;
     }
     *buffer = buf;
     return result;
@@ -156,46 +168,53 @@ int GonkNativeWindowClient::setSwapInter
     // Although we don't have to, we apply the same logic here.
 
     if (interval < minSwapInterval)
         interval = minSwapInterval;
 
     if (interval > maxSwapInterval)
         interval = maxSwapInterval;
 
-    status_t res = mGraphicBufferProducer->setSynchronousMode(interval ? true : false);
+    status_t res = mBufferProducer->setSynchronousMode(interval ? true : false);
 
     return res;
 }
 
 int GonkNativeWindowClient::dequeueBuffer(android_native_buffer_t** buffer,
         int* fenceFd) {
     ALOGV("GonkNativeWindowClient::dequeueBuffer");
     Mutex::Autolock lock(mMutex);
     int buf = -1;
     int reqW = mReqWidth ? mReqWidth : mUserWidth;
     int reqH = mReqHeight ? mReqHeight : mUserHeight;
     sp<Fence> fence;
-    status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence,
+#if ANDROID_VERSION == 17
+    status_t result = mBufferProducer->dequeueBuffer(&buf, fence,
             reqW, reqH, mReqFormat, mReqUsage);
+#else
+    status_t result = mBufferProducer->dequeueBuffer(&buf, &fence,
+            reqW, reqH, mReqFormat, mReqUsage);
+#endif
+
     if (result < 0) {
-        ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer(%d, %d, %d, %d)"
+        ALOGV("dequeueBuffer: dequeueBuffer(%d, %d, %d, %d)"
              "failed: %d", mReqWidth, mReqHeight, mReqFormat, mReqUsage,
              result);
         return result;
     }
     sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
     if (result & IGraphicBufferProducer::RELEASE_ALL_BUFFERS) {
         freeAllBuffers();
     }
 
     if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) {
-        result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);
+        result = mBufferProducer->requestBuffer(buf, &gbuf);
+
         if (result != NO_ERROR) {
-            ALOGE("dequeueBuffer: IGraphicBufferProducer::requestBuffer failed: %d",
+            ALOGE("dequeueBuffer: requestBuffer failed: %d",
                     result);
             return result;
         }
     }
 
     if (fence->isValid()) {
         *fenceFd = fence->dup();
         if (*fenceFd == -1) {
@@ -216,17 +235,17 @@ int GonkNativeWindowClient::cancelBuffer
         int fenceFd) {
     ALOGV("GonkNativeWindowClient::cancelBuffer");
     Mutex::Autolock lock(mMutex);
     int i = getSlotFromBufferLocked(buffer);
     if (i < 0) {
         return i;
     }
     sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
-    mGraphicBufferProducer->cancelBuffer(i, fence);
+    mBufferProducer->cancelBuffer(i, fence);
     return OK;
 }
 
 int GonkNativeWindowClient::getSlotFromBufferLocked(
         android_native_buffer_t* buffer) const {
     bool dumpedState = false;
     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
         if (mSlots[i].buffer != NULL &&
@@ -264,17 +283,17 @@ int GonkNativeWindowClient::queueBuffer(
     // Make sure the crop rectangle is entirely inside the buffer.
     Rect crop;
     mCrop.intersect(Rect(buffer->width, buffer->height), &crop);
 
     sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
     IGraphicBufferProducer::QueueBufferOutput output;
     IGraphicBufferProducer::QueueBufferInput input(timestamp, crop, mScalingMode,
             mTransform, fence);
-    status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);
+    status_t err = mBufferProducer->queueBuffer(i, input, &output);
     if (err != OK)  {
         ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
     }
     uint32_t numPendingBuffers = 0;
     output.deflate(&mDefaultWidth, &mDefaultHeight, &mTransformHint,
             &numPendingBuffers);
 
     mConsumerRunningBehind = (numPendingBuffers >= 2);
@@ -291,50 +310,55 @@ int GonkNativeWindowClient::query(int wh
                 if (mReqFormat) {
                     *value = mReqFormat;
                     return NO_ERROR;
                 }
                 break;
             case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: {
                 //sp<ISurfaceComposer> composer(
                 //        ComposerService::getComposerService());
-                //if (composer->authenticateSurfaceTexture(mGraphicBufferProducer)) {
+                //if (composer->authenticateSurfaceTexture(mBufferProducer)) {
                 //    *value = 1;
                 //} else {
                     *value = 0;
                 //}
                 return NO_ERROR;
             }
             case NATIVE_WINDOW_CONCRETE_TYPE:
+#if ANDROID_VERSION == 17
+                *value = NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT;
+#else
                 *value = NATIVE_WINDOW_SURFACE;
+#endif
                 return NO_ERROR;
             case NATIVE_WINDOW_DEFAULT_WIDTH:
                 *value = mUserWidth ? mUserWidth : mDefaultWidth;
                 return NO_ERROR;
             case NATIVE_WINDOW_DEFAULT_HEIGHT:
                 *value = mUserHeight ? mUserHeight : mDefaultHeight;
                 return NO_ERROR;
             case NATIVE_WINDOW_TRANSFORM_HINT:
                 *value = mTransformHint;
                 return NO_ERROR;
             case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: {
                 status_t err = NO_ERROR;
                 if (!mConsumerRunningBehind) {
                     *value = 0;
                 } else {
-                    err = mGraphicBufferProducer->query(what, value);
+                    err = mBufferProducer->query(what, value);
                     if (err == NO_ERROR) {
                         mConsumerRunningBehind = *value;
                     }
                 }
                 return err;
             }
         }
     }
-    return mGraphicBufferProducer->query(what, value);
+
+    return mBufferProducer->query(what, value);
 }
 
 int GonkNativeWindowClient::perform(int operation, va_list args)
 {
     int res = NO_ERROR;
     switch (operation) {
     case NATIVE_WINDOW_CONNECT:
         // deprecated. must return NO_ERROR.
@@ -469,34 +493,35 @@ int GonkNativeWindowClient::dispatchUnlo
     return unlockAndPost();
 }
 
 
 int GonkNativeWindowClient::connect(int api) {
     ALOGV("GonkNativeWindowClient::connect");
     Mutex::Autolock lock(mMutex);
     IGraphicBufferProducer::QueueBufferOutput output;
-    int err = mGraphicBufferProducer->connect(api, &output);
+    int err = mBufferProducer->connect(api, &output);
     if (err == NO_ERROR) {
         uint32_t numPendingBuffers = 0;
         output.deflate(&mDefaultWidth, &mDefaultHeight, &mTransformHint,
                 &numPendingBuffers);
         mConsumerRunningBehind = (numPendingBuffers >= 2);
     }
     if (!err && api == NATIVE_WINDOW_API_CPU) {
         mConnectedToCpu = true;
     }
     return err;
 }
 
 int GonkNativeWindowClient::disconnect(int api) {
     ALOGV("GonkNativeWindowClient::disconnect");
     Mutex::Autolock lock(mMutex);
     freeAllBuffers();
-    int err = mGraphicBufferProducer->disconnect(api);
+    int err = mBufferProducer->disconnect(api);
+
     if (!err) {
         mReqFormat = 0;
         mReqWidth = 0;
         mReqHeight = 0;
         mReqUsage = 0;
         mCrop.clear();
         mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
         mTransform = 0;
@@ -532,17 +557,17 @@ int GonkNativeWindowClient::setCrop(Rect
     return NO_ERROR;
 }
 
 int GonkNativeWindowClient::setBufferCount(int bufferCount)
 {
     ALOGV("GonkNativeWindowClient::setBufferCount");
     Mutex::Autolock lock(mMutex);
 
-    status_t err = mGraphicBufferProducer->setBufferCount(bufferCount);
+    status_t err = mBufferProducer->setBufferCount(bufferCount);
     ALOGE_IF(err, "IGraphicBufferProducer::setBufferCount(%d) returned %s",
             bufferCount, strerror(-err));
 
     if (err == NO_ERROR) {
         freeAllBuffers();
     }
 
     return err;
--- a/widget/gonk/nativewindow/GonkNativeWindowClientJB.h
+++ b/widget/gonk/nativewindow/GonkNativeWindowClientJB.h
@@ -13,17 +13,21 @@
  * 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 NATIVEWINDOW_GONKNATIVEWINDOWCLIENT_JB_H
 #define NATIVEWINDOW_GONKNATIVEWINDOWCLIENT_JB_H
 
+#if ANDROID_VERSION == 17
+#include <gui/ISurfaceTexture.h>
+#else
 #include <gui/IGraphicBufferProducer.h>
+#endif
 
 #include <ui/ANativeObjectBase.h>
 #include <ui/Region.h>
 
 #include <utils/RefBase.h>
 #include <utils/threads.h>
 #include <utils/KeyedVector.h>
 
@@ -64,23 +68,29 @@ public:
      * therefore prevent them to be used as actual producers of buffers.
      */
     GonkNativeWindowClient(const sp<IGraphicBufferProducer>& bufferProducer);
 
     /* getIGraphicBufferProducer() returns the IGraphicBufferProducer this
      * GonkNativeWindowClient was created with. Usually it's an error to use the
      * IGraphicBufferProducer while the GonkNativeWindowClient is connected.
      */
+#if ANDROID_VERSION == 17
+    sp<IGraphicBufferProducer> getISurfaceTexture() const;
+#else
     sp<IGraphicBufferProducer> getIGraphicBufferProducer() const;
+#endif
 
     /* convenience function to check that the given surface is non NULL as
      * well as its IGraphicBufferProducer */
+#if ANDROID_VERSION >= 18
     static bool isValid(const sp<GonkNativeWindowClient>& surface) {
         return surface != NULL && surface->getIGraphicBufferProducer() != NULL;
     }
+#endif
 
 protected:
     virtual ~GonkNativeWindowClient();
 
 private:
     // can't be copied
     GonkNativeWindowClient& operator = (const GonkNativeWindowClient& rhs);
     GonkNativeWindowClient(const GonkNativeWindowClient& rhs);
@@ -158,18 +168,17 @@ private:
     struct BufferSlot {
         sp<GraphicBuffer> buffer;
         Region dirtyRegion;
     };
 
     // mSurfaceTexture is the interface to the surface texture server. All
     // operations on the surface texture client ultimately translate into
     // interactions with the server using this interface.
-    // TODO: rename to mBufferProducer
-    sp<IGraphicBufferProducer> mGraphicBufferProducer;
+    sp<IGraphicBufferProducer> mBufferProducer;
 
     // mSlots stores the buffers that have been allocated for each buffer slot.
     // It is initialized to null pointers, and gets filled in with the result of
     // IGraphicBufferProducer::requestBuffer when the client dequeues a buffer from a
     // slot that has not yet been used. The buffer allocated to a slot will also
     // be replaced if the requested buffer usage or geometry differs from that
     // of the buffer allocated to a slot.
     BufferSlot mSlots[NUM_BUFFER_SLOTS];
--- a/widget/gonk/nativewindow/GonkNativeWindowJB.cpp
+++ b/widget/gonk/nativewindow/GonkNativeWindowJB.cpp
@@ -42,17 +42,17 @@ GonkNativeWindow::GonkNativeWindow() :
 GonkNativeWindow::~GonkNativeWindow() {
 }
 
 void GonkNativeWindow::setName(const String8& name) {
     Mutex::Autolock _l(mMutex);
     mName = name;
     mBufferQueue->setConsumerName(name);
 }
-
+#if ANDROID_VERSION >= 18
 status_t GonkNativeWindow::acquireBuffer(BufferItem *item, bool waitForFence) {
     status_t err;
 
     if (!item) return BAD_VALUE;
 
     Mutex::Autolock _l(mMutex);
 
     err = acquireBufferLocked(item);
@@ -87,16 +87,17 @@ status_t GonkNativeWindow::releaseBuffer
 
     err = releaseBufferLocked(item.mBuf);
     if (err != OK) {
         BI_LOGE("Failed to release buffer: %s (%d)",
                 strerror(-err), err);
     }
     return err;
 }
+#endif
 
 status_t GonkNativeWindow::setDefaultBufferSize(uint32_t w, uint32_t h) {
     Mutex::Autolock _l(mMutex);
     return mBufferQueue->setDefaultBufferSize(w, h);
 }
 
 status_t GonkNativeWindow::setDefaultBufferFormat(uint32_t defaultFormat) {
     Mutex::Autolock _l(mMutex);
--- a/widget/gonk/nativewindow/GonkNativeWindowJB.h
+++ b/widget/gonk/nativewindow/GonkNativeWindowJB.h
@@ -81,26 +81,29 @@ class GonkNativeWindow: public GonkConsu
     //
     // Only a fixed number of buffers can be acquired at a time, determined by
     // the construction-time bufferCount parameter. If INVALID_OPERATION is
     // returned by acquireBuffer, then old buffers must be returned to the
     // queue by calling releaseBuffer before more buffers can be acquired.
     //
     // If waitForFence is true, and the acquired BufferItem has a valid fence object,
     // acquireBuffer will wait on the fence with no timeout before returning.
+#if ANDROID_VERSION >= 18
     status_t acquireBuffer(BufferItem *item, bool waitForFence = true);
-
+#endif
     // Returns an acquired buffer to the queue, allowing it to be reused. Since
     // only a fixed number of buffers may be acquired at a time, old buffers
     // must be released by calling releaseBuffer to ensure new buffers can be
     // acquired by acquireBuffer. Once a BufferItem is released, the caller must
     // not access any members of the BufferItem, and should immediately remove
     // all of its references to the BufferItem itself.
+#if ANDROID_VERSION >= 18
     status_t releaseBuffer(const BufferItem &item,
             const sp<Fence>& releaseFence = Fence::NO_FENCE);
+#endif
 
     sp<IGraphicBufferProducer> getProducerInterface() const { return getBufferQueue(); }
 
     // setDefaultBufferSize is used to set the size of buffers returned by
     // requestBuffers when a with and height of zero is requested.
     status_t setDefaultBufferSize(uint32_t w, uint32_t h);
 
     // setDefaultBufferFormat allows the BufferQueue to create
--- a/widget/gonk/nativewindow/moz.build
+++ b/widget/gonk/nativewindow/moz.build
@@ -16,31 +16,31 @@
 
 MODULE = 'nativewindow'
 
 EXPORTS += [
     'GonkNativeWindow.h',
     'GonkNativeWindowClient.h',
 ]
 
-if CONFIG['ANDROID_VERSION'] == '18':
+if CONFIG['ANDROID_VERSION'] in ('17', '18'):
     EXPORTS += [
         'GonkBufferQueue.h',
         'GonkConsumerBase.h',
         'GonkNativeWindowClientJB.h',
         'GonkNativeWindowJB.h',
     ]
 elif CONFIG['ANDROID_VERSION'] == '15':
     EXPORTS += [
         'GonkNativeWindowClientICS.h',
         'GonkNativeWindowICS.h',
     ]
 
 if CONFIG['MOZ_B2G_CAMERA'] or CONFIG['MOZ_OMX_DECODER']:
-    if CONFIG['ANDROID_VERSION'] == '18':
+    if CONFIG['ANDROID_VERSION'] in ('17', '18'):
         CPP_SOURCES += [
             'GonkBufferQueue.cpp',
             'GonkConsumerBase.cpp',
             'GonkNativeWindowJB.cpp',
             'GonkNativeWindowClientJB.cpp',
         ]
     elif CONFIG['ANDROID_VERSION'] == '15':
         CPP_SOURCES += [