Bug 871364 - Support GonkNativeWindow on gonk-JB r=jmuizelaar,mwu,doublec,mikeh,glandium
authorSotaro Ikeda <sikeda@mozilla.com>
Thu, 12 Sep 2013 11:40:26 +0200
changeset 146881 91d00574540191ef40fc7e9b7b348ca57e79ec75
parent 146880 4ab45ab4f80b5962348cc9bc6d24d794f94d9735
child 146882 4fc92e3e3ce0d3dc9d3d235ce4d497bc83212f9a
push id2635
push userryanvm@gmail.com
push dateFri, 13 Sep 2013 02:29:47 +0000
treeherderfx-team@7b85565949af [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjmuizelaar, mwu, doublec, mikeh, glandium
bugs871364
milestone26.0a1
Bug 871364 - Support GonkNativeWindow on gonk-JB r=jmuizelaar,mwu,doublec,mikeh,glandium
configure.in
content/media/Makefile.in
content/media/omx/OmxDecoder.cpp
content/media/omx/mediaresourcemanager/IMediaResourceManagerDeathNotifier.cpp
dom/camera/AudioParameter.cpp
dom/camera/GonkCameraHwMgr.cpp
dom/camera/GonkCameraSource.cpp
dom/camera/GonkCameraSource.h
dom/camera/GonkRecorder.cpp
dom/camera/GonkRecorder.h
dom/camera/moz.build
gfx/layers/GrallocImages.cpp
gfx/layers/GrallocImages.h
gfx/layers/opengl/GrallocTextureHost.cpp
gfx/layers/opengl/TextureHostOGL.cpp
widget/gonk/Makefile.in
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/configure.in
+++ b/configure.in
@@ -206,25 +206,27 @@ if test -n "$gonkdir" ; then
     esac
 
     case "$ANDROID_VERSION" in
     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_DEFINE(MOZ_OMX_DECODER)
         AC_SUBST(MOZ_OMX_DECODER)
         ;;
     18)
-        GONK_INCLUDES="-I$gonkdir/frameworks/native/include"
+        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)
         ;;
     *)
         AC_MSG_ERROR([Unsupported platform version: $ANDROID_VERSION])
         ;;
     esac
     CPPFLAGS="-DANDROID -isystem $gonkdir/bionic/libc/$ARCH_DIR/include -isystem $gonkdir/bionic/libc/include/ -isystem $gonkdir/bionic/libc/kernel/common -isystem $gonkdir/bionic/libc/kernel/$ARCH_DIR -isystem $gonkdir/bionic/libm/include -I$gonkdir/system -I$gonkdir/system/core/include -isystem $gonkdir/bionic -I$gonkdir/hardware/libhardware/include -I$gonkdir/external/valgrind/fxos-include $GONK_INCLUDES $CPPFLAGS"
     CFLAGS="-mandroid -fno-short-enums -fno-exceptions $CFLAGS"
     CXXFLAGS="-mandroid -fno-short-enums -fno-exceptions -Wno-psabi $CXXFLAGS $STLPORT_CPPFLAGS"
--- a/content/media/Makefile.in
+++ b/content/media/Makefile.in
@@ -1,15 +1,19 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 include $(topsrcdir)/config/rules.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
 
+ifdef MOZ_OMX_DECODER
+DEFINES += -DMOZ_OMX_DECODER
+endif
+
 LOCAL_INCLUDES  += \
   -I$(topsrcdir)/content/base/src \
   -I$(topsrcdir)/layout/generic \
   -I$(topsrcdir)/layout/xul/base/src \
   $(NULL)
 
 ifdef MOZ_DIRECTSHOW
 LOCAL_INCLUDES += -I$(topsrcdir)/media/webrtc/trunk/webrtc/modules/video_capture/windows/
--- a/content/media/omx/OmxDecoder.cpp
+++ b/content/media/omx/OmxDecoder.cpp
@@ -467,17 +467,21 @@ 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
+    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
     // for (h.264).  So if we don't get a hardware decoder, just give
     // up.
     int flags = kHardwareCodecsOnly;
 
--- a/content/media/omx/mediaresourcemanager/IMediaResourceManagerDeathNotifier.cpp
+++ b/content/media/omx/mediaresourcemanager/IMediaResourceManagerDeathNotifier.cpp
@@ -19,73 +19,78 @@
 #define LOG_TAG "IMediaResourceManagerDeathNotifier"
 #include <utils/Log.h>
 
 #include <binder/IServiceManager.h>
 #include <binder/IPCThreadState.h>
 
 #include "IMediaResourceManagerDeathNotifier.h"
 
+#define DN_LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
+#define DN_LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
+#define DN_LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
+#define DN_LOGE_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+
 namespace android {
 
 // client singleton for binder interface to services
 Mutex IMediaResourceManagerDeathNotifier::sServiceLock;
 sp<IMediaResourceManagerService> IMediaResourceManagerDeathNotifier::sMediaResourceManagerService;
 sp<IMediaResourceManagerDeathNotifier::DeathNotifier> IMediaResourceManagerDeathNotifier::sDeathNotifier;
 SortedVector< wp<IMediaResourceManagerDeathNotifier> > IMediaResourceManagerDeathNotifier::sObitRecipients;
 
 // establish binder interface to MediaResourceManagerService
 /*static*/const sp<IMediaResourceManagerService>&
 IMediaResourceManagerDeathNotifier::getMediaResourceManagerService()
 {
-    LOGV("getMediaResourceManagerService");
+    DN_LOGV("getMediaResourceManagerService");
     Mutex::Autolock _l(sServiceLock);
     if (sMediaResourceManagerService.get() == 0) {
         sp<IServiceManager> sm = defaultServiceManager();
         sp<IBinder> binder;
         do {
             binder = sm->getService(String16("media.resource_manager"));
             if (binder != 0) {
                 break;
              }
-             LOGW("Media resource manager service not published, waiting...");
+             DN_LOGW("Media resource manager service not published, waiting...");
              usleep(500000); // 0.5 s
         } while(true);
 
         if (sDeathNotifier == NULL) {
         sDeathNotifier = new DeathNotifier();
     }
     binder->linkToDeath(sDeathNotifier);
     sMediaResourceManagerService = interface_cast<IMediaResourceManagerService>(binder);
     }
-    LOGE_IF(sMediaResourceManagerService == 0, "no media player service!?");
+    DN_LOGE_IF(sMediaResourceManagerService == 0, "no media player service!?");
     return sMediaResourceManagerService;
 }
 
 /*static*/ void
 IMediaResourceManagerDeathNotifier::addObitRecipient(const wp<IMediaResourceManagerDeathNotifier>& recipient)
 {
-    LOGV("addObitRecipient");
     Mutex::Autolock _l(sServiceLock);
     sObitRecipients.add(recipient);
 }
 
 /*static*/ void
 IMediaResourceManagerDeathNotifier::removeObitRecipient(const wp<IMediaResourceManagerDeathNotifier>& recipient)
 {
-    LOGV("removeObitRecipient");
     Mutex::Autolock _l(sServiceLock);
     sObitRecipients.remove(recipient);
 }
 
 void
 IMediaResourceManagerDeathNotifier::DeathNotifier::binderDied(const wp<IBinder>& who)
 {
-    LOGW("media server died");
-
+    DN_LOGW("media resource manager service died");
     // Need to do this with the lock held
     SortedVector< wp<IMediaResourceManagerDeathNotifier> > list;
     {
         Mutex::Autolock _l(sServiceLock);
         sMediaResourceManagerService.clear();
         list = sObitRecipients;
     }
 
@@ -98,17 +103,16 @@ IMediaResourceManagerDeathNotifier::Deat
         if (notifier != 0) {
             notifier->died();
         }
     }
 }
 
 IMediaResourceManagerDeathNotifier::DeathNotifier::~DeathNotifier()
 {
-    LOGV("DeathNotifier::~DeathNotifier");
     Mutex::Autolock _l(sServiceLock);
     sObitRecipients.clear();
     if (sMediaResourceManagerService != 0) {
         sMediaResourceManagerService->asBinder()->unlinkToDeath(this);
     }
 }
 
 }; // namespace android
deleted file mode 100644
--- a/dom/camera/AudioParameter.cpp
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (C) 2006-2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.
- */
-
-#define LOG_TAG "AudioParameter"
-//#define LOG_NDEBUG 0
-
-#include <utils/Log.h>
-
-#include <media/AudioParameter.h>
-
-namespace android {
-
-const char *AudioParameter::keyRouting = "routing";
-const char *AudioParameter::keySamplingRate = "sampling_rate";
-const char *AudioParameter::keyFormat = "format";
-const char *AudioParameter::keyChannels = "channels";
-const char *AudioParameter::keyFrameCount = "frame_count";
-const char *AudioParameter::keyInputSource = "input_source";
-
-AudioParameter::AudioParameter(const String8& keyValuePairs)
-{
-    char *str = new char[keyValuePairs.length()+1];
-    mKeyValuePairs = keyValuePairs;
-
-    strcpy(str, keyValuePairs.string());
-    char *pair = strtok(str, ";");
-    while (pair != NULL) {
-        if (strlen(pair) != 0) {
-            size_t eqIdx = strcspn(pair, "=");
-            String8 key = String8(pair, eqIdx);
-            String8 value;
-            if (eqIdx == strlen(pair)) {
-                value = String8("");
-            } else {
-                value = String8(pair + eqIdx + 1);
-            }
-            if (mParameters.indexOfKey(key) < 0) {
-                mParameters.add(key, value);
-            } else {
-                mParameters.replaceValueFor(key, value);
-            }
-        } else {
-            LOGV("AudioParameter() cstor empty key value pair");
-        }
-        pair = strtok(NULL, ";");
-    }
-
-    delete[] str;
-}
-
-AudioParameter::~AudioParameter()
-{
-    mParameters.clear();
-}
-
-String8 AudioParameter::toString()
-{
-    String8 str = String8("");
-
-    size_t size = mParameters.size();
-    for (size_t i = 0; i < size; i++) {
-        str += mParameters.keyAt(i);
-        str += "=";
-        str += mParameters.valueAt(i);
-        if (i < (size - 1)) str += ";";
-    }
-    return str;
-}
-
-status_t AudioParameter::add(const String8& key, const String8& value)
-{
-    if (mParameters.indexOfKey(key) < 0) {
-        mParameters.add(key, value);
-        return NO_ERROR;
-    } else {
-        mParameters.replaceValueFor(key, value);
-        return ALREADY_EXISTS;
-    }
-}
-
-status_t AudioParameter::addInt(const String8& key, const int value)
-{
-    char str[12];
-    if (snprintf(str, 12, "%d", value) > 0) {
-        String8 str8 = String8(str);
-        return add(key, str8);
-    } else {
-        return BAD_VALUE;
-    }
-}
-
-status_t AudioParameter::addFloat(const String8& key, const float value)
-{
-    char str[23];
-    if (snprintf(str, 23, "%.10f", value) > 0) {
-        String8 str8 = String8(str);
-        return add(key, str8);
-    } else {
-        return BAD_VALUE;
-    }
-}
-
-status_t AudioParameter::remove(const String8& key)
-{
-    if (mParameters.indexOfKey(key) >= 0) {
-        mParameters.removeItem(key);
-        return NO_ERROR;
-    } else {
-        return BAD_VALUE;
-    }
-}
-
-status_t AudioParameter::get(const String8& key, String8& value)
-{
-    if (mParameters.indexOfKey(key) >= 0) {
-        value = mParameters.valueFor(key);
-        return NO_ERROR;
-    } else {
-        return BAD_VALUE;
-    }
-}
-
-status_t AudioParameter::getInt(const String8& key, int& value)
-{
-    String8 str8;
-    status_t result = get(key, str8);
-    value = 0;
-    if (result == NO_ERROR) {
-        int val;
-        if (sscanf(str8.string(), "%d", &val) == 1) {
-            value = val;
-        } else {
-            result = INVALID_OPERATION;
-        }
-    }
-    return result;
-}
-
-status_t AudioParameter::getFloat(const String8& key, float& value)
-{
-    String8 str8;
-    status_t result = get(key, str8);
-    value = 0;
-    if (result == NO_ERROR) {
-        float val;
-        if (sscanf(str8.string(), "%f", &val) == 1) {
-            value = val;
-        } else {
-            result = INVALID_OPERATION;
-        }
-    }
-    return result;
-}
-
-status_t AudioParameter::getAt(size_t index, String8& key, String8& value)
-{
-    if (mParameters.size() > index) {
-        key = mParameters.keyAt(index);
-        value = mParameters.valueAt(index);
-        return NO_ERROR;
-    } else {
-        return BAD_VALUE;
-    }
-}
-
-};  // namespace android
--- a/dom/camera/GonkCameraHwMgr.cpp
+++ b/dom/camera/GonkCameraHwMgr.cpp
@@ -178,24 +178,34 @@ 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
+  mCamera->setPreviewTexture(mNativeWindow->getBufferQueue());
+#else
   mCamera->setPreviewTexture(mNativeWindow);
+#endif
   mInitialized = true;
 }
 
 sp<GonkCameraHardware>
 GonkCameraHardware::Connect(mozilla::nsGonkCameraControl* aTarget, uint32_t aCameraId)
 {
+#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 18
+  sp<Camera> camera = Camera::connect(aCameraId, /* clientPackageName */String16("gonk.camera"), Camera::USE_CALLING_UID);
+#else
   sp<Camera> camera = Camera::connect(aCameraId);
+#endif
+
+
   if (camera.get() == nullptr) {
     return nullptr;
   }
   sp<GonkCameraHardware> cameraHardware = new GonkCameraHardware(aTarget, aCameraId, camera);
   return cameraHardware;
  }
 
 void
--- a/dom/camera/GonkCameraSource.cpp
+++ b/dom/camera/GonkCameraSource.cpp
@@ -1,10 +1,11 @@
 /*
  * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2013 Mozilla Foundation
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
@@ -13,34 +14,46 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 #include <base/basictypes.h>
 #include "nsDebug.h"
 #define DOM_CAMERA_LOG_LEVEL        3
 #include "CameraCommon.h"
-#define LOGD DOM_CAMERA_LOGA
-#define LOGV DOM_CAMERA_LOGI
-#define LOGI DOM_CAMERA_LOGI
-#define LOGW DOM_CAMERA_LOGW
-#define LOGE DOM_CAMERA_LOGE
+/*
+#define CS_LOGD(...) DOM_CAMERA_LOGA(__VA_ARGS__)
+#define CS_LOGV(...) DOM_CAMERA_LOGI(__VA_ARGS__)
+#define CS_LOGI(...) DOM_CAMERA_LOGI(__VA_ARGS__)
+#define CS_LOGW(...) DOM_CAMERA_LOGW(__VA_ARGS__)
+#define CS_LOGE(...) DOM_CAMERA_LOGE(__VA_ARGS__)
+*/
+
+#define CS_LOGD(fmt, ...) DOM_CAMERA_LOGA("[%s:%d]" fmt,__FILE__,__LINE__, ## __VA_ARGS__)
+#define CS_LOGV(fmt, ...) DOM_CAMERA_LOGI("[%s:%d]" fmt,__FILE__,__LINE__, ## __VA_ARGS__)
+#define CS_LOGI(fmt, ...) DOM_CAMERA_LOGI("[%s:%d]" fmt,__FILE__,__LINE__, ## __VA_ARGS__)
+#define CS_LOGW(fmt, ...) DOM_CAMERA_LOGW("[%s:%d]" fmt,__FILE__,__LINE__, ## __VA_ARGS__)
+#define CS_LOGE(fmt, ...) DOM_CAMERA_LOGE("[%s:%d]" fmt,__FILE__,__LINE__, ## __VA_ARGS__)
 
 #include <OMX_Component.h>
+#include <binder/IPCThreadState.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+#include <camera/CameraParameters.h>
+#include <utils/String8.h>
+#include <cutils/properties.h>
+
 #include "GonkCameraSource.h"
 #include "GonkCameraListener.h"
 #include "GonkCameraHwMgr.h"
-#include <media/stagefright/MediaDebug.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MetaData.h>
-#include <utils/String8.h>
-#include <cutils/properties.h>
 
 using namespace mozilla;
+
 namespace android {
 
 static const int64_t CAMERA_SOURCE_TIMEOUT_NS = 3000000000LL;
 
 struct GonkCameraSourceListener : public GonkCameraListener {
     GonkCameraSourceListener(const sp<GonkCameraSource> &source);
 
     virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2);
@@ -63,22 +76,22 @@ private:
 GonkCameraSourceListener::GonkCameraSourceListener(const sp<GonkCameraSource> &source)
     : mSource(source) {
 }
 
 GonkCameraSourceListener::~GonkCameraSourceListener() {
 }
 
 void GonkCameraSourceListener::notify(int32_t msgType, int32_t ext1, int32_t ext2) {
-    LOGV("notify(%d, %d, %d)", msgType, ext1, ext2);
+    CS_LOGV("notify(%d, %d, %d)", msgType, ext1, ext2);
 }
 
 void GonkCameraSourceListener::postData(int32_t msgType, const sp<IMemory> &dataPtr,
                                     camera_frame_metadata_t *metadata) {
-    LOGV("postData(%d, ptr:%p, size:%d)",
+    CS_LOGV("postData(%d, ptr:%p, size:%d)",
          msgType, dataPtr->pointer(), dataPtr->size());
 
     sp<GonkCameraSource> source = mSource.promote();
     if (source.get() != NULL) {
         source->dataCallback(msgType, dataPtr);
     }
 }
 
@@ -87,17 +100,17 @@ void GonkCameraSourceListener::postDataT
 
     sp<GonkCameraSource> source = mSource.promote();
     if (source.get() != NULL) {
         source->dataCallbackTimestamp(timestamp/1000, msgType, dataPtr);
     }
 }
 
 static int32_t getColorFormat(const char* colorFormat) {
-    return OMX_COLOR_FormatYUV420SemiPlanar;
+    return OMX_COLOR_FormatYUV420SemiPlanar; //XXX nsGonkCameraControl uses only YUV420SemiPlanar
 
     if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420P)) {
        return OMX_COLOR_FormatYUV420Planar;
     }
 
     if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422SP)) {
        return OMX_COLOR_FormatYUV422SemiPlanar;
     }
@@ -112,21 +125,25 @@ 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;
     }
-
-    LOGE("Uknown color format (%s), please add it to "
+#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 18
+    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_EQ(0, "Unknown color format");
+    CHECK(!"Unknown color format");
 }
 
 GonkCameraSource *GonkCameraSource::Create(
     const sp<GonkCameraHardware>& aCameraHw,
     Size videoSize,
     int32_t frameRate,
     bool storeMetaDataInVideoBuffers) {
 
@@ -138,16 +155,17 @@ GonkCameraSource *GonkCameraSource::Crea
 
 GonkCameraSource::GonkCameraSource(
     const sp<GonkCameraHardware>& aCameraHw,
     Size videoSize,
     int32_t frameRate,
     bool storeMetaDataInVideoBuffers)
     : mCameraHw(aCameraHw),
       mCameraFlags(0),
+      mNumInputBuffers(0),
       mVideoFrameRate(-1),
       mNumFramesReceived(0),
       mLastFrameTimestampUs(0),
       mStarted(false),
       mNumFramesEncoded(0),
       mTimeBetweenFrameCaptureUs(0),
       mFirstFrameTimeUs(0),
       mNumFramesDropped(0),
@@ -176,17 +194,17 @@ status_t GonkCameraSource::initCheck() c
  * @param height the video frame height in pixels
  * @param suppportedSizes the vector of sizes that we check against
  * @return true if the dimension (width and height) is supported.
  */
 static bool isVideoSizeSupported(
     int32_t width, int32_t height,
     const Vector<Size>& supportedSizes) {
 
-    LOGV("isVideoSizeSupported");
+    CS_LOGV("isVideoSizeSupported");
     for (size_t i = 0; i < supportedSizes.size(); ++i) {
         if (width  == supportedSizes[i].width &&
             height == supportedSizes[i].height) {
             return true;
         }
     }
     return false;
 }
@@ -213,17 +231,17 @@ static bool isVideoSizeSupported(
 static void getSupportedVideoSizes(
     const CameraParameters& params,
     bool *isSetVideoSizeSupported,
     Vector<Size>& sizes) {
 
     *isSetVideoSizeSupported = true;
     params.getSupportedVideoSizes(sizes);
     if (sizes.size() == 0) {
-        LOGD("Camera does not support setVideoSize()");
+        CS_LOGD("Camera does not support setVideoSize()");
         params.getSupportedPreviewSizes(sizes);
         *isSetVideoSizeSupported = false;
     }
 }
 
 /*
  * Check whether the camera has the supported color format
  * @param params CameraParameters to retrieve the information
@@ -253,70 +271,70 @@ status_t GonkCameraSource::isCameraColor
  * @param height the target video frame height in pixels
  * @param frameRate the target frame rate in frames per second.
  * @return OK if no error.
  */
 status_t GonkCameraSource::configureCamera(
         CameraParameters* params,
         int32_t width, int32_t height,
         int32_t frameRate) {
-    LOGV("configureCamera");
+    CS_LOGV("configureCamera");
     Vector<Size> sizes;
     bool isSetVideoSizeSupportedByCamera = true;
     getSupportedVideoSizes(*params, &isSetVideoSizeSupportedByCamera, sizes);
     bool isCameraParamChanged = false;
     if (width != -1 && height != -1) {
         if (!isVideoSizeSupported(width, height, sizes)) {
-            LOGE("Video dimension (%dx%d) is unsupported", width, height);
+            CS_LOGE("Video dimension (%dx%d) is unsupported", width, height);
             return BAD_VALUE;
         }
         if (isSetVideoSizeSupportedByCamera) {
             params->setVideoSize(width, height);
         } else {
             params->setPreviewSize(width, height);
         }
         isCameraParamChanged = true;
     } else if ((width == -1 && height != -1) ||
                (width != -1 && height == -1)) {
         // If one and only one of the width and height is -1
         // we reject such a request.
-        LOGE("Requested video size (%dx%d) is not supported", width, height);
+        CS_LOGE("Requested video size (%dx%d) is not supported", width, height);
         return BAD_VALUE;
     } else {  // width == -1 && height == -1
         // Do not configure the camera.
         // Use the current width and height value setting from the camera.
     }
 
     if (frameRate != -1) {
         CHECK(frameRate > 0 && frameRate <= 120);
         const char* supportedFrameRates =
                 params->get(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES);
         CHECK(supportedFrameRates != NULL);
-        LOGV("Supported frame rates: %s", supportedFrameRates);
+        CS_LOGV("Supported frame rates: %s", supportedFrameRates);
         char buf[4];
         snprintf(buf, 4, "%d", frameRate);
         if (strstr(supportedFrameRates, buf) == NULL) {
-            LOGE("Requested frame rate (%d) is not supported: %s",
+            CS_LOGE("Requested frame rate (%d) is not supported: %s",
                 frameRate, supportedFrameRates);
             return BAD_VALUE;
         }
 
         // The frame rate is supported, set the camera to the requested value.
         params->setPreviewFrameRate(frameRate);
         isCameraParamChanged = true;
     } else {  // frameRate == -1
         // Do not configure the camera.
         // Use the current frame rate value setting from the camera
     }
 
     if (isCameraParamChanged) {
         // Either frame rate or frame size needs to be changed.
         if (OK != mCameraHw->PushParameters(*params)) {
-            LOGE("Could not change settings."
-                 " Someone else is using camera ?");
+            CS_LOGE("Could not change settings."
+                 " Someone else is using camera?");
             return -EBUSY;
         }
     }
     return OK;
 }
 
 /*
  * Check whether the requested video frame size
@@ -328,43 +346,43 @@ status_t GonkCameraSource::configureCame
  * @param the target video frame width in pixels to check against
  * @param the target video frame height in pixels to check against
  * @return OK if no error
  */
 status_t GonkCameraSource::checkVideoSize(
         const CameraParameters& params,
         int32_t width, int32_t height) {
 
-    LOGV("checkVideoSize");
+    CS_LOGV("checkVideoSize");
     // The actual video size is the same as the preview size
     // if the camera hal does not support separate video and
     // preview output. In this case, we retrieve the video
     // size from preview.
     int32_t frameWidthActual = -1;
     int32_t frameHeightActual = -1;
     Vector<Size> sizes;
     params.getSupportedVideoSizes(sizes);
     if (sizes.size() == 0) {
         // video size is the same as preview size
         params.getPreviewSize(&frameWidthActual, &frameHeightActual);
     } else {
         // video size may not be the same as preview
         params.getVideoSize(&frameWidthActual, &frameHeightActual);
     }
     if (frameWidthActual < 0 || frameHeightActual < 0) {
-        LOGE("Failed to retrieve video frame size (%dx%d)",
+        CS_LOGE("Failed to retrieve video frame size (%dx%d)",
                 frameWidthActual, frameHeightActual);
         return UNKNOWN_ERROR;
     }
 
     // Check the actual video frame size against the target/requested
     // video frame size.
     if (width != -1 && height != -1) {
         if (frameWidthActual != width || frameHeightActual != height) {
-            LOGE("Failed to set video frame size to %dx%d. "
+            CS_LOGE("Failed to set video frame size to %dx%d. "
                     "The actual video size is %dx%d ", width, height,
                     frameWidthActual, frameHeightActual);
             return UNKNOWN_ERROR;
         }
     }
 
     // Good now.
     mVideoSize.width = frameWidthActual;
@@ -380,38 +398,38 @@ status_t GonkCameraSource::checkVideoSiz
  * @param params CameraParameters to retrieve the information
  * @param the target video frame rate to check against
  * @return OK if no error.
  */
 status_t GonkCameraSource::checkFrameRate(
         const CameraParameters& params,
         int32_t frameRate) {
 
-    LOGV("checkFrameRate");
+    CS_LOGV("checkFrameRate");
     int32_t frameRateActual = params.getPreviewFrameRate();
     if (frameRateActual < 0) {
-        LOGE("Failed to retrieve preview frame rate (%d)", frameRateActual);
+        CS_LOGE("Failed to retrieve preview frame rate (%d)", frameRateActual);
         return UNKNOWN_ERROR;
     }
 
     // Check the actual video frame rate against the target/requested
     // video frame rate.
     if (frameRate != -1 && (frameRateActual - frameRate) != 0) {
-        LOGE("Failed to set preview frame rate to %d fps. The actual "
+        CS_LOGE("Failed to set preview frame rate to %d fps. The actual "
                 "frame rate is %d", frameRate, frameRateActual);
         return UNKNOWN_ERROR;
     }
 
     // Good now.
     mVideoFrameRate = frameRateActual;
     return OK;
 }
 
 /*
- * Initialize the CameraSource to so that it becomes
+ * Initialize the GonkCameraSource so that it becomes
  * ready for providing the video input streams as requested.
  * @param camera the camera object used for the video source
  * @param cameraId if camera == 0, use camera with this id
  *      as the video source
  * @param videoSize the target video frame size. If both
  *      width and height in videoSize is -1, use the current
  *      width and heigth settings by the camera
  * @param frameRate the target frame rate in frames per second.
@@ -423,17 +441,17 @@ status_t GonkCameraSource::checkFrameRat
  *
  * @return OK if no error.
  */
 status_t GonkCameraSource::init(
         Size videoSize,
         int32_t frameRate,
         bool storeMetaDataInVideoBuffers) {
 
-    LOGV("init");
+    CS_LOGV("init");
     status_t err = OK;
     //TODO: need to do something here to check the sanity of camera
 
     CameraParameters params;
     mCameraHw->PullParameters(params);
     if ((err = isCameraColorFormatSupported(params)) != OK) {
         return err;
     }
@@ -461,144 +479,136 @@ status_t GonkCameraSource::init(
     mIsMetaDataStoredInVideoBuffers = false;
     mCameraHw->StoreMetaDataInBuffers(false);
     if (storeMetaDataInVideoBuffers) {
         if (OK == mCameraHw->StoreMetaDataInBuffers(true)) {
             mIsMetaDataStoredInVideoBuffers = true;
         }
     }
 
-    const char *hfr_str = params.get("video-hfr");
-    int32_t hfr = -1;
-    if ( hfr_str != NULL ) {
-      hfr = atoi(hfr_str);
-    }
-    if(hfr < 0) {
-      LOGW("Invalid hfr value(%d) set from app. Disabling HFR.", hfr);
-      hfr = 0;
-    }
-
     int64_t glitchDurationUs = (1000000LL / mVideoFrameRate);
     if (glitchDurationUs > mGlitchDurationThresholdUs) {
         mGlitchDurationThresholdUs = glitchDurationUs;
     }
 
-    const char * k3dFrameArrangement = "3d-frame-format";
-    const char * arrangement = params.get(k3dFrameArrangement);
-    // XXX: just assume left/right for now since that's all the camera supports
-    bool want3D = (arrangement != NULL && !strcmp("left-right", arrangement));
-
     // XXX: query camera for the stride and slice height
     // when the capability becomes available.
     mMeta = new MetaData;
     mMeta->setCString(kKeyMIMEType,  MEDIA_MIMETYPE_VIDEO_RAW);
     mMeta->setInt32(kKeyColorFormat, mColorFormat);
     mMeta->setInt32(kKeyWidth,       mVideoSize.width);
     mMeta->setInt32(kKeyHeight,      mVideoSize.height);
     mMeta->setInt32(kKeyStride,      mVideoSize.width);
     mMeta->setInt32(kKeySliceHeight, mVideoSize.height);
     mMeta->setInt32(kKeyFrameRate,   mVideoFrameRate);
-
     return OK;
 }
 
 GonkCameraSource::~GonkCameraSource() {
     if (mStarted) {
-        stop();
+        reset();
     } else if (mInitCheck == OK) {
         // Camera is initialized but because start() is never called,
         // the lock on Camera is never released(). This makes sure
         // Camera's lock is released in this case.
         // TODO: Don't think I need to do this
         releaseCamera();
     }
 }
 
 int GonkCameraSource::startCameraRecording() {
-    LOGV("startCameraRecording");
+    CS_LOGV("startCameraRecording");
     return mCameraHw->StartRecording();
 }
 
 status_t GonkCameraSource::start(MetaData *meta) {
     int rv;
 
-    LOGV("start");
+    CS_LOGV("start");
     CHECK(!mStarted);
     if (mInitCheck != OK) {
-        LOGE("GonkCameraSource is not initialized yet");
+        CS_LOGE("GonkCameraSource is not initialized yet");
         return mInitCheck;
     }
 
     char value[PROPERTY_VALUE_MAX];
     if (property_get("media.stagefright.record-stats", value, NULL)
         && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
         mCollectStats = true;
     }
 
     mStartTimeUs = 0;
-    int64_t startTimeUs;
-    if (meta && meta->findInt64(kKeyTime, &startTimeUs)) {
-        LOGV("Metadata enabled, startime: %lld us", startTimeUs);
-        mStartTimeUs = startTimeUs;
+    mNumInputBuffers = 0;
+    if (meta) {
+        int64_t startTimeUs;
+        if (meta->findInt64(kKeyTime, &startTimeUs)) {
+            mStartTimeUs = startTimeUs;
+        }
+#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 18
+        int32_t nBuffers;
+        if (meta->findInt32(kKeyNumBuffers, &nBuffers)) {
+            CHECK_GT(nBuffers, 0);
+            mNumInputBuffers = nBuffers;
+        }
+#endif
     }
 
     // Register a listener with GonkCameraHardware so that we can get callbacks
     mCameraHw->SetListener(new GonkCameraSourceListener(this));
 
     rv = startCameraRecording();
 
     mStarted = (rv == OK);
     return rv;
 }
 
 void GonkCameraSource::stopCameraRecording() {
-    LOGV("stopCameraRecording");
+    CS_LOGV("stopCameraRecording");
     mCameraHw->StopRecording();
 }
 
 void GonkCameraSource::releaseCamera() {
-    LOGV("releaseCamera");
+    CS_LOGV("releaseCamera");
 }
 
-status_t GonkCameraSource::stop() {
-    LOGV("stop: E");
+status_t GonkCameraSource::reset() {
+    CS_LOGD("reset: E");
     Mutex::Autolock autoLock(mLock);
     mStarted = false;
     mFrameAvailableCondition.signal();
 
     releaseQueuedFrames();
     while (!mFramesBeingEncoded.empty()) {
         if (NO_ERROR !=
             mFrameCompleteCondition.waitRelative(mLock,
                     mTimeBetweenFrameCaptureUs * 1000LL + CAMERA_SOURCE_TIMEOUT_NS)) {
-            LOGW("Timed out waiting for outstanding frames being encoded: %d",
+            CS_LOGW("Timed out waiting for outstanding frames being encoded: %d",
                 mFramesBeingEncoded.size());
         }
     }
-    LOGV("Calling stopCameraRecording");
     stopCameraRecording();
     releaseCamera();
 
     if (mCollectStats) {
-        LOGI("Frames received/encoded/dropped: %d/%d/%d in %lld us",
+        CS_LOGI("Frames received/encoded/dropped: %d/%d/%d in %lld us",
                 mNumFramesReceived, mNumFramesEncoded, mNumFramesDropped,
                 mLastFrameTimestampUs - mFirstFrameTimeUs);
     }
 
     if (mNumGlitches > 0) {
-        LOGW("%d long delays between neighboring video frames", mNumGlitches);
+        CS_LOGW("%d long delays between neighboring video frames", mNumGlitches);
     }
 
     CHECK_EQ(mNumFramesReceived, mNumFramesEncoded + mNumFramesDropped);
-    LOGV("stop: X");
+    CS_LOGD("reset: X");
     return OK;
 }
 
 void GonkCameraSource::releaseRecordingFrame(const sp<IMemory>& frame) {
-    LOGV("releaseRecordingFrame");
+    CS_LOGV("releaseRecordingFrame");
     mCameraHw->ReleaseRecordingFrame(frame);
 }
 
 void GonkCameraSource::releaseQueuedFrames() {
     List<sp<IMemory> >::iterator it;
     while (!mFramesReceived.empty()) {
         it = mFramesReceived.begin();
         releaseRecordingFrame(*it);
@@ -611,36 +621,36 @@ sp<MetaData> GonkCameraSource::getFormat
     return mMeta;
 }
 
 void GonkCameraSource::releaseOneRecordingFrame(const sp<IMemory>& frame) {
     releaseRecordingFrame(frame);
 }
 
 void GonkCameraSource::signalBufferReturned(MediaBuffer *buffer) {
-    LOGV("signalBufferReturned: %p", buffer->data());
+    CS_LOGV("signalBufferReturned: %p", buffer->data());
     Mutex::Autolock autoLock(mLock);
     for (List<sp<IMemory> >::iterator it = mFramesBeingEncoded.begin();
          it != mFramesBeingEncoded.end(); ++it) {
         if ((*it)->pointer() ==  buffer->data()) {
             releaseOneRecordingFrame((*it));
             mFramesBeingEncoded.erase(it);
             ++mNumFramesEncoded;
             buffer->setObserver(0);
             buffer->release();
             mFrameCompleteCondition.signal();
             return;
         }
     }
-    CHECK_EQ(0, "signalBufferReturned: bogus buffer");
+    CHECK(!"signalBufferReturned: bogus buffer");
 }
 
 status_t GonkCameraSource::read(
         MediaBuffer **buffer, const ReadOptions *options) {
-    LOGV("read");
+    CS_LOGV("read");
 
     *buffer = NULL;
 
     int64_t seekTimeUs;
     ReadOptions::SeekMode mode;
     if (options && options->getSeekTo(&seekTimeUs, &mode)) {
         return ERROR_UNSUPPORTED;
     }
@@ -650,17 +660,17 @@ status_t GonkCameraSource::read(
 
     {
         Mutex::Autolock autoLock(mLock);
         while (mStarted && mFramesReceived.empty()) {
             if (NO_ERROR !=
                 mFrameAvailableCondition.waitRelative(mLock,
                     mTimeBetweenFrameCaptureUs * 1000LL + CAMERA_SOURCE_TIMEOUT_NS)) {
                 //TODO: check sanity of camera?
-                LOGW("Timed out waiting for incoming camera video frames: %lld us",
+                CS_LOGW("Timed out waiting for incoming camera video frames: %lld us",
                     mLastFrameTimestampUs);
             }
         }
         if (!mStarted) {
             return OK;
         }
         frame = *mFramesReceived.begin();
         mFramesReceived.erase(mFramesReceived.begin());
@@ -673,34 +683,33 @@ status_t GonkCameraSource::read(
         (*buffer)->add_ref();
         (*buffer)->meta_data()->setInt64(kKeyTime, frameTime);
     }
     return OK;
 }
 
 void GonkCameraSource::dataCallbackTimestamp(int64_t timestampUs,
         int32_t msgType, const sp<IMemory> &data) {
-    LOGV("dataCallbackTimestamp: timestamp %lld us", timestampUs);
-    //LOGV("dataCallbackTimestamp: data %x size %d", data->pointer(), data->size());
+    CS_LOGV("dataCallbackTimestamp: timestamp %lld us", timestampUs);
     Mutex::Autolock autoLock(mLock);
     if (!mStarted || (mNumFramesReceived == 0 && timestampUs < mStartTimeUs)) {
-        LOGV("Drop frame at %lld/%lld us", timestampUs, mStartTimeUs);
+        CS_LOGV("Drop frame at %lld/%lld us", timestampUs, mStartTimeUs);
         releaseOneRecordingFrame(data);
         return;
     }
 
     if (mNumFramesReceived > 0) {
         CHECK(timestampUs > mLastFrameTimestampUs);
         if (timestampUs - mLastFrameTimestampUs > mGlitchDurationThresholdUs) {
             ++mNumGlitches;
         }
     }
 
     // May need to skip frame or modify timestamp. Currently implemented
-    // by the subclass GonkCameraSourceTimeLapse.
+    // by the subclass CameraSourceTimeLapse.
     if (skipCurrentFrame(timestampUs)) {
         releaseOneRecordingFrame(data);
         return;
     }
 
     mLastFrameTimestampUs = timestampUs;
     if (mNumFramesReceived == 0) {
         mFirstFrameTimeUs = timestampUs;
@@ -716,19 +725,19 @@ void GonkCameraSource::dataCallbackTimes
         }
     }
     ++mNumFramesReceived;
 
     CHECK(data != NULL && data->size() > 0);
     mFramesReceived.push_back(data);
     int64_t timeUs = mStartTimeUs + (timestampUs - mFirstFrameTimeUs);
     mFrameTimes.push_back(timeUs);
-    LOGV("initial delay: %lld, current time stamp: %lld",
+    CS_LOGV("initial delay: %lld, current time stamp: %lld",
         mStartTimeUs, timeUs);
     mFrameAvailableCondition.signal();
 }
 
 bool GonkCameraSource::isMetaDataStoredInVideoBuffers() const {
-    LOGV("isMetaDataStoredInVideoBuffers");
+    CS_LOGV("isMetaDataStoredInVideoBuffers");
     return mIsMetaDataStoredInVideoBuffers;
 }
 
-} // namespace android
+}  // namespace android
--- a/dom/camera/GonkCameraSource.h
+++ b/dom/camera/GonkCameraSource.h
@@ -18,37 +18,36 @@
 
 #define GONK_CAMERA_SOURCE_H_
 
 #include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/MediaSource.h>
 #include <camera/CameraParameters.h>
 #include <utils/List.h>
 #include <utils/RefBase.h>
-#include <utils/threads.h>
+#include <utils/String16.h>
 
 #include "GonkCameraHwMgr.h"
 
 namespace android {
 
 class IMemory;
-class GonkCameraSourceListener;
 
 class GonkCameraSource : public MediaSource, public MediaBufferObserver {
 public:
 
     static GonkCameraSource *Create(const sp<GonkCameraHardware>& aCameraHw,
                                     Size videoSize,
                                     int32_t frameRate,
                                     bool storeMetaDataInVideoBuffers = false);
 
     virtual ~GonkCameraSource();
 
     virtual status_t start(MetaData *params = NULL);
-    virtual status_t stop();
+    virtual status_t stop() { return reset(); }
     virtual status_t read(
             MediaBuffer **buffer, const ReadOptions *options = NULL);
 
     /**
      * Check whether a GonkCameraSource object is properly initialized.
      * Must call this method before stop().
      * @return OK if initialization has successfully completed.
      */
@@ -80,16 +79,17 @@ protected:
 
     enum CameraFlags {
         FLAGS_SET_CAMERA = 1L << 0,
         FLAGS_HOT_CAMERA = 1L << 1,
     };
 
     int32_t  mCameraFlags;
     Size     mVideoSize;
+    int32_t  mNumInputBuffers;
     int32_t  mVideoFrameRate;
     int32_t  mColorFormat;
     status_t mInitCheck;
 
     sp<MetaData> mMeta;
 
     int64_t mStartTimeUs;
     int32_t mNumFramesReceived;
@@ -148,16 +148,17 @@ private:
 
     status_t checkVideoSize(const CameraParameters& params,
                     int32_t width, int32_t height);
 
     status_t checkFrameRate(const CameraParameters& params,
                     int32_t frameRate);
 
     void releaseCamera();
+    status_t reset();
 
     GonkCameraSource(const GonkCameraSource &);
     GonkCameraSource &operator=(const GonkCameraSource &);
 };
 
 }  // namespace android
 
 #endif  // GONK_CAMERA_SOURCE_H_
--- a/dom/camera/GonkRecorder.cpp
+++ b/dom/camera/GonkRecorder.cpp
@@ -1,229 +1,225 @@
 /*
  * Copyright (C) 2009 The Android Open Source Project
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (C) 2013 Mozilla Foundation
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * 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.
  */
 
-
-#include <media/AudioParameter.h>
+#include "nsDebug.h"
+#define DOM_CAMERA_LOG_LEVEL        3
+#include "CameraCommon.h"
+#include "GonkCameraSource.h"
 #include "GonkRecorder.h"
 
+#define RE_LOGD(fmt, ...) DOM_CAMERA_LOGA("[%s:%d]" fmt,__FILE__,__LINE__, ## __VA_ARGS__)
+#define RE_LOGV(fmt, ...) DOM_CAMERA_LOGI("[%s:%d]" fmt,__FILE__,__LINE__, ## __VA_ARGS__)
+#define RE_LOGI(fmt, ...) DOM_CAMERA_LOGI("[%s:%d]" fmt,__FILE__,__LINE__, ## __VA_ARGS__)
+#define RE_LOGW(fmt, ...) DOM_CAMERA_LOGW("[%s:%d]" fmt,__FILE__,__LINE__, ## __VA_ARGS__)
+#define RE_LOGE(fmt, ...) DOM_CAMERA_LOGE("[%s:%d]" fmt,__FILE__,__LINE__, ## __VA_ARGS__)
+
+#include <binder/IPCThreadState.h>
+#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 18
+# include <media/openmax/OMX_Audio.h>
+#endif
+#include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/AudioSource.h>
 #include <media/stagefright/AMRWriter.h>
+#include <media/stagefright/AACWriter.h>
 #include <media/stagefright/MPEG2TSWriter.h>
 #include <media/stagefright/MPEG4Writer.h>
-#include <media/stagefright/MediaDebug.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/OMXClient.h>
 #include <media/stagefright/OMXCodec.h>
 #include <media/MediaProfiles.h>
-#include <utils/String8.h>
 
 #include <utils/Errors.h>
 #include <sys/types.h>
 #include <ctype.h>
 #include <unistd.h>
 
+#include <cutils/properties.h>
 #include <system/audio.h>
 
-#include "ARTPWriter.h"
-
-#include <cutils/properties.h>
-
-#include "CameraCommon.h"
-#include "GonkCameraSource.h"
-
 namespace android {
 
 GonkRecorder::GonkRecorder()
     : mWriter(NULL),
       mOutputFd(-1),
       mAudioSource(AUDIO_SOURCE_CNT),
       mVideoSource(VIDEO_SOURCE_LIST_END),
-      mStarted(false),
-      mDisableAudio(false) {
+      mStarted(false) {
 
-    DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+    RE_LOGV("Constructor");
     reset();
 }
 
 GonkRecorder::~GonkRecorder() {
-    DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+    RE_LOGV("Destructor");
     stop();
 }
 
 status_t GonkRecorder::init() {
-    DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+    RE_LOGV("init");
     return OK;
 }
 
 status_t GonkRecorder::setAudioSource(audio_source_t as) {
-    DOM_CAMERA_LOGI("%s: %d", __func__, as);
-
+    RE_LOGV("setAudioSource: %d", as);
     if (as < AUDIO_SOURCE_DEFAULT ||
         as >= AUDIO_SOURCE_CNT) {
-        DOM_CAMERA_LOGE("Invalid audio source: %d", as);
+        RE_LOGE("Invalid audio source: %d", as);
         return BAD_VALUE;
     }
 
-    if (mDisableAudio) {
-        return OK;
-    }
-
     if (as == AUDIO_SOURCE_DEFAULT) {
         mAudioSource = AUDIO_SOURCE_MIC;
     } else {
         mAudioSource = as;
     }
 
     return OK;
 }
 
 status_t GonkRecorder::setVideoSource(video_source vs) {
-    DOM_CAMERA_LOGI("%s: %d", __func__, vs);
+    RE_LOGV("setVideoSource: %d", vs);
     if (vs < VIDEO_SOURCE_DEFAULT ||
         vs >= VIDEO_SOURCE_LIST_END) {
-        DOM_CAMERA_LOGE("Invalid video source: %d", vs);
+        RE_LOGE("Invalid video source: %d", vs);
         return BAD_VALUE;
     }
 
     if (vs == VIDEO_SOURCE_DEFAULT) {
         mVideoSource = VIDEO_SOURCE_CAMERA;
     } else {
         mVideoSource = vs;
     }
 
     return OK;
 }
 
 status_t GonkRecorder::setOutputFormat(output_format of) {
-    DOM_CAMERA_LOGI("%s: %d", __func__, of);
+    RE_LOGV("setOutputFormat: %d", of);
     if (of < OUTPUT_FORMAT_DEFAULT ||
         of >= OUTPUT_FORMAT_LIST_END) {
-        DOM_CAMERA_LOGE("Invalid output format: %d", of);
+        RE_LOGE("Invalid output format: %d", of);
         return BAD_VALUE;
     }
 
     if (of == OUTPUT_FORMAT_DEFAULT) {
         mOutputFormat = OUTPUT_FORMAT_THREE_GPP;
     } else {
         mOutputFormat = of;
     }
 
     return OK;
 }
 
 status_t GonkRecorder::setAudioEncoder(audio_encoder ae) {
-    DOM_CAMERA_LOGI("%s: %d", __func__, ae);
+    RE_LOGV("setAudioEncoder: %d", ae);
     if (ae < AUDIO_ENCODER_DEFAULT ||
         ae >= AUDIO_ENCODER_LIST_END) {
-        DOM_CAMERA_LOGE("Invalid audio encoder: %d", ae);
+        RE_LOGE("Invalid audio encoder: %d", ae);
         return BAD_VALUE;
     }
 
-    if (mDisableAudio) {
-        return OK;
-    }
-
     if (ae == AUDIO_ENCODER_DEFAULT) {
         mAudioEncoder = AUDIO_ENCODER_AMR_NB;
     } else {
         mAudioEncoder = ae;
     }
 
     return OK;
 }
 
 status_t GonkRecorder::setVideoEncoder(video_encoder ve) {
-    DOM_CAMERA_LOGI("%s: %d", __func__, ve);
+    RE_LOGV("setVideoEncoder: %d", ve);
     if (ve < VIDEO_ENCODER_DEFAULT ||
         ve >= VIDEO_ENCODER_LIST_END) {
-        DOM_CAMERA_LOGE("Invalid video encoder: %d", ve);
+        RE_LOGE("Invalid video encoder: %d", ve);
         return BAD_VALUE;
     }
 
     if (ve == VIDEO_ENCODER_DEFAULT) {
         mVideoEncoder = VIDEO_ENCODER_H263;
     } else {
         mVideoEncoder = ve;
     }
 
     return OK;
 }
 
 status_t GonkRecorder::setVideoSize(int width, int height) {
-    DOM_CAMERA_LOGI("%s: %dx%d", __func__, width, height);
+    RE_LOGV("setVideoSize: %dx%d", width, height);
     if (width <= 0 || height <= 0) {
-        DOM_CAMERA_LOGE("Invalid video size: %dx%d", width, height);
+        RE_LOGE("Invalid video size: %dx%d", width, height);
         return BAD_VALUE;
     }
 
     // Additional check on the dimension will be performed later
     mVideoWidth = width;
     mVideoHeight = height;
 
     return OK;
 }
 
 status_t GonkRecorder::setVideoFrameRate(int frames_per_second) {
-    DOM_CAMERA_LOGI("%s: %d", __func__, frames_per_second);
+    RE_LOGV("setVideoFrameRate: %d", frames_per_second);
     if ((frames_per_second <= 0 && frames_per_second != -1) ||
         frames_per_second > 120) {
-        DOM_CAMERA_LOGE("Invalid video frame rate: %d", frames_per_second);
+        RE_LOGE("Invalid video frame rate: %d", frames_per_second);
         return BAD_VALUE;
     }
 
     // Additional check on the frame rate will be performed later
     mFrameRate = frames_per_second;
 
     return OK;
 }
 
 status_t GonkRecorder::setOutputFile(const char *path) {
-    DOM_CAMERA_LOGE("setOutputFile(const char*) must not be called");
+    RE_LOGE("setOutputFile(const char*) must not be called");
     // We don't actually support this at all, as the media_server process
     // no longer has permissions to create files.
 
     return -EPERM;
 }
 
 status_t GonkRecorder::setOutputFile(int fd, int64_t offset, int64_t length) {
-    DOM_CAMERA_LOGI("%s: %d, %lld, %lld", __func__, fd, offset, length);
+    RE_LOGV("setOutputFile: %d, %lld, %lld", fd, offset, length);
     // These don't make any sense, do they?
-    CHECK_EQ(offset, 0);
-    CHECK_EQ(length, 0);
+    CHECK_EQ(offset, 0ll);
+    CHECK_EQ(length, 0ll);
 
     if (fd < 0) {
-        DOM_CAMERA_LOGE("Invalid file descriptor: %d", fd);
+        RE_LOGE("Invalid file descriptor: %d", fd);
         return -EBADF;
     }
 
     if (mOutputFd >= 0) {
         ::close(mOutputFd);
     }
     mOutputFd = dup(fd);
 
     return OK;
 }
 
-// Attempt to parse an int64_t literal optionally surrounded by whitespace,
+// Attempt to parse an int64 literal optionally surrounded by whitespace,
 // returns true on success, false otherwise.
 static bool safe_strtoi64(const char *s, int64_t *val) {
     char *end;
 
     // It is lame, but according to man page, we have to set errno to 0
     // before calling strtoll().
     errno = 0;
     *val = strtoll(s, &end, 10);
@@ -233,17 +229,17 @@ static bool safe_strtoi64(const char *s,
     }
 
     // Skip trailing whitespace
     while (isspace(*end)) {
         ++end;
     }
 
     // For a successful return, the string must contain nothing but a valid
-    // int64_t literal optionally surrounded by whitespace.
+    // int64 literal optionally surrounded by whitespace.
 
     return *end == '\0';
 }
 
 // Return true if the value is in [0, 0x007FFFFFFF]
 static bool safe_strtoi32(const char *s, int32_t *val) {
     int64_t temp;
     if (safe_strtoi64(s, &temp)) {
@@ -269,229 +265,224 @@ static void TrimString(String8 *s) {
     while (i > leading_space && isspace(data[i - 1])) {
         --i;
     }
 
     s->setTo(String8(&data[leading_space], i - leading_space));
 }
 
 status_t GonkRecorder::setParamAudioSamplingRate(int32_t sampleRate) {
-    DOM_CAMERA_LOGI("%s: %d", __func__, sampleRate);
+    RE_LOGV("setParamAudioSamplingRate: %d", sampleRate);
     if (sampleRate <= 0) {
-        DOM_CAMERA_LOGE("Invalid audio sampling rate: %d", sampleRate);
+        RE_LOGE("Invalid audio sampling rate: %d", sampleRate);
         return BAD_VALUE;
     }
 
     // Additional check on the sample rate will be performed later.
     mSampleRate = sampleRate;
     return OK;
 }
 
 status_t GonkRecorder::setParamAudioNumberOfChannels(int32_t channels) {
-    DOM_CAMERA_LOGI("%s: %d", __func__, channels);
+    RE_LOGV("setParamAudioNumberOfChannels: %d", channels);
     if (channels <= 0 || channels >= 3) {
-        DOM_CAMERA_LOGE("Invalid number of audio channels: %d", channels);
+        RE_LOGE("Invalid number of audio channels: %d", channels);
         return BAD_VALUE;
     }
 
     // Additional check on the number of channels will be performed later.
     mAudioChannels = channels;
     return OK;
 }
 
 status_t GonkRecorder::setParamAudioEncodingBitRate(int32_t bitRate) {
-    DOM_CAMERA_LOGI("%s: %d", __func__, bitRate);
+    RE_LOGV("setParamAudioEncodingBitRate: %d", bitRate);
     if (bitRate <= 0) {
-        DOM_CAMERA_LOGE("Invalid audio encoding bit rate: %d", bitRate);
+        RE_LOGE("Invalid audio encoding bit rate: %d", bitRate);
         return BAD_VALUE;
     }
 
     // The target bit rate may not be exactly the same as the requested.
     // It depends on many factors, such as rate control, and the bit rate
     // range that a specific encoder supports. The mismatch between the
     // the target and requested bit rate will NOT be treated as an error.
     mAudioBitRate = bitRate;
     return OK;
 }
 
 status_t GonkRecorder::setParamVideoEncodingBitRate(int32_t bitRate) {
-    DOM_CAMERA_LOGI("%s: %d", __func__, bitRate);
+    RE_LOGV("setParamVideoEncodingBitRate: %d", bitRate);
     if (bitRate <= 0) {
-        DOM_CAMERA_LOGE("Invalid video encoding bit rate: %d", bitRate);
+        RE_LOGE("Invalid video encoding bit rate: %d", bitRate);
         return BAD_VALUE;
     }
 
     // The target bit rate may not be exactly the same as the requested.
     // It depends on many factors, such as rate control, and the bit rate
     // range that a specific encoder supports. The mismatch between the
     // the target and requested bit rate will NOT be treated as an error.
     mVideoBitRate = bitRate;
     return OK;
 }
 
 // Always rotate clockwise, and only support 0, 90, 180 and 270 for now.
 status_t GonkRecorder::setParamVideoRotation(int32_t degrees) {
-    DOM_CAMERA_LOGI("%s: %d", __func__, degrees);
+    RE_LOGV("setParamVideoRotation: %d", degrees);
     if (degrees < 0 || degrees % 90 != 0) {
-        DOM_CAMERA_LOGE("Unsupported video rotation angle: %d", degrees);
+        RE_LOGE("Unsupported video rotation angle: %d", degrees);
         return BAD_VALUE;
     }
     mRotationDegrees = degrees % 360;
     return OK;
 }
 
 status_t GonkRecorder::setParamMaxFileDurationUs(int64_t timeUs) {
-    DOM_CAMERA_LOGI("%s: %lld us", __func__, timeUs);
+    RE_LOGV("setParamMaxFileDurationUs: %lld us", timeUs);
 
     // This is meant for backward compatibility for MediaRecorder.java
     if (timeUs <= 0) {
-        DOM_CAMERA_LOGW("Max file duration is not positive: %lld us. Disabling duration limit.", timeUs);
+        RE_LOGW("Max file duration is not positive: %lld us. Disabling duration limit.", timeUs);
         timeUs = 0; // Disable the duration limit for zero or negative values.
     } else if (timeUs <= 100000LL) {  // XXX: 100 milli-seconds
-        DOM_CAMERA_LOGE("Max file duration is too short: %lld us", timeUs);
+        RE_LOGE("Max file duration is too short: %lld us", timeUs);
         return BAD_VALUE;
     }
 
     if (timeUs <= 15 * 1000000LL) {
-        DOM_CAMERA_LOGW("Target duration (%lld us) too short to be respected", timeUs);
+        RE_LOGW("Target duration (%lld us) too short to be respected", timeUs);
     }
     mMaxFileDurationUs = timeUs;
     return OK;
 }
 
 status_t GonkRecorder::setParamMaxFileSizeBytes(int64_t bytes) {
-    DOM_CAMERA_LOGI("%s: %lld bytes", __func__, bytes);
+    RE_LOGV("setParamMaxFileSizeBytes: %lld bytes", bytes);
 
     // This is meant for backward compatibility for MediaRecorder.java
     if (bytes <= 0) {
-        DOM_CAMERA_LOGW("Max file size is not positive: %lld bytes. "
+        RE_LOGW("Max file size is not positive: %lld bytes. "
              "Disabling file size limit.", bytes);
         bytes = 0; // Disable the file size limit for zero or negative values.
     } else if (bytes <= 1024) {  // XXX: 1 kB
-        DOM_CAMERA_LOGE("Max file size is too small: %lld bytes", bytes);
+        RE_LOGE("Max file size is too small: %lld bytes", bytes);
         return BAD_VALUE;
     }
 
     if (bytes <= 100 * 1024) {
-        DOM_CAMERA_LOGW("Target file size (%lld bytes) is too small to be respected", bytes);
-    }
-
-    if (bytes >= 0xffffffffLL) {
-        DOM_CAMERA_LOGW("Target file size (%lld bytes) too larger than supported, clip to 4GB", bytes);
-        bytes = 0xffffffffLL;
+        RE_LOGW("Target file size (%lld bytes) is too small to be respected", bytes);
     }
 
     mMaxFileSizeBytes = bytes;
     return OK;
 }
 
 status_t GonkRecorder::setParamInterleaveDuration(int32_t durationUs) {
-    DOM_CAMERA_LOGI("%s: %d", __func__, durationUs);
+    RE_LOGV("setParamInterleaveDuration: %d", durationUs);
     if (durationUs <= 500000) {           //  500 ms
         // If interleave duration is too small, it is very inefficient to do
         // interleaving since the metadata overhead will count for a significant
         // portion of the saved contents
-        DOM_CAMERA_LOGE("Audio/video interleave duration is too small: %d us", durationUs);
+        RE_LOGE("Audio/video interleave duration is too small: %d us", durationUs);
         return BAD_VALUE;
     } else if (durationUs >= 10000000) {  // 10 seconds
         // If interleaving duration is too large, it can cause the recording
         // session to use too much memory since we have to save the output
         // data before we write them out
-        DOM_CAMERA_LOGE("Audio/video interleave duration is too large: %d us", durationUs);
+        RE_LOGE("Audio/video interleave duration is too large: %d us", durationUs);
         return BAD_VALUE;
     }
     mInterleaveDurationUs = durationUs;
     return OK;
 }
 
 // If seconds <  0, only the first frame is I frame, and rest are all P frames
 // If seconds == 0, all frames are encoded as I frames. No P frames
 // If seconds >  0, it is the time spacing (seconds) between 2 neighboring I frames
 status_t GonkRecorder::setParamVideoIFramesInterval(int32_t seconds) {
-    DOM_CAMERA_LOGI("%s: %d seconds", __func__, seconds);
+    RE_LOGV("setParamVideoIFramesInterval: %d seconds", seconds);
     mIFramesIntervalSec = seconds;
     return OK;
 }
 
 status_t GonkRecorder::setParam64BitFileOffset(bool use64Bit) {
-    DOM_CAMERA_LOGI("%s: %s", __func__,
+    RE_LOGV("setParam64BitFileOffset: %s",
         use64Bit? "use 64 bit file offset": "use 32 bit file offset");
     mUse64BitFileOffset = use64Bit;
     return OK;
 }
 
 status_t GonkRecorder::setParamVideoCameraId(int32_t cameraId) {
-    DOM_CAMERA_LOGI("%s: %d", __func__, cameraId);
+    RE_LOGV("setParamVideoCameraId: %d", cameraId);
     if (cameraId < 0) {
         return BAD_VALUE;
     }
     mCameraId = cameraId;
     return OK;
 }
 
 status_t GonkRecorder::setParamTrackTimeStatus(int64_t timeDurationUs) {
-    DOM_CAMERA_LOGI("%s: %lld", __func__, timeDurationUs);
+    RE_LOGV("setParamTrackTimeStatus: %lld", timeDurationUs);
     if (timeDurationUs < 20000) {  // Infeasible if shorter than 20 ms?
-        DOM_CAMERA_LOGE("Tracking time duration too short: %lld us", timeDurationUs);
+        RE_LOGE("Tracking time duration too short: %lld us", timeDurationUs);
         return BAD_VALUE;
     }
     mTrackEveryTimeDurationUs = timeDurationUs;
     return OK;
 }
 
 status_t GonkRecorder::setParamVideoEncoderProfile(int32_t profile) {
-    DOM_CAMERA_LOGI("%s: %d", __func__, profile);
+    RE_LOGV("setParamVideoEncoderProfile: %d", profile);
 
     // Additional check will be done later when we load the encoder.
     // For now, we are accepting values defined in OpenMAX IL.
     mVideoEncoderProfile = profile;
     return OK;
 }
 
 status_t GonkRecorder::setParamVideoEncoderLevel(int32_t level) {
-    DOM_CAMERA_LOGI("%s: %d", __func__, level);
+    RE_LOGV("setParamVideoEncoderLevel: %d", level);
 
     // Additional check will be done later when we load the encoder.
     // For now, we are accepting values defined in OpenMAX IL.
     mVideoEncoderLevel = level;
     return OK;
 }
 
 status_t GonkRecorder::setParamMovieTimeScale(int32_t timeScale) {
-    DOM_CAMERA_LOGI("%s: %d", __func__, timeScale);
+    RE_LOGV("setParamMovieTimeScale: %d", timeScale);
 
     // The range is set to be the same as the audio's time scale range
     // since audio's time scale has a wider range.
     if (timeScale < 600 || timeScale > 96000) {
-        DOM_CAMERA_LOGE("Time scale (%d) for movie is out of range [600, 96000]", timeScale);
+        RE_LOGE("Time scale (%d) for movie is out of range [600, 96000]", timeScale);
         return BAD_VALUE;
     }
     mMovieTimeScale = timeScale;
     return OK;
 }
 
 status_t GonkRecorder::setParamVideoTimeScale(int32_t timeScale) {
-    DOM_CAMERA_LOGI("%s: %d", __func__, timeScale);
+    RE_LOGV("setParamVideoTimeScale: %d", timeScale);
 
     // 60000 is chosen to make sure that each video frame from a 60-fps
     // video has 1000 ticks.
     if (timeScale < 600 || timeScale > 60000) {
-        DOM_CAMERA_LOGE("Time scale (%d) for video is out of range [600, 60000]", timeScale);
+        RE_LOGE("Time scale (%d) for video is out of range [600, 60000]", timeScale);
         return BAD_VALUE;
     }
     mVideoTimeScale = timeScale;
     return OK;
 }
 
 status_t GonkRecorder::setParamAudioTimeScale(int32_t timeScale) {
-    DOM_CAMERA_LOGI("%s: %d", __func__, timeScale);
+    RE_LOGV("setParamAudioTimeScale: %d", timeScale);
 
     // 96000 Hz is the highest sampling rate support in AAC.
     if (timeScale < 600 || timeScale > 96000) {
-        DOM_CAMERA_LOGE("Time scale (%d) for audio is out of range [600, 96000]", timeScale);
+        RE_LOGE("Time scale (%d) for audio is out of range [600, 96000]", timeScale);
         return BAD_VALUE;
     }
     mAudioTimeScale = timeScale;
     return OK;
 }
 
 status_t GonkRecorder::setParamGeoDataLongitude(
     int64_t longitudex10000) {
@@ -510,17 +501,17 @@ status_t GonkRecorder::setParamGeoDataLa
         return BAD_VALUE;
     }
     mLatitudex10000 = latitudex10000;
     return OK;
 }
 
 status_t GonkRecorder::setParameter(
         const String8 &key, const String8 &value) {
-    DOM_CAMERA_LOGI("%s: key (%s) => value (%s)", __func__, key.string(), value.string());
+    RE_LOGV("setParameter: key (%s) => value (%s)", key.string(), value.string());
     if (key == "max-duration") {
         int64_t max_duration_ms;
         if (safe_strtoi64(value.string(), &max_duration_ms)) {
             return setParamMaxFileDurationUs(1000LL * max_duration_ms);
         }
     } else if (key == "max-filesize") {
         int64_t max_filesize_bytes;
         if (safe_strtoi64(value.string(), &max_filesize_bytes)) {
@@ -607,35 +598,35 @@ status_t GonkRecorder::setParameter(
             return setParamVideoCameraId(cameraId);
         }
     } else if (key == "video-param-time-scale") {
         int32_t timeScale;
         if (safe_strtoi32(value.string(), &timeScale)) {
             return setParamVideoTimeScale(timeScale);
         }
     } else {
-        DOM_CAMERA_LOGE("setParameter: failed to find key %s", key.string());
+        RE_LOGE("setParameter: failed to find key %s", key.string());
     }
     return BAD_VALUE;
 }
 
 status_t GonkRecorder::setParameters(const String8 &params) {
-    DOM_CAMERA_LOGI("%s: %s", __func__, params.string());
+    RE_LOGV("setParameters: %s", params.string());
     const char *cparams = params.string();
     const char *key_start = cparams;
     for (;;) {
         const char *equal_pos = strchr(key_start, '=');
         if (equal_pos == NULL) {
-            DOM_CAMERA_LOGE("Parameters %s miss a value", cparams);
+            RE_LOGE("Parameters %s miss a value", cparams);
             return BAD_VALUE;
         }
         String8 key(key_start, equal_pos - key_start);
         TrimString(&key);
         if (key.length() == 0) {
-            DOM_CAMERA_LOGE("Parameters %s contains an empty key", cparams);
+            RE_LOGE("Parameters %s contains an empty key", cparams);
             return BAD_VALUE;
         }
         const char *value_start = equal_pos + 1;
         const char *semicolon_pos = strchr(value_start, ';');
         String8 value;
         if (semicolon_pos == NULL) {
             value.setTo(value_start);
         } else {
@@ -653,36 +644,33 @@ status_t GonkRecorder::setParameters(con
 }
 
 status_t GonkRecorder::setListener(const sp<IMediaRecorderClient> &listener) {
     mListener = listener;
 
     return OK;
 }
 
-status_t GonkRecorder::prepare() {
-  DOM_CAMERA_LOGI(" %s E", __func__ );
+status_t GonkRecorder::setClientName(const String16& clientName) {
+    mClientName = clientName;
 
-  if(mVideoSource != VIDEO_SOURCE_LIST_END && mVideoEncoder != VIDEO_ENCODER_LIST_END && mVideoHeight && mVideoWidth &&             /*Video recording*/
-         (mMaxFileDurationUs <=0 ||             /*Max duration is not set*/
-         (mVideoHeight * mVideoWidth < 720 * 1280 && mMaxFileDurationUs > 30*60*1000*1000) ||
-         (mVideoHeight * mVideoWidth >= 720 * 1280 && mMaxFileDurationUs > 10*60*1000*1000))) {
-    /*Above Check can be further optimized for lower resolutions to reduce file size*/
-    DOM_CAMERA_LOGI("File is huge so setting 64 bit file offsets");
-    setParam64BitFileOffset(true);
-  }
-  DOM_CAMERA_LOGI(" %s X", __func__ );
-  return OK;
+    return OK;
+}
+
+status_t GonkRecorder::prepare() {
+    return OK;
 }
 
 status_t GonkRecorder::start() {
-    CHECK(mOutputFd >= 0);
+    CHECK_GE(mOutputFd, 0);
 
+    // Get UID here for permission checking
+    mClientUid = IPCThreadState::self()->getCallingUid();
     if (mWriter != NULL) {
-        DOM_CAMERA_LOGE("File writer is not available");
+        RE_LOGE("File writer is not avaialble");
         return UNKNOWN_ERROR;
     }
 
     status_t status = OK;
 
     switch (mOutputFormat) {
         case OUTPUT_FORMAT_DEFAULT:
         case OUTPUT_FORMAT_THREE_GPP:
@@ -690,62 +678,84 @@ status_t GonkRecorder::start() {
             status = startMPEG4Recording();
             break;
 
         case OUTPUT_FORMAT_AMR_NB:
         case OUTPUT_FORMAT_AMR_WB:
             status = startAMRRecording();
             break;
 
+#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 18
+        case OUTPUT_FORMAT_AAC_ADIF:
+        case OUTPUT_FORMAT_AAC_ADTS:
+            status = startAACRecording();
+            break;
+#endif
+
+        case OUTPUT_FORMAT_RTP_AVP:
+            status = startRTPRecording();
+            break;
+
         case OUTPUT_FORMAT_MPEG2TS:
             status = startMPEG2TSRecording();
-		    break;
+            break;
+
         default:
-            DOM_CAMERA_LOGE("Unsupported output file format: %d", mOutputFormat);
+            RE_LOGE("Unsupported output file format: %d", mOutputFormat);
             status = UNKNOWN_ERROR;
             break;
     }
 
     if ((status == OK) && (!mStarted)) {
         mStarted = true;
     }
 
     return status;
 }
 
 sp<MediaSource> GonkRecorder::createAudioSource() {
-
     sp<AudioSource> audioSource =
         new AudioSource(
                 mAudioSource,
                 mSampleRate,
                 mAudioChannels);
 
     status_t err = audioSource->initCheck();
 
     if (err != OK) {
-        DOM_CAMERA_LOGE("audio source is not initialized");
+        RE_LOGE("audio source is not initialized");
         return NULL;
     }
 
     sp<MetaData> encMeta = new MetaData;
     const char *mime;
     switch (mAudioEncoder) {
         case AUDIO_ENCODER_AMR_NB:
         case AUDIO_ENCODER_DEFAULT:
             mime = MEDIA_MIMETYPE_AUDIO_AMR_NB;
             break;
         case AUDIO_ENCODER_AMR_WB:
             mime = MEDIA_MIMETYPE_AUDIO_AMR_WB;
             break;
+#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 18
         case AUDIO_ENCODER_AAC:
             mime = MEDIA_MIMETYPE_AUDIO_AAC;
+            encMeta->setInt32(kKeyAACProfile, OMX_AUDIO_AACObjectLC);
             break;
+        case AUDIO_ENCODER_HE_AAC:
+            mime = MEDIA_MIMETYPE_AUDIO_AAC;
+            encMeta->setInt32(kKeyAACProfile, OMX_AUDIO_AACObjectHE);
+            break;
+        case AUDIO_ENCODER_AAC_ELD:
+            mime = MEDIA_MIMETYPE_AUDIO_AAC;
+            encMeta->setInt32(kKeyAACProfile, OMX_AUDIO_AACObjectELD);
+            break;
+#endif
         default:
-            DOM_CAMERA_LOGE("Unknown audio encoder: %d", mAudioEncoder);
+            RE_LOGE("Unknown audio encoder: %d", mAudioEncoder);
             return NULL;
     }
     encMeta->setCString(kKeyMIMEType, mime);
 
     int32_t maxInputSize;
     CHECK(audioSource->getFormat()->findInt32(
                 kKeyMaxInputSize, &maxInputSize));
 
@@ -756,57 +766,78 @@ sp<MediaSource> GonkRecorder::createAudi
     if (mAudioTimeScale > 0) {
         encMeta->setInt32(kKeyTimeScale, mAudioTimeScale);
     }
 
     // OMXClient::connect() always returns OK and abort's fatally if
     // it can't connect.
     OMXClient client;
     // CHECK_EQ causes an abort if the given condition fails.
-    CHECK_EQ(client.connect(), OK);
-
+    CHECK_EQ(client.connect(), (status_t)OK);
     sp<MediaSource> audioEncoder =
         OMXCodec::Create(client.interface(), encMeta,
                          true /* createEncoder */, audioSource);
     mAudioSourceNode = audioSource;
 
     return audioEncoder;
 }
 
+#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 18
+status_t GonkRecorder::startAACRecording() {
+    // FIXME:
+    // Add support for OUTPUT_FORMAT_AAC_ADIF
+    CHECK_EQ(mOutputFormat, OUTPUT_FORMAT_AAC_ADTS);
+
+    CHECK(mAudioEncoder == AUDIO_ENCODER_AAC ||
+          mAudioEncoder == AUDIO_ENCODER_HE_AAC ||
+          mAudioEncoder == AUDIO_ENCODER_AAC_ELD);
+    CHECK(mAudioSource != AUDIO_SOURCE_CNT);
+
+    mWriter = new AACWriter(mOutputFd);
+    status_t status = startRawAudioRecording();
+    if (status != OK) {
+        mWriter.clear();
+        mWriter = NULL;
+    }
+
+    return status;
+}
+#endif
+
 status_t GonkRecorder::startAMRRecording() {
     CHECK(mOutputFormat == OUTPUT_FORMAT_AMR_NB ||
           mOutputFormat == OUTPUT_FORMAT_AMR_WB);
 
     if (mOutputFormat == OUTPUT_FORMAT_AMR_NB) {
         if (mAudioEncoder != AUDIO_ENCODER_DEFAULT &&
             mAudioEncoder != AUDIO_ENCODER_AMR_NB) {
-            DOM_CAMERA_LOGE("Invalid encoder %d used for AMRNB recording",
+            RE_LOGE("Invalid encoder %d used for AMRNB recording",
                     mAudioEncoder);
             return BAD_VALUE;
         }
     } else {  // mOutputFormat must be OUTPUT_FORMAT_AMR_WB
         if (mAudioEncoder != AUDIO_ENCODER_AMR_WB) {
-            DOM_CAMERA_LOGE("Invalid encoder %d used for AMRWB recording",
+            RE_LOGE("Invlaid encoder %d used for AMRWB recording",
                     mAudioEncoder);
             return BAD_VALUE;
         }
     }
 
     mWriter = new AMRWriter(mOutputFd);
     status_t status = startRawAudioRecording();
     if (status != OK) {
         mWriter.clear();
         mWriter = NULL;
     }
     return status;
 }
 
 status_t GonkRecorder::startRawAudioRecording() {
     if (mAudioSource >= AUDIO_SOURCE_CNT) {
-        DOM_CAMERA_LOGE("Invalid audio source: %d", mAudioSource);
+        RE_LOGE("Invalid audio source: %d", mAudioSource);
         return BAD_VALUE;
     }
 
     status_t status = BAD_VALUE;
     if (OK != (status = checkAudioEncoderCapabilities())) {
         return status;
     }
 
@@ -825,26 +856,33 @@ status_t GonkRecorder::startRawAudioReco
         mWriter->setMaxFileSize(mMaxFileSizeBytes);
     }
     mWriter->setListener(mListener);
     mWriter->start();
 
     return OK;
 }
 
+status_t GonkRecorder::startRTPRecording() {
+    return INVALID_OPERATION;
+}
+
 status_t GonkRecorder::startMPEG2TSRecording() {
     CHECK_EQ(mOutputFormat, OUTPUT_FORMAT_MPEG2TS);
 
     sp<MediaWriter> writer = new MPEG2TSWriter(mOutputFd);
 
     if (mAudioSource != AUDIO_SOURCE_CNT) {
-        if (mAudioEncoder != AUDIO_ENCODER_AAC) {
+#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 18
+        if (mAudioEncoder != AUDIO_ENCODER_AAC &&
+            mAudioEncoder != AUDIO_ENCODER_HE_AAC &&
+            mAudioEncoder != AUDIO_ENCODER_AAC_ELD) {
             return ERROR_UNSUPPORTED;
         }
-
+#endif
         status_t err = setupAudioEncoder(writer);
 
         if (err != OK) {
             return err;
         }
     }
 
     if (mVideoSource < VIDEO_SOURCE_LIST_END) {
@@ -877,81 +915,82 @@ status_t GonkRecorder::startMPEG2TSRecor
     }
 
     mWriter = writer;
 
     return mWriter->start();
 }
 
 void GonkRecorder::clipVideoFrameRate() {
-    DOM_CAMERA_LOGI("%s: encoder %d", __func__, mVideoEncoder);
+    RE_LOGV("clipVideoFrameRate: encoder %d", mVideoEncoder);
     int minFrameRate = mEncoderProfiles->getVideoEncoderParamByName(
                         "enc.vid.fps.min", mVideoEncoder);
     int maxFrameRate = mEncoderProfiles->getVideoEncoderParamByName(
                         "enc.vid.fps.max", mVideoEncoder);
-    if (mFrameRate < minFrameRate && mFrameRate != -1) {
-        DOM_CAMERA_LOGW("Intended video encoding frame rate (%d fps) is too small"
+    if (mFrameRate < minFrameRate && minFrameRate != -1) {
+        RE_LOGW("Intended video encoding frame rate (%d fps) is too small"
              " and will be set to (%d fps)", mFrameRate, minFrameRate);
         mFrameRate = minFrameRate;
-    } else if (mFrameRate > maxFrameRate) {
-        DOM_CAMERA_LOGW("Intended video encoding frame rate (%d fps) is too large"
+    } else if (mFrameRate > maxFrameRate && maxFrameRate != -1) {
+        RE_LOGW("Intended video encoding frame rate (%d fps) is too large"
              " and will be set to (%d fps)", mFrameRate, maxFrameRate);
         mFrameRate = maxFrameRate;
     }
 }
 
 void GonkRecorder::clipVideoBitRate() {
-    DOM_CAMERA_LOGI("%s: encoder %d", __func__, mVideoEncoder);
+    RE_LOGV("clipVideoBitRate: encoder %d", mVideoEncoder);
     int minBitRate = mEncoderProfiles->getVideoEncoderParamByName(
                         "enc.vid.bps.min", mVideoEncoder);
     int maxBitRate = mEncoderProfiles->getVideoEncoderParamByName(
                         "enc.vid.bps.max", mVideoEncoder);
-    if (mVideoBitRate < minBitRate) {
-        DOM_CAMERA_LOGW("Intended video encoding bit rate (%d bps) is too small"
+    if (mVideoBitRate < minBitRate && minBitRate != -1) {
+        RE_LOGW("Intended video encoding bit rate (%d bps) is too small"
              " and will be set to (%d bps)", mVideoBitRate, minBitRate);
         mVideoBitRate = minBitRate;
-    } else if (mVideoBitRate > maxBitRate) {
-        DOM_CAMERA_LOGW("Intended video encoding bit rate (%d bps) is too large"
+    } else if (mVideoBitRate > maxBitRate && maxBitRate != -1) {
+        RE_LOGW("Intended video encoding bit rate (%d bps) is too large"
              " and will be set to (%d bps)", mVideoBitRate, maxBitRate);
         mVideoBitRate = maxBitRate;
     }
 }
 
 void GonkRecorder::clipVideoFrameWidth() {
-    DOM_CAMERA_LOGI("%s: encoder %d", __func__, mVideoEncoder);
+    RE_LOGV("clipVideoFrameWidth: encoder %d", mVideoEncoder);
     int minFrameWidth = mEncoderProfiles->getVideoEncoderParamByName(
                         "enc.vid.width.min", mVideoEncoder);
     int maxFrameWidth = mEncoderProfiles->getVideoEncoderParamByName(
                         "enc.vid.width.max", mVideoEncoder);
-    if (mVideoWidth < minFrameWidth) {
-        DOM_CAMERA_LOGW("Intended video encoding frame width (%d) is too small"
+    if (mVideoWidth < minFrameWidth && minFrameWidth != -1) {
+        RE_LOGW("Intended video encoding frame width (%d) is too small"
              " and will be set to (%d)", mVideoWidth, minFrameWidth);
         mVideoWidth = minFrameWidth;
-    } else if (mVideoWidth > maxFrameWidth) {
-        DOM_CAMERA_LOGW("Intended video encoding frame width (%d) is too large"
+    } else if (mVideoWidth > maxFrameWidth && maxFrameWidth != -1) {
+        RE_LOGW("Intended video encoding frame width (%d) is too large"
              " and will be set to (%d)", mVideoWidth, maxFrameWidth);
         mVideoWidth = maxFrameWidth;
     }
 }
 
 status_t GonkRecorder::checkVideoEncoderCapabilities() {
-        // Dont clip for time lapse capture as encoder will have enough
-        // time to encode because of slow capture rate of time lapse.
-        clipVideoBitRate();
-        clipVideoFrameRate();
-        clipVideoFrameWidth();
-        clipVideoFrameHeight();
-        setDefaultProfileIfNecessary();
+
+    // Dont clip for time lapse capture as encoder will have enough
+    // time to encode because of slow capture rate of time lapse.
+    clipVideoBitRate();
+    clipVideoFrameRate();
+    clipVideoFrameWidth();
+    clipVideoFrameHeight();
+    setDefaultProfileIfNecessary();
     return OK;
 }
 
 // Set to use AVC baseline profile if the encoding parameters matches
 // CAMCORDER_QUALITY_LOW profile; this is for the sake of MMS service.
 void GonkRecorder::setDefaultProfileIfNecessary() {
-    DOM_CAMERA_LOGI("%s", __func__);
+    RE_LOGV("setDefaultProfileIfNecessary");
 
     camcorder_quality quality = CAMCORDER_QUALITY_LOW;
 
     int64_t durationUs   = mEncoderProfiles->getCamcorderProfileParamByName(
                                 "duration", mCameraId, quality) * 1000000LL;
 
     int fileFormat       = mEncoderProfiles->getCamcorderProfileParamByName(
                                 "file.format", mCameraId, quality);
@@ -990,107 +1029,107 @@ void GonkRecorder::setDefaultProfileIfNe
         videoFrameRate == mFrameRate &&
         videoFrameWidth == mVideoWidth &&
         videoFrameHeight == mVideoHeight &&
         audioCodec == mAudioEncoder &&
         audioBitRate == mAudioBitRate &&
         audioSampleRate == mSampleRate &&
         audioChannels == mAudioChannels) {
         if (videoCodec == VIDEO_ENCODER_H264) {
-            DOM_CAMERA_LOGI("Force to use AVC baseline profile");
+            RE_LOGI("Force to use AVC baseline profile");
             setParamVideoEncoderProfile(OMX_VIDEO_AVCProfileBaseline);
         }
     }
 }
 
 status_t GonkRecorder::checkAudioEncoderCapabilities() {
     clipAudioBitRate();
     clipAudioSampleRate();
     clipNumberOfAudioChannels();
     return OK;
 }
 
 void GonkRecorder::clipAudioBitRate() {
-    DOM_CAMERA_LOGI("%s: encoder %d", __func__, mAudioEncoder);
+    RE_LOGV("clipAudioBitRate: encoder %d", mAudioEncoder);
 
     int minAudioBitRate =
             mEncoderProfiles->getAudioEncoderParamByName(
                 "enc.aud.bps.min", mAudioEncoder);
-    if (mAudioBitRate < minAudioBitRate) {
-        DOM_CAMERA_LOGW("Intended audio encoding bit rate (%d) is too small"
+    if (minAudioBitRate != -1 && mAudioBitRate < minAudioBitRate) {
+        RE_LOGW("Intended audio encoding bit rate (%d) is too small"
             " and will be set to (%d)", mAudioBitRate, minAudioBitRate);
         mAudioBitRate = minAudioBitRate;
     }
 
     int maxAudioBitRate =
             mEncoderProfiles->getAudioEncoderParamByName(
                 "enc.aud.bps.max", mAudioEncoder);
-    if (mAudioBitRate > maxAudioBitRate) {
-        DOM_CAMERA_LOGW("Intended audio encoding bit rate (%d) is too large"
+    if (maxAudioBitRate != -1 && mAudioBitRate > maxAudioBitRate) {
+        RE_LOGW("Intended audio encoding bit rate (%d) is too large"
             " and will be set to (%d)", mAudioBitRate, maxAudioBitRate);
         mAudioBitRate = maxAudioBitRate;
     }
 }
 
 void GonkRecorder::clipAudioSampleRate() {
-    DOM_CAMERA_LOGI("%s: encoder %d", __func__, mAudioEncoder);
+    RE_LOGV("clipAudioSampleRate: encoder %d", mAudioEncoder);
 
     int minSampleRate =
             mEncoderProfiles->getAudioEncoderParamByName(
                 "enc.aud.hz.min", mAudioEncoder);
-    if (mSampleRate < minSampleRate) {
-        DOM_CAMERA_LOGW("Intended audio sample rate (%d) is too small"
+    if (minSampleRate != -1 && mSampleRate < minSampleRate) {
+        RE_LOGW("Intended audio sample rate (%d) is too small"
             " and will be set to (%d)", mSampleRate, minSampleRate);
         mSampleRate = minSampleRate;
     }
 
     int maxSampleRate =
             mEncoderProfiles->getAudioEncoderParamByName(
                 "enc.aud.hz.max", mAudioEncoder);
-    if (mSampleRate > maxSampleRate) {
-        DOM_CAMERA_LOGW("Intended audio sample rate (%d) is too large"
+    if (maxSampleRate != -1 && mSampleRate > maxSampleRate) {
+        RE_LOGW("Intended audio sample rate (%d) is too large"
             " and will be set to (%d)", mSampleRate, maxSampleRate);
         mSampleRate = maxSampleRate;
     }
 }
 
 void GonkRecorder::clipNumberOfAudioChannels() {
-    DOM_CAMERA_LOGI("%s: encoder %d", __func__, mAudioEncoder);
+    RE_LOGV("clipNumberOfAudioChannels: encoder %d", mAudioEncoder);
 
     int minChannels =
             mEncoderProfiles->getAudioEncoderParamByName(
                 "enc.aud.ch.min", mAudioEncoder);
-    if (mAudioChannels < minChannels) {
-        DOM_CAMERA_LOGW("Intended number of audio channels (%d) is too small"
+    if (minChannels != -1 && mAudioChannels < minChannels) {
+        RE_LOGW("Intended number of audio channels (%d) is too small"
             " and will be set to (%d)", mAudioChannels, minChannels);
         mAudioChannels = minChannels;
     }
 
     int maxChannels =
             mEncoderProfiles->getAudioEncoderParamByName(
                 "enc.aud.ch.max", mAudioEncoder);
-    if (mAudioChannels > maxChannels) {
-        DOM_CAMERA_LOGW("Intended number of audio channels (%d) is too large"
+    if (maxChannels != -1 && mAudioChannels > maxChannels) {
+        RE_LOGW("Intended number of audio channels (%d) is too large"
             " and will be set to (%d)", mAudioChannels, maxChannels);
         mAudioChannels = maxChannels;
     }
 }
 
 void GonkRecorder::clipVideoFrameHeight() {
-    DOM_CAMERA_LOGI("%s: encoder %d", __func__, mVideoEncoder);
+    RE_LOGV("clipVideoFrameHeight: encoder %d", mVideoEncoder);
     int minFrameHeight = mEncoderProfiles->getVideoEncoderParamByName(
                         "enc.vid.height.min", mVideoEncoder);
     int maxFrameHeight = mEncoderProfiles->getVideoEncoderParamByName(
                         "enc.vid.height.max", mVideoEncoder);
-    if (mVideoHeight < minFrameHeight) {
-        DOM_CAMERA_LOGW("Intended video encoding frame height (%d) is too small"
+    if (minFrameHeight != -1 && mVideoHeight < minFrameHeight) {
+        RE_LOGW("Intended video encoding frame height (%d) is too small"
              " and will be set to (%d)", mVideoHeight, minFrameHeight);
         mVideoHeight = minFrameHeight;
-    } else if (mVideoHeight > maxFrameHeight) {
-        DOM_CAMERA_LOGW("Intended video encoding frame height (%d) is too large"
+    } else if (maxFrameHeight != -1 && mVideoHeight > maxFrameHeight) {
+        RE_LOGW("Intended video encoding frame height (%d) is too large"
              " and will be set to (%d)", mVideoHeight, maxFrameHeight);
         mVideoHeight = maxFrameHeight;
     }
 }
 
 // Set up the appropriate MediaSource depending on the chosen option
 status_t GonkRecorder::setupMediaSource(
                       sp<MediaSource> *mediaSource) {
@@ -1139,17 +1178,17 @@ status_t GonkRecorder::setupCameraSource
     }
 
     // When frame rate is not set, the actual frame rate will be set to
     // the current frame rate being used.
     if (mFrameRate == -1) {
         int32_t frameRate = 0;
         CHECK ((*cameraSource)->getFormat()->findInt32(
                     kKeyFrameRate, &frameRate));
-        DOM_CAMERA_LOGI("Frame rate is not explicitly set. Use the current frame "
+        RE_LOGI("Frame rate is not explicitly set. Use the current frame "
              "rate (%d fps)", frameRate);
         mFrameRate = frameRate;
     }
 
     CHECK(mFrameRate != -1);
 
     mIsMetaDataStoredInVideoBuffers =
         (*cameraSource)->isMetaDataStoredInVideoBuffers();
@@ -1198,94 +1237,40 @@ status_t GonkRecorder::setupVideoEncoder
     enc_meta->setInt32(kKeyHeight, height);
     enc_meta->setInt32(kKeyIFramesInterval, mIFramesIntervalSec);
     enc_meta->setInt32(kKeyStride, stride);
     enc_meta->setInt32(kKeySliceHeight, sliceHeight);
     enc_meta->setInt32(kKeyColorFormat, colorFormat);
     if (mVideoTimeScale > 0) {
         enc_meta->setInt32(kKeyTimeScale, mVideoTimeScale);
     }
-
-    /*
-     * can set profile from the app as a parameter.
-     * For the mean time, set from shell
-     */
-
-    char value[PROPERTY_VALUE_MAX];
-    bool customProfile = false;
-
-    if (property_get("encoder.video.profile", value, NULL) > 0) {
-        customProfile = true;
-    }
-
-    if (customProfile) {
-        switch ( mVideoEncoder ) {
-        case VIDEO_ENCODER_H264:
-            if (strncmp("base", value, 4) == 0) {
-                mVideoEncoderProfile = OMX_VIDEO_AVCProfileBaseline;
-                DOM_CAMERA_LOGI("H264 Baseline Profile");
-            }
-            else if (strncmp("main", value, 4) == 0) {
-                mVideoEncoderProfile = OMX_VIDEO_AVCProfileMain;
-                DOM_CAMERA_LOGI("H264 Main Profile");
-            }
-            else if (strncmp("high", value, 4) == 0) {
-                mVideoEncoderProfile = OMX_VIDEO_AVCProfileHigh;
-                DOM_CAMERA_LOGI("H264 High Profile");
-            }
-            else {
-               DOM_CAMERA_LOGW("Unsupported H264 Profile");
-            }
-            break;
-        case VIDEO_ENCODER_MPEG_4_SP:
-            if (strncmp("simple", value, 5) == 0 ) {
-                mVideoEncoderProfile = OMX_VIDEO_MPEG4ProfileSimple;
-                DOM_CAMERA_LOGI("MPEG4 Simple profile");
-            }
-            else if (strncmp("asp", value, 3) == 0 ) {
-                mVideoEncoderProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple;
-                DOM_CAMERA_LOGI("MPEG4 Advanced Simple Profile");
-            }
-            else {
-                DOM_CAMERA_LOGW("Unsupported MPEG4 Profile");
-            }
-            break;
-        default:
-            DOM_CAMERA_LOGW("No custom profile support for other codecs");
-            break;
-        }
-    }
-
     if (mVideoEncoderProfile != -1) {
         enc_meta->setInt32(kKeyVideoProfile, mVideoEncoderProfile);
     }
     if (mVideoEncoderLevel != -1) {
         enc_meta->setInt32(kKeyVideoLevel, mVideoEncoderLevel);
     }
 
-    uint32_t encoder_flags = 0;
-    if (mIsMetaDataStoredInVideoBuffers) {
-        DOM_CAMERA_LOGW("Camera source supports metadata mode, create OMXCodec for metadata");
-        encoder_flags |= OMXCodec::kHardwareCodecsOnly;
-        encoder_flags |= OMXCodec::kStoreMetaDataInVideoBuffers;
-        encoder_flags |= OMXCodec::kOnlySubmitOneInputBufferAtOneTime;
-    }
-
     // OMXClient::connect() always returns OK and abort's fatally if
     // it can't connect.
     OMXClient client;
     // CHECK_EQ causes an abort if the given condition fails.
-    CHECK_EQ(client.connect(), OK);
+    CHECK_EQ(client.connect(), (status_t)OK);
+
+    uint32_t encoder_flags = 0;
+    if (mIsMetaDataStoredInVideoBuffers) {
+        encoder_flags |= OMXCodec::kStoreMetaDataInVideoBuffers;
+    }
 
     sp<MediaSource> encoder = OMXCodec::Create(
             client.interface(), enc_meta,
             true /* createEncoder */, cameraSource,
             NULL, encoder_flags);
     if (encoder == NULL) {
-        DOM_CAMERA_LOGW("Failed to create the encoder");
+        RE_LOGW("Failed to create the encoder");
         // When the encoder fails to be created, we need
         // release the camera source due to the camera's lock
         // and unlock mechanism.
         cameraSource->stop();
         return UNKNOWN_ERROR;
     }
 
     *source = encoder;
@@ -1297,21 +1282,25 @@ status_t GonkRecorder::setupAudioEncoder
     status_t status = BAD_VALUE;
     if (OK != (status = checkAudioEncoderCapabilities())) {
         return status;
     }
 
     switch(mAudioEncoder) {
         case AUDIO_ENCODER_AMR_NB:
         case AUDIO_ENCODER_AMR_WB:
+#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 18
         case AUDIO_ENCODER_AAC:
+        case AUDIO_ENCODER_HE_AAC:
+        case AUDIO_ENCODER_AAC_ELD:
+#endif
             break;
 
         default:
-            DOM_CAMERA_LOGE("Unsupported audio encoder: %d", mAudioEncoder);
+            RE_LOGE("Unsupported audio encoder: %d", mAudioEncoder);
             return UNKNOWN_ERROR;
     }
 
     sp<MediaSource> audioEncoder = createAudioSource();
     if (audioEncoder == NULL) {
         return UNKNOWN_ERROR;
     }
 
@@ -1394,17 +1383,17 @@ void GonkRecorder::setupMPEG4MetaData(in
     }
     if (mTrackEveryTimeDurationUs > 0) {
         (*meta)->setInt64(kKeyTrackTimeStatus, mTrackEveryTimeDurationUs);
     }
 
     char value[PROPERTY_VALUE_MAX];
     if (property_get("debug.camcorder.rotation", value, 0) > 0 && atoi(value) >= 0) {
         mRotationDegrees = atoi(value);
-        DOM_CAMERA_LOGI("Setting rotation to %d", mRotationDegrees );
+        RE_LOGI("Setting rotation to %d", mRotationDegrees );
     }
 
     if (mRotationDegrees != 0) {
         (*meta)->setInt32(kKeyRotation, mRotationDegrees);
     }
 }
 
 status_t GonkRecorder::startMPEG4Recording() {
@@ -1431,32 +1420,32 @@ status_t GonkRecorder::startMPEG4Recordi
     if (err != OK) {
         return err;
     }
 
     return OK;
 }
 
 status_t GonkRecorder::pause() {
-    DOM_CAMERA_LOGI("%s", __func__);
+    RE_LOGV("pause");
     if (mWriter == NULL) {
         return UNKNOWN_ERROR;
     }
     mWriter->pause();
 
     if (mStarted) {
         mStarted = false;
     }
 
 
     return OK;
 }
 
 status_t GonkRecorder::stop() {
-    DOM_CAMERA_LOGI("%s", __func__);
+    RE_LOGV("stop");
     status_t err = OK;
 
     if (mWriter != NULL) {
         err = mWriter->stop();
         mWriter.clear();
     }
 
     if (mOutputFd >= 0) {
@@ -1468,24 +1457,24 @@ status_t GonkRecorder::stop() {
         mStarted = false;
     }
 
 
     return err;
 }
 
 status_t GonkRecorder::close() {
-    DOM_CAMERA_LOGI("%s", __func__);
+    RE_LOGV("close");
     stop();
 
     return OK;
 }
 
 status_t GonkRecorder::reset() {
-    DOM_CAMERA_LOGI("%s", __func__);
+    RE_LOGV("reset");
     stop();
 
     // No audio or video source by default
     mAudioSource = AUDIO_SOURCE_CNT;
     mVideoSource = VIDEO_SOURCE_LIST_END;
 
     // Default parameters
     mOutputFormat  = OUTPUT_FORMAT_THREE_GPP;
@@ -1494,17 +1483,17 @@ status_t GonkRecorder::reset() {
     mVideoWidth    = 176;
     mVideoHeight   = 144;
     mFrameRate     = -1;
     mVideoBitRate  = 192000;
     mSampleRate    = 8000;
     mAudioChannels = 1;
     mAudioBitRate  = 12200;
     mInterleaveDurationUs = 0;
-    mIFramesIntervalSec = 2;
+    mIFramesIntervalSec = 1;
     mAudioSourceNode = 0;
     mUse64BitFileOffset = false;
     mMovieTimeScale  = -1;
     mAudioTimeScale  = -1;
     mVideoTimeScale  = -1;
     mCameraId        = 0;
     mStartTimeOffsetMs = -1;
     mVideoEncoderProfile = -1;
@@ -1520,44 +1509,39 @@ status_t GonkRecorder::reset() {
 
     mOutputFd = -1;
     mCameraHw.clear();
     //TODO: May need to register a listener eventually
     //if someone is interested in recorder events for now
     //default to no listener registered
     mListener = NULL;
 
-    // Disable Audio Encoding
-    char value[PROPERTY_VALUE_MAX];
-    property_get("camcorder.debug.disableaudio", value, "0");
-    if(atoi(value)) mDisableAudio = true;
-
     return OK;
 }
 
 status_t GonkRecorder::getMaxAmplitude(int *max) {
-    DOM_CAMERA_LOGI("%s", __func__);
+    RE_LOGV("getMaxAmplitude");
 
     if (max == NULL) {
-        DOM_CAMERA_LOGE("Null pointer argument");
+        RE_LOGE("Null pointer argument");
         return BAD_VALUE;
     }
 
     if (mAudioSourceNode != 0) {
         *max = mAudioSourceNode->getMaxAmplitude();
     } else {
         *max = 0;
     }
 
     return OK;
 }
 
 status_t GonkRecorder::dump(
         int fd, const Vector<String16>& args) const {
-    DOM_CAMERA_LOGI("%s", __func__);
+    RE_LOGV("dump");
     const size_t SIZE = 256;
     char buffer[SIZE];
     String8 result;
     if (mWriter != 0) {
         mWriter->dump(fd, args);
     } else {
         snprintf(buffer, SIZE, "   No file writer\n");
         result.append(buffer);
--- a/dom/camera/GonkRecorder.h
+++ b/dom/camera/GonkRecorder.h
@@ -1,11 +1,10 @@
 /*
  * Copyright (C) 2009 The Android Open Source Project
- * Copyright (C) 2013 Mozilla Foundation
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
@@ -14,21 +13,24 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 #ifndef GONK_RECORDER_H_
 #define GONK_RECORDER_H_
 
 #include "nsISupportsImpl.h"
+#include "GonkCameraHwMgr.h"
 
-#include <media/mediarecorder.h>
+#include <media/MediaRecorderBase.h>
 #include <camera/CameraParameters.h>
 #include <utils/String8.h>
 #include <system/audio.h>
+
+#include "mozilla/RefPtr.h"
 #include "GonkCameraHwMgr.h"
 
 namespace android {
 
 class GonkCameraSource;
 struct MediaSource;
 struct MediaWriter;
 class MetaData;
@@ -49,31 +51,34 @@ struct GonkRecorder {
     virtual status_t setVideoEncoder(video_encoder ve);
     virtual status_t setVideoSize(int width, int height);
     virtual status_t setVideoFrameRate(int frames_per_second);
     virtual status_t setOutputFile(const char *path);
     virtual status_t setOutputFile(int fd, int64_t offset, int64_t length);
     virtual status_t setParameters(const String8& params);
     virtual status_t setCamera(const sp<GonkCameraHardware>& aCameraHw);
     virtual status_t setListener(const sp<IMediaRecorderClient>& listener);
+    virtual status_t setClientName(const String16& clientName);
     virtual status_t prepare();
     virtual status_t start();
     virtual status_t pause();
     virtual status_t stop();
     virtual status_t close();
     virtual status_t reset();
     virtual status_t getMaxAmplitude(int *max);
     virtual status_t dump(int fd, const Vector<String16>& args) const;
     // Querying a SurfaceMediaSourcer
 
 protected:
     virtual ~GonkRecorder();
 
 private:
     sp<IMediaRecorderClient> mListener;
+    String16 mClientName;
+    uid_t mClientUid;
     sp<MediaWriter> mWriter;
     int mOutputFd;
     sp<AudioSource> mAudioSourceNode;
 
     audio_source_t mAudioSource;
     video_source mVideoSource;
     output_format mOutputFormat;
     audio_encoder mAudioEncoder;
@@ -103,33 +108,37 @@ private:
 
     String8 mParams;
 
     bool mIsMetaDataStoredInVideoBuffers;
     MediaProfiles *mEncoderProfiles;
 
     bool mStarted;
     // Needed when GLFrames are encoded.
-    // An <ISurfaceTexture> pointer
+    // An <IGraphicBufferProducer> pointer
     // will be sent to the client side using which the
     // frame buffers will be queued and dequeued
-    bool mDisableAudio;
+
     sp<GonkCameraHardware> mCameraHw;
 
     status_t setupMPEG4Recording(
         int outputFd,
         int32_t videoWidth, int32_t videoHeight,
         int32_t videoBitRate,
         int32_t *totalBitRate,
         sp<MediaWriter> *mediaWriter);
     void setupMPEG4MetaData(int64_t startTimeUs, int32_t totalBitRate,
         sp<MetaData> *meta);
     status_t startMPEG4Recording();
     status_t startAMRRecording();
+#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 18
+    status_t startAACRecording();
+#endif
     status_t startRawAudioRecording();
+    status_t startRTPRecording();
     status_t startMPEG2TSRecording();
     sp<MediaSource> createAudioSource();
     status_t checkVideoEncoderCapabilities();
     status_t checkAudioEncoderCapabilities();
     // Generic MediaSource set-up. Returns the appropriate
     // source (CameraSource or SurfaceMediaSource)
     // depending on the videosource type
     status_t setupMediaSource(sp<MediaSource> *mediaSource);
--- a/dom/camera/moz.build
+++ b/dom/camera/moz.build
@@ -34,17 +34,16 @@ CPP_SOURCES += [
 
 if CONFIG['MOZ_B2G_CAMERA']:
     CPP_SOURCES += [
         'GonkCameraManager.cpp',
         'GonkCameraControl.cpp',
         'GonkCameraHwMgr.cpp',
         'GonkRecorder.cpp',
         'GonkCameraSource.cpp',
-        'AudioParameter.cpp',
         'GonkRecorderProfiles.cpp',
     ]
 else:
     CPP_SOURCES += [
         'FallbackCameraManager.cpp',
         'FallbackCameraControl.cpp',
     ]
 
--- a/gfx/layers/GrallocImages.cpp
+++ b/gfx/layers/GrallocImages.cpp
@@ -24,16 +24,18 @@ namespace mozilla {
 namespace layers {
 
 uint32_t GrallocImage::sColorIdMap[] = {
     HAL_PIXEL_FORMAT_YCbCr_420_P, OMX_COLOR_FormatYUV420Planar,
     HAL_PIXEL_FORMAT_YCbCr_422_P, OMX_COLOR_FormatYUV422Planar,
     HAL_PIXEL_FORMAT_YCbCr_420_SP, OMX_COLOR_FormatYUV420SemiPlanar,
     HAL_PIXEL_FORMAT_YCrCb_420_SP, -1,
     HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO, -1,
+    HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED, HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED,
+    HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS, HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS,
     HAL_PIXEL_FORMAT_YV12, OMX_COLOR_FormatYUV420Planar,
     0, 0
 };
 
 struct GraphicBufferAutoUnlock {
   android::sp<GraphicBuffer> mGraphicBuffer;
 
   GraphicBufferAutoUnlock(android::sp<GraphicBuffer>& aGraphicBuffer)
--- a/gfx/layers/GrallocImages.h
+++ b/gfx/layers/GrallocImages.h
@@ -99,16 +99,18 @@ public:
 
   // From [android 4.0.4]/hardware/msm7k/libgralloc-qsd8k/gralloc_priv.h
   enum {
     /* OEM specific HAL formats */
     HAL_PIXEL_FORMAT_YCbCr_422_P            = 0x102,
     HAL_PIXEL_FORMAT_YCbCr_420_P            = 0x103,
     HAL_PIXEL_FORMAT_YCbCr_420_SP           = 0x109,
     HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO    = 0x10A,
+    HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED     = 0x7FA30C03,
+    HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS     = 0x7FA30C04,
   };
 
   virtual already_AddRefed<gfxASurface> GetAsSurface();
 
   void* GetNativeBuffer()
   {
     if (IsValid()) {
       return GrallocBufferActor::GetFrom(GetSurfaceDescriptor())->getNativeBuffer();
--- a/gfx/layers/opengl/GrallocTextureHost.cpp
+++ b/gfx/layers/opengl/GrallocTextureHost.cpp
@@ -2,16 +2,17 @@
 //  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "GLContext.h"
 #include "gfxImageSurface.h"
 #include "gfx2DGlue.h"
 #include <ui/GraphicBuffer.h>
+#include "GrallocImages.h"  // for GrallocImage
 #include "mozilla/layers/GrallocTextureHost.h"
 #include "mozilla/layers/CompositorOGL.h"
 
 namespace mozilla {
 namespace layers {
 
 using namespace android;
 
@@ -28,16 +29,18 @@ SurfaceFormatForAndroidPixelFormat(andro
     return swapRB ? gfx::FORMAT_B8G8R8X8 : gfx::FORMAT_R8G8B8X8;
   case android::PIXEL_FORMAT_RGB_565:
     return gfx::FORMAT_R5G6B5;
   case android::PIXEL_FORMAT_A_8:
     return gfx::FORMAT_A8;
   case HAL_PIXEL_FORMAT_YCbCr_422_SP:
   case HAL_PIXEL_FORMAT_YCrCb_420_SP:
   case HAL_PIXEL_FORMAT_YCbCr_422_I:
+  case GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+  case GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
   case HAL_PIXEL_FORMAT_YV12:
     return gfx::FORMAT_B8G8R8A8; // yup, use FORMAT_B8G8R8A8 even though it's a YUV texture. This is an external texture.
   default:
     if (aFormat >= 0x100 && aFormat <= 0x1FF) {
       // Reserved range for HAL specific formats.
       return gfx::FORMAT_B8G8R8A8;
     } else {
       // This is not super-unreachable, there's a bunch of hypothetical pixel
@@ -54,16 +57,18 @@ SurfaceFormatForAndroidPixelFormat(andro
 
 static GLenum
 TextureTargetForAndroidPixelFormat(android::PixelFormat aFormat)
 {
   switch (aFormat) {
   case HAL_PIXEL_FORMAT_YCbCr_422_SP:
   case HAL_PIXEL_FORMAT_YCrCb_420_SP:
   case HAL_PIXEL_FORMAT_YCbCr_422_I:
+  case GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+  case GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
   case HAL_PIXEL_FORMAT_YV12:
     return LOCAL_GL_TEXTURE_EXTERNAL;
   case android::PIXEL_FORMAT_RGBA_8888:
   case android::PIXEL_FORMAT_RGBX_8888:
   case android::PIXEL_FORMAT_RGB_565:
   case android::PIXEL_FORMAT_A_8:
     return LOCAL_GL_TEXTURE_2D;
   default:
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -14,16 +14,19 @@
 #include "gfx2DGlue.h"                  // for ContentForFormat, etc
 #include "gfxImageSurface.h"            // for gfxImageSurface
 #include "gfxPoint.h"                   // for gfxIntSize
 #include "gfxReusableSurfaceWrapper.h"  // for gfxReusableSurfaceWrapper
 #include "ipc/AutoOpenSurface.h"        // for AutoOpenSurface
 #include "mozilla/gfx/2D.h"             // for DataSourceSurface
 #include "mozilla/gfx/BaseSize.h"       // for BaseSize
 #include "mozilla/layers/CompositorOGL.h"  // for CompositorOGL
+#ifdef MOZ_WIDGET_GONK
+# include "GrallocImages.h"  // for GrallocImage
+#endif
 #include "mozilla/layers/ISurfaceAllocator.h"
 #include "mozilla/layers/YCbCrImageDataSerializer.h"
 #include "mozilla/layers/GrallocTextureHost.h"
 #include "nsPoint.h"                    // for nsIntPoint
 #include "nsRegion.h"                   // for nsIntRegion
 #include "GfxTexturesReporter.h"        // for GfxTexturesReporter
 #ifdef XP_MACOSX
 #include "SharedSurfaceIO.h"
@@ -947,16 +950,18 @@ SurfaceFormatForAndroidPixelFormat(andro
     return swapRB ? FORMAT_B8G8R8X8 : FORMAT_R8G8B8X8;
   case android::PIXEL_FORMAT_RGB_565:
     return FORMAT_R5G6B5;
   case android::PIXEL_FORMAT_A_8:
     return FORMAT_A8;
   case HAL_PIXEL_FORMAT_YCbCr_422_SP:
   case HAL_PIXEL_FORMAT_YCrCb_420_SP:
   case HAL_PIXEL_FORMAT_YCbCr_422_I:
+  case GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+  case GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
   case HAL_PIXEL_FORMAT_YV12:
     return FORMAT_B8G8R8A8; // yup, use FORMAT_B8G8R8A8 even though it's a YUV texture. This is an external texture.
   default:
     if (aFormat >= 0x100 && aFormat <= 0x1FF) {
       // Reserved range for HAL specific formats.
       return FORMAT_B8G8R8A8;
     } else {
       // This is not super-unreachable, there's a bunch of hypothetical pixel
@@ -972,16 +977,18 @@ SurfaceFormatForAndroidPixelFormat(andro
 
 static GLenum
 TextureTargetForAndroidPixelFormat(android::PixelFormat aFormat)
 {
   switch (aFormat) {
   case HAL_PIXEL_FORMAT_YCbCr_422_SP:
   case HAL_PIXEL_FORMAT_YCrCb_420_SP:
   case HAL_PIXEL_FORMAT_YCbCr_422_I:
+  case GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+  case GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
   case HAL_PIXEL_FORMAT_YV12:
     return LOCAL_GL_TEXTURE_EXTERNAL;
   case android::PIXEL_FORMAT_RGBA_8888:
   case android::PIXEL_FORMAT_RGBX_8888:
   case android::PIXEL_FORMAT_RGB_565:
   case android::PIXEL_FORMAT_A_8:
     return LOCAL_GL_TEXTURE_2D;
   default:
--- a/widget/gonk/Makefile.in
+++ b/widget/gonk/Makefile.in
@@ -20,16 +20,20 @@ VPATH           = \
 EXPORT_LIBRARY  = 1
 SHARED_LIBRARY_LIBS = ../xpwidgets/libxpwidgets_s.a
 
 include $(topsrcdir)/config/rules.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
 
 DEFINES += -DHAVE_OFF64_T -DSK_BUILD_FOR_ANDROID_NDK
 
+ifdef MOZ_OMX_DECODER
+DEFINES += -DMOZ_OMX_DECODER
+endif
+
 LOCAL_INCLUDES += \
 	-I$(ANDROID_SOURCE)/hardware/libhardware/include \
 	-I$(ANDROID_SOURCE)/hardware/libhardware_legacy/include \
 	-I$(ANDROID_SOURCE)/frameworks/native/opengl/include \
 	-I$(topsrcdir)/widget/xpwidgets \
 	-I$(topsrcdir)/widget/shared \
 	-I$(topsrcdir)/dom/system/android \
 	-I$(topsrcdir)/content/events/src \
--- a/widget/gonk/nativewindow/GonkBufferQueue.cpp
+++ b/widget/gonk/nativewindow/GonkBufferQueue.cpp
@@ -17,40 +17,32 @@
 
 #define LOG_TAG "GonkBufferQueue"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 #define LOG_NDEBUG 0
 
 #define GL_GLEXT_PROTOTYPES
 #define EGL_EGLEXT_PROTOTYPES
 
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
+#include <utils/Log.h>
 
-#include <gui/BufferQueue.h>
-#include <gui/ISurfaceComposer.h>
-#include <private/gui/ComposerService.h>
+#include "mozilla/layers/ImageBridgeChild.h"
 
-#include <utils/Log.h>
-#include <utils/Trace.h>
+#include "GonkBufferQueue.h"
 
 // Macros for including the GonkBufferQueue name in log messages
-#define ST_LOGV(x, ...) ALOGV("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
-#define ST_LOGD(x, ...) ALOGD("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
-#define ST_LOGI(x, ...) ALOGI("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
-#define ST_LOGW(x, ...) ALOGW("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
-#define ST_LOGE(x, ...) ALOGE("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
+#define ST_LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
+#define ST_LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
+#define ST_LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
+#define ST_LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
+#define ST_LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
 
-#define ATRACE_BUFFER_INDEX(index)                                            \
-    if (ATRACE_ENABLED()) {                                                   \
-        char ___traceBuf[1024];                                               \
-        snprintf(___traceBuf, 1024, "%s: %d", mConsumerName.string(),         \
-                (index));                                                     \
-        android::ScopedTrace ___bufTracer(ATRACE_TAG, ___traceBuf);           \
-    }
+#define ATRACE_BUFFER_INDEX(index)
+
+using namespace mozilla::layers;
 
 namespace android {
 
 // Get an ID that's unique within this process.
 static int32_t createProcessUniqueId() {
     static volatile int32_t globalCounter = 0;
     return android_atomic_inc(&globalCounter);
 }
@@ -66,39 +58,31 @@ static const char* scalingModeName(int s
 
 GonkBufferQueue::GonkBufferQueue(bool allowSynchronousMode,
         const sp<IGraphicBufferAlloc>& allocator) :
     mDefaultWidth(1),
     mDefaultHeight(1),
     mMaxAcquiredBufferCount(1),
     mDefaultMaxBufferCount(2),
     mOverrideMaxBufferCount(0),
-    mSynchronousMode(false),
+    mSynchronousMode(true), // GonkBufferQueue always works in sync mode.
     mAllowSynchronousMode(allowSynchronousMode),
     mConnectedApi(NO_CONNECTED_API),
     mAbandoned(false),
     mFrameCounter(0),
     mBufferHasBeenQueued(false),
     mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888),
     mConsumerUsageBits(0),
-    mTransformHint(0)
+    mTransformHint(0),
+    mGeneration(0)
 {
     // Choose a name using the PID and a process-unique ID.
     mConsumerName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
 
     ST_LOGV("GonkBufferQueue");
-    if (allocator == NULL) {
-        sp<ISurfaceComposer> composer(ComposerService::getComposerService());
-        mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
-        if (mGraphicBufferAlloc == 0) {
-            ST_LOGE("createGraphicBufferAlloc() failed in GonkBufferQueue()");
-        }
-    } else {
-        mGraphicBufferAlloc = allocator;
-    }
 }
 
 GonkBufferQueue::~GonkBufferQueue() {
     ST_LOGV("~GonkBufferQueue");
 }
 
 status_t GonkBufferQueue::setDefaultMaxBufferCountLocked(int count) {
     if (count < 2 || count > NUM_BUFFER_SLOTS)
@@ -134,20 +118,43 @@ status_t GonkBufferQueue::setConsumerUsa
 
 status_t GonkBufferQueue::setTransformHint(uint32_t hint) {
     ST_LOGV("setTransformHint: %02x", hint);
     Mutex::Autolock lock(mMutex);
     mTransformHint = hint;
     return NO_ERROR;
 }
 
+int GonkBufferQueue::getGeneration() {
+    return mGeneration;
+}
+
+mozilla::layers::SurfaceDescriptor*
+GonkBufferQueue::getSurfaceDescriptorFromBuffer(ANativeWindowBuffer* buffer)
+{
+    Mutex::Autolock _l(mMutex);
+    if (buffer == NULL) {
+        ST_LOGE("getSlotFromBufferLocked: encountered NULL buffer");
+        return nullptr;
+    }
+
+    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
+        if (mSlots[i].mGraphicBuffer != NULL && mSlots[i].mGraphicBuffer->handle == buffer->handle) {
+            return &mSlots[i].mSurfaceDescriptor;
+        }
+    }
+    ST_LOGE("getSlotFromBufferLocked: unknown buffer: %p", buffer->handle);
+    return nullptr;
+}
+
 status_t GonkBufferQueue::setBufferCount(int bufferCount) {
     ST_LOGV("setBufferCount: count=%d", bufferCount);
 
     sp<ConsumerListener> listener;
+    nsAutoTArray<SurfaceDescriptor, NUM_BUFFER_SLOTS> freeList;
     {
         Mutex::Autolock lock(mMutex);
 
         if (mAbandoned) {
             ST_LOGE("setBufferCount: GonkBufferQueue has been abandoned!");
             return NO_INIT;
         }
         if (bufferCount > NUM_BUFFER_SLOTS) {
@@ -177,33 +184,33 @@ status_t GonkBufferQueue::setBufferCount
                     "minimum (%d)", bufferCount, minBufferSlots);
             return BAD_VALUE;
         }
 
         // here we're guaranteed that the client doesn't have dequeued buffers
         // and will release all of its buffer references.
         //
         // XXX: Should this use drainQueueAndFreeBuffersLocked instead?
-        freeAllBuffersLocked();
+        freeAllBuffersLocked(freeList);
         mOverrideMaxBufferCount = bufferCount;
         mBufferHasBeenQueued = false;
         mDequeueCondition.broadcast();
         listener = mConsumerListener;
     } // scope for lock
+    releaseBufferFreeListUnlocked(freeList);
 
     if (listener != NULL) {
         listener->onBuffersReleased();
     }
 
     return NO_ERROR;
 }
 
 int GonkBufferQueue::query(int what, int* outValue)
 {
-    ATRACE_CALL();
     Mutex::Autolock lock(mMutex);
 
     if (mAbandoned) {
         ST_LOGE("query: GonkBufferQueue has been abandoned!");
         return NO_INIT;
     }
 
     int value;
@@ -226,17 +233,16 @@ int GonkBufferQueue::query(int what, int
     default:
         return BAD_VALUE;
     }
     outValue[0] = value;
     return NO_ERROR;
 }
 
 status_t GonkBufferQueue::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
-    ATRACE_CALL();
     ST_LOGV("requestBuffer: slot=%d", slot);
     Mutex::Autolock lock(mMutex);
     if (mAbandoned) {
         ST_LOGE("requestBuffer: GonkBufferQueue has been abandoned!");
         return NO_INIT;
     }
     int maxBufferCount = getMaxBufferCountLocked();
     if (slot < 0 || maxBufferCount <= slot) {
@@ -253,30 +259,31 @@ status_t GonkBufferQueue::requestBuffer(
     }
     mSlots[slot].mRequestBufferCalled = true;
     *buf = mSlots[slot].mGraphicBuffer;
     return NO_ERROR;
 }
 
 status_t GonkBufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence,
         uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
-    ATRACE_CALL();
     ST_LOGV("dequeueBuffer: w=%d h=%d fmt=%#x usage=%#x", w, h, format, usage);
 
     if ((w && !h) || (!w && h)) {
         ST_LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
         return BAD_VALUE;
     }
 
     status_t returnFlags(OK);
-    EGLDisplay dpy = EGL_NO_DISPLAY;
-    EGLSyncKHR eglFence = EGL_NO_SYNC_KHR;
+    uint32_t generation;
+    int buf = INVALID_BUFFER_SLOT;
+    SurfaceDescriptor descOld;
 
     { // Scope for the lock
         Mutex::Autolock lock(mMutex);
+        generation = mGeneration;
 
         if (format == 0) {
             format = mDefaultBufferFormat;
         }
         // turn on usage bits the consumer requested
         usage |= mConsumerUsageBits;
 
         int found = -1;
@@ -287,23 +294,23 @@ status_t GonkBufferQueue::dequeueBuffer(
                 ST_LOGE("dequeueBuffer: GonkBufferQueue has been abandoned!");
                 return NO_INIT;
             }
 
             const int maxBufferCount = getMaxBufferCountLocked();
 
             // Free up any buffers that are in slots beyond the max buffer
             // count.
-            for (int i = maxBufferCount; i < NUM_BUFFER_SLOTS; i++) {
-                assert(mSlots[i].mBufferState == BufferSlot::FREE);
-                if (mSlots[i].mGraphicBuffer != NULL) {
-                    freeBufferLocked(i);
-                    returnFlags |= IGraphicBufferProducer::RELEASE_ALL_BUFFERS;
-                }
-            }
+            //for (int i = maxBufferCount; i < NUM_BUFFER_SLOTS; i++) {
+            //    assert(mSlots[i].mBufferState == BufferSlot::FREE);
+            //    if (mSlots[i].mGraphicBuffer != NULL) {
+            //        freeBufferLocked(i);
+            //        returnFlags |= IGraphicBufferProducer::RELEASE_ALL_BUFFERS;
+            //    }
+            //}
 
             // look for a free buffer to give to the client
             found = INVALID_BUFFER_SLOT;
             dequeuedCount = 0;
             for (int i = 0; i < maxBufferCount; i++) {
                 const int state = mSlots[i].mBufferState;
                 if (state == BufferSlot::DEQUEUED) {
                     dequeuedCount++;
@@ -357,21 +364,19 @@ status_t GonkBufferQueue::dequeueBuffer(
 
 
         if (found == INVALID_BUFFER_SLOT) {
             // This should not happen.
             ST_LOGE("dequeueBuffer: no available buffer slots");
             return -EBUSY;
         }
 
-        const int buf = found;
+        buf = found;
         *outBuf = found;
 
-        ATRACE_BUFFER_INDEX(buf);
-
         const bool useDefaultSize = !w && !h;
         if (useDefaultSize) {
             // use the default size
             w = mDefaultWidth;
             h = mDefaultHeight;
         }
 
         mSlots[buf].mBufferState = BufferSlot::DEQUEUED;
@@ -381,108 +386,96 @@ status_t GonkBufferQueue::dequeueBuffer(
             (uint32_t(buffer->width)  != w) ||
             (uint32_t(buffer->height) != h) ||
             (uint32_t(buffer->format) != format) ||
             ((uint32_t(buffer->usage) & usage) != usage))
         {
             mSlots[buf].mAcquireCalled = false;
             mSlots[buf].mGraphicBuffer = NULL;
             mSlots[buf].mRequestBufferCalled = false;
-            mSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
             mSlots[buf].mFence = Fence::NO_FENCE;
-            mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
+            descOld = mSlots[buf].mSurfaceDescriptor;
+            mSlots[buf].mSurfaceDescriptor = SurfaceDescriptor();
 
             returnFlags |= IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION;
         }
 
-        dpy = mSlots[buf].mEglDisplay;
-        eglFence = mSlots[buf].mEglFence;
         *outFence = mSlots[buf].mFence;
-        mSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
         mSlots[buf].mFence = Fence::NO_FENCE;
     }  // end lock scope
 
+    SurfaceDescriptor desc;
+    ImageBridgeChild* ibc;
+    sp<GraphicBuffer> graphicBuffer;
     if (returnFlags & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) {
+        usage |= GraphicBuffer::USAGE_HW_TEXTURE;
         status_t error;
-        sp<GraphicBuffer> graphicBuffer(
-                mGraphicBufferAlloc->createGraphicBuffer(
-                        w, h, format, usage, &error));
-        if (graphicBuffer == 0) {
-            ST_LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer "
-                    "failed");
+        ibc = ImageBridgeChild::GetSingleton();
+        ST_LOGD("dequeueBuffer: about to alloc surface descriptor");
+        ibc->AllocSurfaceDescriptorGralloc(gfxIntSize(w, h),
+                                           format,
+                                           usage,
+                                           &desc);
+        // We can only use a gralloc buffer here.  If we didn't get
+        // one back, something went wrong.
+        ST_LOGD("dequeueBuffer: got surface descriptor");
+        if (SurfaceDescriptor::TSurfaceDescriptorGralloc != desc.type()) {
+            MOZ_ASSERT(SurfaceDescriptor::T__None == desc.type());
+            ST_LOGE("dequeueBuffer: failed to alloc gralloc buffer");
+            return -ENOMEM;
+        }
+        graphicBuffer = GrallocBufferActor::GetFrom(desc.get_SurfaceDescriptorGralloc());
+        error = graphicBuffer->initCheck();
+        if (error != NO_ERROR) {
+            ST_LOGE("dequeueBuffer: createGraphicBuffer failed with error %d", error);
             return error;
         }
 
+        bool tooOld = false;
         { // Scope for the lock
             Mutex::Autolock lock(mMutex);
 
             if (mAbandoned) {
-                ST_LOGE("dequeueBuffer: GonkBufferQueue has been abandoned!");
+                ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
                 return NO_INIT;
             }
 
-            mSlots[*outBuf].mGraphicBuffer = graphicBuffer;
+            if (generation == mGeneration) {
+                mSlots[buf].mGraphicBuffer = graphicBuffer;
+                mSlots[buf].mSurfaceDescriptor = desc;
+                mSlots[buf].mSurfaceDescriptor.get_SurfaceDescriptorGralloc().external() = true;
+                ST_LOGD("dequeueBuffer: returning slot=%d buf=%p ", buf,
+                        mSlots[buf].mGraphicBuffer->handle);
+            } else {
+                tooOld = true;
+            }
+            //mSlots[*outBuf].mGraphicBuffer = graphicBuffer;
         }
-    }
 
-    if (eglFence != EGL_NO_SYNC_KHR) {
-        EGLint result = eglClientWaitSyncKHR(dpy, eglFence, 0, 1000000000);
-        // If something goes wrong, log the error, but return the buffer without
-        // synchronizing access to it.  It's too late at this point to abort the
-        // dequeue operation.
-        if (result == EGL_FALSE) {
-            ST_LOGE("dequeueBuffer: error waiting for fence: %#x", eglGetError());
-        } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
-            ST_LOGE("dequeueBuffer: timeout waiting for fence");
+        if (IsSurfaceDescriptorValid(descOld)) {
+            ibc->DeallocSurfaceDescriptorGralloc(descOld);
         }
-        eglDestroySyncKHR(dpy, eglFence);
+
+        if (tooOld) {
+            ibc->DeallocSurfaceDescriptorGralloc(desc);
+        }
     }
 
     ST_LOGV("dequeueBuffer: returning slot=%d buf=%p flags=%#x", *outBuf,
             mSlots[*outBuf].mGraphicBuffer->handle, returnFlags);
 
     return returnFlags;
 }
 
 status_t GonkBufferQueue::setSynchronousMode(bool enabled) {
-    ATRACE_CALL();
-    ST_LOGV("setSynchronousMode: enabled=%d", enabled);
-    Mutex::Autolock lock(mMutex);
-
-    if (mAbandoned) {
-        ST_LOGE("setSynchronousMode: GonkBufferQueue has been abandoned!");
-        return NO_INIT;
-    }
-
-    status_t err = OK;
-    if (!mAllowSynchronousMode && enabled)
-        return err;
-
-    if (!enabled) {
-        // going to asynchronous mode, drain the queue
-        err = drainQueueLocked();
-        if (err != NO_ERROR)
-            return err;
-    }
-
-    if (mSynchronousMode != enabled) {
-        // - if we're going to asynchronous mode, the queue is guaranteed to be
-        // empty here
-        // - if the client set the number of buffers, we're guaranteed that
-        // we have at least 3 (because we don't allow less)
-        mSynchronousMode = enabled;
-        mDequeueCondition.broadcast();
-    }
-    return err;
+    return NO_ERROR;
 }
 
 status_t GonkBufferQueue::queueBuffer(int buf,
         const QueueBufferInput& input, QueueBufferOutput* output) {
-    ATRACE_CALL();
-    ATRACE_BUFFER_INDEX(buf);
 
     Rect crop;
     uint32_t transform;
     int scalingMode;
     int64_t timestamp;
     sp<Fence> fence;
 
     input.deflate(&timestamp, &crop, &scalingMode, &transform, &fence);
@@ -576,29 +569,26 @@ status_t GonkBufferQueue::queueBuffer(in
         mFrameCounter++;
         mSlots[buf].mFrameNumber = mFrameCounter;
 
         mBufferHasBeenQueued = true;
         mDequeueCondition.broadcast();
 
         output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint,
                 mQueue.size());
-
-        ATRACE_INT(mConsumerName.string(), mQueue.size());
     } // scope for the lock
 
     // call back without lock held
     if (listener != 0) {
         listener->onFrameAvailable();
     }
     return NO_ERROR;
 }
 
 void GonkBufferQueue::cancelBuffer(int buf, const sp<Fence>& fence) {
-    ATRACE_CALL();
     ST_LOGV("cancelBuffer: slot=%d", buf);
     Mutex::Autolock lock(mMutex);
 
     if (mAbandoned) {
         ST_LOGW("cancelBuffer: GonkBufferQueue has been abandoned!");
         return;
     }
 
@@ -617,17 +607,16 @@ void GonkBufferQueue::cancelBuffer(int b
     }
     mSlots[buf].mBufferState = BufferSlot::FREE;
     mSlots[buf].mFrameNumber = 0;
     mSlots[buf].mFence = fence;
     mDequeueCondition.broadcast();
 }
 
 status_t GonkBufferQueue::connect(int api, QueueBufferOutput* output) {
-    ATRACE_CALL();
     ST_LOGV("connect: api=%d", api);
     Mutex::Autolock lock(mMutex);
 
     if (mAbandoned) {
         ST_LOGE("connect: GonkBufferQueue has been abandoned!");
         return NO_INIT;
     }
 
@@ -658,53 +647,54 @@ status_t GonkBufferQueue::connect(int ap
     }
 
     mBufferHasBeenQueued = false;
 
     return err;
 }
 
 status_t GonkBufferQueue::disconnect(int api) {
-    ATRACE_CALL();
     ST_LOGV("disconnect: api=%d", api);
 
     int err = NO_ERROR;
     sp<ConsumerListener> listener;
+    nsAutoTArray<SurfaceDescriptor, NUM_BUFFER_SLOTS> freeList;
 
     { // Scope for the lock
         Mutex::Autolock lock(mMutex);
 
         if (mAbandoned) {
             // it is not really an error to disconnect after the surface
             // has been abandoned, it should just be a no-op.
             return NO_ERROR;
         }
 
         switch (api) {
             case NATIVE_WINDOW_API_EGL:
             case NATIVE_WINDOW_API_CPU:
             case NATIVE_WINDOW_API_MEDIA:
             case NATIVE_WINDOW_API_CAMERA:
                 if (mConnectedApi == api) {
-                    drainQueueAndFreeBuffersLocked();
+                    freeAllBuffersLocked(freeList);
                     mConnectedApi = NO_CONNECTED_API;
                     mDequeueCondition.broadcast();
                     listener = mConsumerListener;
                 } else {
                     ST_LOGE("disconnect: connected to another api (cur=%d, req=%d)",
                             mConnectedApi, api);
                     err = -EINVAL;
                 }
                 break;
             default:
                 ST_LOGE("disconnect: unknown API %d", api);
                 err = -EINVAL;
                 break;
         }
     }
+    releaseBufferFreeListUnlocked(freeList);
 
     if (listener != NULL) {
         listener->onBuffersReleased();
     }
 
     return err;
 }
 
@@ -772,46 +762,58 @@ void GonkBufferQueue::dump(String8& resu
                     buf->handle, buf->width, buf->height, buf->stride,
                     buf->format);
             result.append(buffer);
         }
         result.append("\n");
     }
 }
 
-void GonkBufferQueue::freeBufferLocked(int slot) {
-    ST_LOGV("freeBufferLocked: slot=%d", slot);
-    mSlots[slot].mGraphicBuffer = 0;
-    if (mSlots[slot].mBufferState == BufferSlot::ACQUIRED) {
-        mSlots[slot].mNeedsCleanupOnRelease = true;
+void GonkBufferQueue::releaseBufferFreeListUnlocked(nsTArray<SurfaceDescriptor>& freeList)
+{
+    // This function MUST ONLY be called with mMutex unlocked; else there
+    // is a risk of deadlock with the ImageBridge thread.
+
+    ST_LOGD("releaseBufferFreeListUnlocked: E");
+    ImageBridgeChild *ibc = ImageBridgeChild::GetSingleton();
+
+    for (uint32_t i = 0; i < freeList.Length(); ++i) {
+        ibc->DeallocSurfaceDescriptorGralloc(freeList[i]);
     }
-    mSlots[slot].mBufferState = BufferSlot::FREE;
-    mSlots[slot].mFrameNumber = 0;
-    mSlots[slot].mAcquireCalled = false;
 
-    // destroy fence as GonkBufferQueue now takes ownership
-    if (mSlots[slot].mEglFence != EGL_NO_SYNC_KHR) {
-        eglDestroySyncKHR(mSlots[slot].mEglDisplay, mSlots[slot].mEglFence);
-        mSlots[slot].mEglFence = EGL_NO_SYNC_KHR;
-    }
-    mSlots[slot].mFence = Fence::NO_FENCE;
+    freeList.Clear();
+    ST_LOGD("releaseBufferFreeListUnlocked: X");
 }
 
-void GonkBufferQueue::freeAllBuffersLocked() {
+void GonkBufferQueue::freeAllBuffersLocked(nsTArray<SurfaceDescriptor>& freeList)
+{
     ALOGW_IF(!mQueue.isEmpty(),
             "freeAllBuffersLocked called but mQueue is not empty");
+    ++mGeneration;
     mQueue.clear();
     mBufferHasBeenQueued = false;
     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
-        freeBufferLocked(i);
+        if (mSlots[i].mGraphicBuffer.get() && mSlots[i].mBufferState != BufferSlot::ACQUIRED) {
+            SurfaceDescriptor* desc = freeList.AppendElement();
+            *desc = mSlots[i].mSurfaceDescriptor;
+        }
+        mSlots[i].mGraphicBuffer = 0;
+        mSlots[i].mSurfaceDescriptor = SurfaceDescriptor();
+        if (mSlots[i].mBufferState == BufferSlot::ACQUIRED) {
+            mSlots[i].mNeedsCleanupOnRelease = true;
+        }
+        mSlots[i].mBufferState = BufferSlot::FREE;
+        mSlots[i].mFrameNumber = 0;
+        mSlots[i].mAcquireCalled = false;
+        // destroy fence as GonkBufferQueue now takes ownership
+        mSlots[i].mFence = Fence::NO_FENCE;
     }
 }
 
 status_t GonkBufferQueue::acquireBuffer(BufferItem *buffer) {
-    ATRACE_CALL();
     Mutex::Autolock _l(mMutex);
 
     // Check that the consumer doesn't currently have the maximum number of
     // buffers acquired.  We allow the max buffer count to be exceeded by one
     // buffer, so that the consumer can successfully set up the newly acquired
     // buffer before releasing the old one.
     int numAcquiredBuffers = 0;
     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
@@ -827,60 +829,58 @@ status_t GonkBufferQueue::acquireBuffer(
 
     // check if queue is empty
     // In asynchronous mode the list is guaranteed to be one buffer
     // deep, while in synchronous mode we use the oldest buffer.
     if (!mQueue.empty()) {
         Fifo::iterator front(mQueue.begin());
         int buf = *front;
 
-        ATRACE_BUFFER_INDEX(buf);
+        // In android, when the buffer is aquired by BufferConsumer,
+        // BufferQueue releases a reference to the buffer and
+        // it's ownership moves to the BufferConsumer.
+        // In b2g, GonkBufferQueue continues to have a buffer ownership.
+        // It is necessary to free buffer via ImageBridgeChild.
 
-        if (mSlots[buf].mAcquireCalled) {
-            buffer->mGraphicBuffer = NULL;
-        } else {
-            buffer->mGraphicBuffer = mSlots[buf].mGraphicBuffer;
-        }
+        //if (mSlots[buf].mAcquireCalled) {
+        //    buffer->mGraphicBuffer = NULL;
+        //} else {
+        //    buffer->mGraphicBuffer = mSlots[buf].mGraphicBuffer;
+        //}
+        buffer->mGraphicBuffer = mSlots[buf].mGraphicBuffer;
+        buffer->mSurfaceDescriptor = mSlots[buf].mSurfaceDescriptor;
         buffer->mCrop = mSlots[buf].mCrop;
         buffer->mTransform = mSlots[buf].mTransform;
         buffer->mScalingMode = mSlots[buf].mScalingMode;
         buffer->mFrameNumber = mSlots[buf].mFrameNumber;
         buffer->mTimestamp = mSlots[buf].mTimestamp;
         buffer->mBuf = buf;
         buffer->mFence = mSlots[buf].mFence;
 
         mSlots[buf].mAcquireCalled = true;
         mSlots[buf].mNeedsCleanupOnRelease = false;
         mSlots[buf].mBufferState = BufferSlot::ACQUIRED;
         mSlots[buf].mFence = Fence::NO_FENCE;
 
         mQueue.erase(front);
         mDequeueCondition.broadcast();
-
-        ATRACE_INT(mConsumerName.string(), mQueue.size());
     } else {
         return NO_BUFFER_AVAILABLE;
     }
 
     return NO_ERROR;
 }
 
-status_t GonkBufferQueue::releaseBuffer(int buf, EGLDisplay display,
-        EGLSyncKHR eglFence, const sp<Fence>& fence) {
-    ATRACE_CALL();
-    ATRACE_BUFFER_INDEX(buf);
-
+status_t GonkBufferQueue::releaseBuffer(int buf, const sp<Fence>& fence) {
     Mutex::Autolock _l(mMutex);
 
     if (buf == INVALID_BUFFER_SLOT || fence == NULL) {
         return BAD_VALUE;
     }
 
-    mSlots[buf].mEglDisplay = display;
-    mSlots[buf].mEglFence = eglFence;
     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;
     } else if (mSlots[buf].mNeedsCleanupOnRelease) {
         ST_LOGV("releasing a stale buf %d its state was %d", buf, mSlots[buf].mBufferState);
         mSlots[buf].mNeedsCleanupOnRelease = false;
@@ -909,28 +909,33 @@ status_t GonkBufferQueue::consumerConnec
 
     mConsumerListener = consumerListener;
 
     return NO_ERROR;
 }
 
 status_t GonkBufferQueue::consumerDisconnect() {
     ST_LOGV("consumerDisconnect");
-    Mutex::Autolock lock(mMutex);
+    nsAutoTArray<SurfaceDescriptor, NUM_BUFFER_SLOTS> freeList;
+    {
+        Mutex::Autolock lock(mMutex);
 
-    if (mConsumerListener == NULL) {
-        ST_LOGE("consumerDisconnect: No consumer is connected!");
-        return -EINVAL;
+        if (mConsumerListener == NULL) {
+            ST_LOGE("consumerDisconnect: No consumer is connected!");
+            return -EINVAL;
+        }
+
+        mAbandoned = true;
+        mConsumerListener = NULL;
+        mQueue.clear();
+        freeAllBuffersLocked(freeList);
     }
+    releaseBufferFreeListUnlocked(freeList);
+    mDequeueCondition.broadcast();
 
-    mAbandoned = true;
-    mConsumerListener = NULL;
-    mQueue.clear();
-    freeAllBuffersLocked();
-    mDequeueCondition.broadcast();
     return NO_ERROR;
 }
 
 status_t GonkBufferQueue::getReleasedBuffers(uint32_t* slotMask) {
     ST_LOGV("getReleasedBuffers");
     Mutex::Autolock lock(mMutex);
 
     if (mAbandoned) {
@@ -961,77 +966,34 @@ status_t GonkBufferQueue::setDefaultBuff
 
     Mutex::Autolock lock(mMutex);
     mDefaultWidth = w;
     mDefaultHeight = h;
     return NO_ERROR;
 }
 
 status_t GonkBufferQueue::setDefaultMaxBufferCount(int bufferCount) {
-    ATRACE_CALL();
     Mutex::Autolock lock(mMutex);
     return setDefaultMaxBufferCountLocked(bufferCount);
 }
 
 status_t GonkBufferQueue::setMaxAcquiredBufferCount(int maxAcquiredBuffers) {
-    ATRACE_CALL();
     Mutex::Autolock lock(mMutex);
     if (maxAcquiredBuffers < 1 || maxAcquiredBuffers > MAX_MAX_ACQUIRED_BUFFERS) {
         ST_LOGE("setMaxAcquiredBufferCount: invalid count specified: %d",
                 maxAcquiredBuffers);
         return BAD_VALUE;
     }
     if (mConnectedApi != NO_CONNECTED_API) {
         return INVALID_OPERATION;
     }
     mMaxAcquiredBufferCount = maxAcquiredBuffers;
     return NO_ERROR;
 }
 
-void GonkBufferQueue::freeAllBuffersExceptHeadLocked() {
-    int head = -1;
-    if (!mQueue.empty()) {
-        Fifo::iterator front(mQueue.begin());
-        head = *front;
-    }
-    mBufferHasBeenQueued = false;
-    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
-        if (i != head) {
-            freeBufferLocked(i);
-        }
-    }
-}
-
-status_t GonkBufferQueue::drainQueueLocked() {
-    while (mSynchronousMode && mQueue.size() > 1) {
-        mDequeueCondition.wait(mMutex);
-        if (mAbandoned) {
-            ST_LOGE("drainQueueLocked: GonkBufferQueue has been abandoned!");
-            return NO_INIT;
-        }
-        if (mConnectedApi == NO_CONNECTED_API) {
-            ST_LOGE("drainQueueLocked: GonkBufferQueue is not connected!");
-            return NO_INIT;
-        }
-    }
-    return NO_ERROR;
-}
-
-status_t GonkBufferQueue::drainQueueAndFreeBuffersLocked() {
-    status_t err = drainQueueLocked();
-    if (err == NO_ERROR) {
-        if (mQueue.empty()) {
-            freeAllBuffersLocked();
-        } else {
-            freeAllBuffersExceptHeadLocked();
-        }
-    }
-    return err;
-}
-
 int GonkBufferQueue::getMinMaxBufferCountLocked() const {
     return getMinUndequeuedBufferCountLocked() + 1;
 }
 
 int GonkBufferQueue::getMinUndequeuedBufferCountLocked() const {
     return mSynchronousMode ? mMaxAcquiredBufferCount :
             mMaxAcquiredBufferCount + 1;
 }
--- a/widget/gonk/nativewindow/GonkBufferQueue.h
+++ b/widget/gonk/nativewindow/GonkBufferQueue.h
@@ -13,33 +13,34 @@
  * 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_GONKBUFFERQUEUE_H
 #define NATIVEWINDOW_GONKBUFFERQUEUE_H
 
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
 #include <gui/IGraphicBufferAlloc.h>
 #include <gui/IGraphicBufferProducer.h>
 
 #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"
+
 namespace android {
 // ----------------------------------------------------------------------------
 
 class GonkBufferQueue : public BnGraphicBufferProducer {
+    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 };
 
     // When in async mode we reserve two slots in order to guarantee that the
@@ -232,28 +233,32 @@ public:
     virtual void dump(String8& result) const;
     virtual void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const;
 
     // public facing structure for BufferSlot
     struct BufferItem {
 
         BufferItem()
          :
+           mSurfaceDescriptor(SurfaceDescriptor()),
            mTransform(0),
            mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
            mTimestamp(0),
            mFrameNumber(0),
            mBuf(INVALID_BUFFER_SLOT) {
              mCrop.makeInvalid();
         }
         // mGraphicBuffer points to the buffer allocated for this slot, or is NULL
         // if the buffer in this slot has been acquired in the past (see
         // BufferSlot.mAcquireCalled).
         sp<GraphicBuffer> mGraphicBuffer;
 
+        // mSurfaceDescriptor is the token to remotely allocated GraphicBuffer.
+        SurfaceDescriptor mSurfaceDescriptor;
+
         // mCrop is the current crop rectangle for this buffer slot.
         Rect mCrop;
 
         // mTransform is the current transform flags for this buffer slot.
         uint32_t mTransform;
 
         // mScalingMode is the current scaling mode for this buffer slot.
         uint32_t mScalingMode;
@@ -290,18 +295,17 @@ public:
     //
     // If releaseBuffer returns STALE_BUFFER_SLOT, then the consumer must free
     // any references to the just-released buffer that it might have, as if it
     // had received a onBuffersReleased() call with a mask set for the released
     // buffer.
     //
     // Note that the dependencies on EGL will be removed once we switch to using
     // the Android HW Sync HAL.
-    status_t releaseBuffer(int buf, EGLDisplay display, EGLSyncKHR fence,
-            const sp<Fence>& releaseFence);
+    status_t releaseBuffer(int buf, const sp<Fence>& releaseFence);
 
     // consumerConnect connects a consumer to the GonkBufferQueue.  Only one
     // consumer may be connected, and when that consumer disconnects the
     // GonkBufferQueue is placed into the "abandoned" state, causing most
     // interactions with the GonkBufferQueue by the producer to fail.
     //
     // consumer may not be NULL.
     status_t consumerConnect(const sp<ConsumerListener>& consumer);
@@ -355,39 +359,33 @@ public:
     // enumerated in gralloc.h, e.g. GRALLOC_USAGE_HW_RENDER; the default is 0.
     status_t setConsumerUsageBits(uint32_t usage);
 
     // setTransformHint bakes in rotation to buffers so overlays can be used.
     // The values are enumerated in window.h, e.g.
     // NATIVE_WINDOW_TRANSFORM_ROT_90.  The default is 0 (no transform).
     status_t setTransformHint(uint32_t hint);
 
+    int getGeneration();
+
+    SurfaceDescriptor *getSurfaceDescriptorFromBuffer(ANativeWindowBuffer* buffer);
+
 private:
+    // releaseBufferFreeListUnlocked releases the resources in the freeList;
+    // this must be called with mMutex unlocked.
+    void releaseBufferFreeListUnlocked(nsTArray<SurfaceDescriptor>& freeList);
+
     // freeBufferLocked frees the GraphicBuffer and sync resources for the
     // given slot.
-    void freeBufferLocked(int index);
+    //void freeBufferLocked(int index);
 
     // freeAllBuffersLocked frees the GraphicBuffer and sync resources for
     // all slots.
-    void freeAllBuffersLocked();
-
-    // freeAllBuffersExceptHeadLocked frees the GraphicBuffer and sync
-    // resources for all slots except the head of mQueue.
-    void freeAllBuffersExceptHeadLocked();
-
-    // drainQueueLocked waits for the buffer queue to empty if we're in
-    // synchronous mode, or returns immediately otherwise. It returns NO_INIT
-    // if the GonkBufferQueue is abandoned (consumer disconnected) or disconnected
-    // (producer disconnected) during the call.
-    status_t drainQueueLocked();
-
-    // drainQueueAndFreeBuffersLocked drains the buffer queue if we're in
-    // synchronous mode and free all buffers. In asynchronous mode, all buffers
-    // are freed except the currently queued buffer (if it exists).
-    status_t drainQueueAndFreeBuffersLocked();
+    //void freeAllBuffersLocked();
+    void freeAllBuffersLocked(nsTArray<SurfaceDescriptor>& freeList);
 
     // setDefaultMaxBufferCountLocked sets the maximum number of buffer slots
     // that will be used if the producer does not override the buffer slot
     // count.  The count must be between 2 and NUM_BUFFER_SLOTS, inclusive.
     // The initial default is 2.
     status_t setDefaultMaxBufferCountLocked(int count);
 
     // getMinBufferCountLocked returns the minimum number of buffers allowed
@@ -409,35 +407,34 @@ private:
     //
     // Any time one of these member variables is changed while a producer is
     // connected, mDequeueCondition must be broadcast.
     int getMaxBufferCountLocked() const;
 
     struct BufferSlot {
 
         BufferSlot()
-        : mEglDisplay(EGL_NO_DISPLAY),
+        : mSurfaceDescriptor(SurfaceDescriptor()),
           mBufferState(BufferSlot::FREE),
           mRequestBufferCalled(false),
           mTransform(0),
           mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
           mTimestamp(0),
           mFrameNumber(0),
-          mEglFence(EGL_NO_SYNC_KHR),
           mAcquireCalled(false),
           mNeedsCleanupOnRelease(false) {
             mCrop.makeInvalid();
         }
 
         // mGraphicBuffer points to the buffer allocated for this slot or is NULL
         // if no buffer has been allocated.
         sp<GraphicBuffer> mGraphicBuffer;
 
-        // mEglDisplay is the EGLDisplay used to create EGLSyncKHR objects.
-        EGLDisplay mEglDisplay;
+        // mSurfaceDescriptor is the token to remotely allocated GraphicBuffer.
+        SurfaceDescriptor mSurfaceDescriptor;
 
         // BufferState represents the different states in which a buffer slot
         // can be.  All slots are initially FREE.
         enum BufferState {
             // FREE indicates that the buffer is available to be dequeued
             // by the producer.  The buffer may be in use by the consumer for
             // a finite time, so the buffer must not be modified until the
             // associated fence is signaled.
@@ -503,17 +500,17 @@ private:
         // may be released before their release fence is signaled).
         uint64_t mFrameNumber;
 
         // mEglFence is the EGL sync object that must signal before the buffer
         // associated with this buffer slot may be dequeued. It is initialized
         // to EGL_NO_SYNC_KHR when the buffer is created and may be set to a
         // new sync object in releaseBuffer.  (This is deprecated in favor of
         // mFence, below.)
-        EGLSyncKHR mEglFence;
+        //EGLSyncKHR mEglFence;
 
         // mFence is a fence which will signal when work initiated by the
         // previous owner of the buffer is finished. When the buffer is FREE,
         // the fence indicates when the consumer has finished reading
         // from the buffer, or when the producer has finished writing if it
         // called cancelBuffer after queueing some writes. When the buffer is
         // QUEUED, it indicates when the producer has finished filling the
         // buffer. When the buffer is DEQUEUED or ACQUIRED, the fence has been
@@ -626,14 +623,17 @@ private:
     // the buffer format when it isn't specified in dequeueBuffer
     uint32_t mDefaultBufferFormat;
 
     // mConsumerUsageBits contains flags the consumer wants for GraphicBuffers
     uint32_t mConsumerUsageBits;
 
     // mTransformHint is used to optimize for screen rotations
     uint32_t mTransformHint;
+
+    // mGeneration is the current generation of buffer slots
+    uint32_t mGeneration;
 };
 
 // ----------------------------------------------------------------------------
 }; // namespace android
 
 #endif // ANDROID_GUI_BUFFERQUEUE_H
--- a/widget/gonk/nativewindow/GonkConsumerBase.cpp
+++ b/widget/gonk/nativewindow/GonkConsumerBase.cpp
@@ -16,38 +16,30 @@
  */
 
 #define LOG_TAG "GonkConsumerBase"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 //#define LOG_NDEBUG 0
 
 #define EGL_EGLEXT_PROTOTYPES
 
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
 #include <hardware/hardware.h>
 
 #include <gui/IGraphicBufferAlloc.h>
-#include <gui/ISurfaceComposer.h>
-#include <gui/SurfaceComposerClient.h>
-#include <gui/ConsumerBase.h>
-
-#include <private/gui/ComposerService.h>
-
 #include <utils/Log.h>
 #include <utils/String8.h>
-#include <utils/Trace.h>
+
+#include "GonkConsumerBase.h"
 
 // Macros for including the GonkConsumerBase name in log messages
-#define CB_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define CB_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define CB_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define CB_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define CB_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__)
+#define CB_LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
+#define CB_LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
+#define CB_LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
+#define CB_LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
+#define CB_LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
 
 namespace android {
 
 // Get an ID that's unique within this process.
 static int32_t createProcessUniqueId() {
     static volatile int32_t globalCounter = 0;
     return android_atomic_inc(&globalCounter);
 }
@@ -225,21 +217,19 @@ status_t GonkConsumerBase::addReleaseFen
             return BAD_VALUE;
         }
         mSlots[slot].mFence = mergedFence;
     }
 
     return OK;
 }
 
-status_t GonkConsumerBase::releaseBufferLocked(int slot, EGLDisplay display,
-       EGLSyncKHR eglFence) {
+status_t GonkConsumerBase::releaseBufferLocked(int slot) {
     CB_LOGV("releaseBufferLocked: slot=%d", slot);
-    status_t err = mBufferQueue->releaseBuffer(slot, display, eglFence,
-            mSlots[slot].mFence);
+    status_t err = mBufferQueue->releaseBuffer(slot, mSlots[slot].mFence);
     if (err == GonkBufferQueue::STALE_BUFFER_SLOT) {
         freeBufferLocked(slot);
     }
 
     mSlots[slot].mFence = Fence::NO_FENCE;
 
     return err;
 }
--- a/widget/gonk/nativewindow/GonkConsumerBase.h
+++ b/widget/gonk/nativewindow/GonkConsumerBase.h
@@ -13,24 +13,24 @@
  * 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_GONKCONSUMERBASE_H
 #define NATIVEWINDOW_GONKCONSUMERBASE_H
 
-#include <gui/BufferQueue.h>
-
 #include <ui/GraphicBuffer.h>
 
 #include <utils/String8.h>
 #include <utils/Vector.h>
 #include <utils/threads.h>
 
+#include "GonkBufferQueue.h"
+
 namespace android {
 // ----------------------------------------------------------------------------
 
 class String8;
 
 // GonkConsumerBase is a base class for GonkBufferQueue consumer end-points. It
 // handles common tasks like management of the connection to the GonkBufferQueue
 // and the buffer pool.
@@ -158,18 +158,17 @@ protected:
 
     // releaseBufferLocked relinquishes control over a buffer, returning that
     // control to the GonkBufferQueue.
     //
     // Derived classes should override this method to perform any cleanup that
     // must take place when a buffer is released back to the GonkBufferQueue.  If
     // it is overridden the derived class's implementation must call
     // GonkConsumerBase::releaseBufferLocked.
-    virtual status_t releaseBufferLocked(int buf, EGLDisplay display,
-           EGLSyncKHR eglFence);
+    virtual status_t releaseBufferLocked(int buf);
 
     // addReleaseFence* adds the sync points associated with a fence to the set
     // of sync points that must be reached before the buffer in the given slot
     // may be used after the slot has been released.  This should be called by
     // derived classes each time some asynchronous work is kicked off that
     // references the buffer.
     status_t addReleaseFence(int slot, const sp<Fence>& fence);
     status_t addReleaseFenceLocked(int slot, const sp<Fence>& fence);
@@ -210,17 +209,17 @@ protected:
 
     // 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.
     wp<FrameAvailableListener> mFrameAvailableListener;
 
     // The GonkConsumerBase has-a GonkBufferQueue and is responsible for creating this object
     // if none is supplied
-    sp<GonkBufferQueue> mGonkBufferQueue;
+    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
     // called.
     //
     // This mutex is intended to be locked by derived classes.
     mutable Mutex mMutex;
--- a/widget/gonk/nativewindow/GonkNativeWindow.h
+++ b/widget/gonk/nativewindow/GonkNativeWindow.h
@@ -1,2 +1,20 @@
+/* Copyright 2013 Mozilla Foundation and Mozilla contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
 
-#include "GonkNativeWindowICS.h"
+#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >=  18
+# 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
@@ -1,2 +1,20 @@
+/* Copyright 2013 Mozilla Foundation and Mozilla contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
 
-#include "GonkNativeWindowClientICS.h"
+#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >=  18
+# 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,30 +15,23 @@
  * limitations under the License.
  */
 
 #define LOG_TAG "GonkNativeWindowClient"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 //#define LOG_NDEBUG 0
 
 #include <android/native_window.h>
+#include <cutils/trace.h>
 
 #include <binder/Parcel.h>
-
 #include <utils/Log.h>
-#include <utils/Trace.h>
-
 #include <ui/Fence.h>
 
-#include <gui/ISurfaceComposer.h>
-#include <gui/SurfaceComposerClient.h>
-#include <gui/GLConsumer.h>
-#include <gui/Surface.h>
-
-#include <private/gui/ComposerService.h>
+#include "GonkNativeWindowClientJB.h"
 
 namespace android {
 
 GonkNativeWindowClient::GonkNativeWindowClient(
         const sp<IGraphicBufferProducer>& bufferProducer)
     : mGraphicBufferProducer(bufferProducer)
 {
     // Initialize the ANativeWindow function pointers.
@@ -152,17 +145,16 @@ int GonkNativeWindowClient::hook_query(c
 int GonkNativeWindowClient::hook_perform(ANativeWindow* window, int operation, ...) {
     va_list args;
     va_start(args, operation);
     GonkNativeWindowClient* c = getSelf(window);
     return c->perform(operation, args);
 }
 
 int GonkNativeWindowClient::setSwapInterval(int interval) {
-    ATRACE_CALL();
     // EGL specification states:
     //  interval is silently clamped to minimum and maximum implementation
     //  dependent values before being stored.
     // Although we don't have to, we apply the same logic here.
 
     if (interval < minSwapInterval)
         interval = minSwapInterval;
 
@@ -171,17 +163,16 @@ int GonkNativeWindowClient::setSwapInter
 
     status_t res = mGraphicBufferProducer->setSynchronousMode(interval ? true : false);
 
     return res;
 }
 
 int GonkNativeWindowClient::dequeueBuffer(android_native_buffer_t** buffer,
         int* fenceFd) {
-    ATRACE_CALL();
     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,
             reqW, reqH, mReqFormat, mReqUsage);
@@ -218,17 +209,16 @@ int GonkNativeWindowClient::dequeueBuffe
     }
 
     *buffer = gbuf.get();
     return OK;
 }
 
 int GonkNativeWindowClient::cancelBuffer(android_native_buffer_t* buffer,
         int fenceFd) {
-    ATRACE_CALL();
     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);
@@ -250,17 +240,16 @@ int GonkNativeWindowClient::getSlotFromB
 
 int GonkNativeWindowClient::lockBuffer_DEPRECATED(android_native_buffer_t* buffer) {
     ALOGV("GonkNativeWindowClient::lockBuffer");
     Mutex::Autolock lock(mMutex);
     return OK;
 }
 
 int GonkNativeWindowClient::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
-    ATRACE_CALL();
     ALOGV("GonkNativeWindowClient::queueBuffer");
     Mutex::Autolock lock(mMutex);
     int64_t timestamp;
     if (mTimestamp == NATIVE_WINDOW_TIMESTAMP_AUTO) {
         timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
         ALOGV("GonkNativeWindowClient::queueBuffer making up timestamp: %.2f ms",
              timestamp / 1000000.f);
     } else {
@@ -289,35 +278,34 @@ int GonkNativeWindowClient::queueBuffer(
             &numPendingBuffers);
 
     mConsumerRunningBehind = (numPendingBuffers >= 2);
 
     return err;
 }
 
 int GonkNativeWindowClient::query(int what, int* value) const {
-    ATRACE_CALL();
     ALOGV("GonkNativeWindowClient::query");
     { // scope for the lock
         Mutex::Autolock lock(mMutex);
         switch (what) {
             case NATIVE_WINDOW_FORMAT:
                 if (mReqFormat) {
                     *value = mReqFormat;
                     return NO_ERROR;
                 }
                 break;
             case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: {
-                sp<ISurfaceComposer> composer(
-                        ComposerService::getComposerService());
-                if (composer->authenticateSurfaceTexture(mGraphicBufferProducer)) {
-                    *value = 1;
-                } else {
+                //sp<ISurfaceComposer> composer(
+                //        ComposerService::getComposerService());
+                //if (composer->authenticateSurfaceTexture(mGraphicBufferProducer)) {
+                //    *value = 1;
+                //} else {
                     *value = 0;
-                }
+                //}
                 return NO_ERROR;
             }
             case NATIVE_WINDOW_CONCRETE_TYPE:
                 *value = NATIVE_WINDOW_SURFACE;
                 return NO_ERROR;
             case NATIVE_WINDOW_DEFAULT_WIDTH:
                 *value = mUserWidth ? mUserWidth : mDefaultWidth;
                 return NO_ERROR;
@@ -478,17 +466,16 @@ int GonkNativeWindowClient::dispatchLock
 }
 
 int GonkNativeWindowClient::dispatchUnlockAndPost(va_list args) {
     return unlockAndPost();
 }
 
 
 int GonkNativeWindowClient::connect(int api) {
-    ATRACE_CALL();
     ALOGV("GonkNativeWindowClient::connect");
     Mutex::Autolock lock(mMutex);
     IGraphicBufferProducer::QueueBufferOutput output;
     int err = mGraphicBufferProducer->connect(api, &output);
     if (err == NO_ERROR) {
         uint32_t numPendingBuffers = 0;
         output.deflate(&mDefaultWidth, &mDefaultHeight, &mTransformHint,
                 &numPendingBuffers);
@@ -496,17 +483,16 @@ int GonkNativeWindowClient::connect(int 
     }
     if (!err && api == NATIVE_WINDOW_API_CPU) {
         mConnectedToCpu = true;
     }
     return err;
 }
 
 int GonkNativeWindowClient::disconnect(int api) {
-    ATRACE_CALL();
     ALOGV("GonkNativeWindowClient::disconnect");
     Mutex::Autolock lock(mMutex);
     freeAllBuffers();
     int err = mGraphicBufferProducer->disconnect(api);
     if (!err) {
         mReqFormat = 0;
         mReqWidth = 0;
         mReqHeight = 0;
@@ -526,18 +512,16 @@ int GonkNativeWindowClient::setUsage(uin
     ALOGV("GonkNativeWindowClient::setUsage");
     Mutex::Autolock lock(mMutex);
     mReqUsage = reqUsage;
     return OK;
 }
 
 int GonkNativeWindowClient::setCrop(Rect const* rect)
 {
-    ATRACE_CALL();
-
     Rect realRect;
     if (rect == NULL || rect->isEmpty()) {
         realRect.clear();
     } else {
         realRect = *rect;
     }
 
     ALOGV("GonkNativeWindowClient::setCrop rect=[%d %d %d %d]",
@@ -545,51 +529,48 @@ int GonkNativeWindowClient::setCrop(Rect
 
     Mutex::Autolock lock(mMutex);
     mCrop = realRect;
     return NO_ERROR;
 }
 
 int GonkNativeWindowClient::setBufferCount(int bufferCount)
 {
-    ATRACE_CALL();
     ALOGV("GonkNativeWindowClient::setBufferCount");
     Mutex::Autolock lock(mMutex);
 
     status_t err = mGraphicBufferProducer->setBufferCount(bufferCount);
     ALOGE_IF(err, "IGraphicBufferProducer::setBufferCount(%d) returned %s",
             bufferCount, strerror(-err));
 
     if (err == NO_ERROR) {
         freeAllBuffers();
     }
 
     return err;
 }
 
 int GonkNativeWindowClient::setBuffersDimensions(int w, int h)
 {
-    ATRACE_CALL();
     ALOGV("GonkNativeWindowClient::setBuffersDimensions");
 
     if (w<0 || h<0)
         return BAD_VALUE;
 
     if ((w && !h) || (!w && h))
         return BAD_VALUE;
 
     Mutex::Autolock lock(mMutex);
     mReqWidth = w;
     mReqHeight = h;
     return NO_ERROR;
 }
 
 int GonkNativeWindowClient::setBuffersUserDimensions(int w, int h)
 {
-    ATRACE_CALL();
     ALOGV("GonkNativeWindowClient::setBuffersUserDimensions");
 
     if (w<0 || h<0)
         return BAD_VALUE;
 
     if ((w && !h) || (!w && h))
         return BAD_VALUE;
 
@@ -608,17 +589,16 @@ int GonkNativeWindowClient::setBuffersFo
 
     Mutex::Autolock lock(mMutex);
     mReqFormat = format;
     return NO_ERROR;
 }
 
 int GonkNativeWindowClient::setScalingMode(int mode)
 {
-    ATRACE_CALL();
     ALOGV("GonkNativeWindowClient::setScalingMode(%d)", mode);
 
     switch (mode) {
         case NATIVE_WINDOW_SCALING_MODE_FREEZE:
         case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
         case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
             break;
         default:
@@ -628,17 +608,16 @@ int GonkNativeWindowClient::setScalingMo
 
     Mutex::Autolock lock(mMutex);
     mScalingMode = mode;
     return NO_ERROR;
 }
 
 int GonkNativeWindowClient::setBuffersTransform(int transform)
 {
-    ATRACE_CALL();
     ALOGV("GonkNativeWindowClient::setBuffersTransform");
     Mutex::Autolock lock(mMutex);
     mTransform = transform;
     return NO_ERROR;
 }
 
 int GonkNativeWindowClient::setBuffersTimestamp(int64_t timestamp)
 {
@@ -652,184 +631,22 @@ void GonkNativeWindowClient::freeAllBuff
     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
         mSlots[i].buffer = 0;
     }
 }
 
 // ----------------------------------------------------------------------
 // the lock/unlock APIs must be used from the same thread
 
-static status_t copyBlt(
-        const sp<GraphicBuffer>& dst,
-        const sp<GraphicBuffer>& src,
-        const Region& reg)
-{
-    // src and dst with, height and format must be identical. no verification
-    // is done here.
-    status_t err;
-    uint8_t const * src_bits = NULL;
-    err = src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds(), (void**)&src_bits);
-    ALOGE_IF(err, "error locking src buffer %s", strerror(-err));
-
-    uint8_t* dst_bits = NULL;
-    err = dst->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(), (void**)&dst_bits);
-    ALOGE_IF(err, "error locking dst buffer %s", strerror(-err));
-
-    Region::const_iterator head(reg.begin());
-    Region::const_iterator tail(reg.end());
-    if (head != tail && src_bits && dst_bits) {
-        const size_t bpp = bytesPerPixel(src->format);
-        const size_t dbpr = dst->stride * bpp;
-        const size_t sbpr = src->stride * bpp;
-
-        while (head != tail) {
-            const Rect& r(*head++);
-            ssize_t h = r.height();
-            if (h <= 0) continue;
-            size_t size = r.width() * bpp;
-            uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp;
-            uint8_t       * d = dst_bits + (r.left + dst->stride * r.top) * bpp;
-            if (dbpr==sbpr && size==sbpr) {
-                size *= h;
-                h = 1;
-            }
-            do {
-                memcpy(d, s, size);
-                d += dbpr;
-                s += sbpr;
-            } while (--h > 0);
-        }
-    }
-
-    if (src_bits)
-        src->unlock();
-
-    if (dst_bits)
-        dst->unlock();
-
-    return err;
-}
-
 // ----------------------------------------------------------------------------
 
 status_t GonkNativeWindowClient::lock(
         ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds)
 {
-    if (mLockedBuffer != 0) {
-        ALOGE("GonkNativeWindowClient::lock failed, already locked");
-        return INVALID_OPERATION;
-    }
-
-    if (!mConnectedToCpu) {
-        int err = GonkNativeWindowClient::connect(NATIVE_WINDOW_API_CPU);
-        if (err) {
-            return err;
-        }
-        // we're intending to do software rendering from this point
-        setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
-    }
-
-    ANativeWindowBuffer* out;
-    int fenceFd = -1;
-    status_t err = dequeueBuffer(&out, &fenceFd);
-    ALOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err));
-    if (err == NO_ERROR) {
-        sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out));
-        sp<Fence> fence(new Fence(fenceFd));
-
-        err = fence->waitForever("GonkNativeWindowClient::lock");
-        if (err != OK) {
-            ALOGE("Fence::wait failed (%s)", strerror(-err));
-            cancelBuffer(out, fenceFd);
-            return err;
-        }
-
-        const Rect bounds(backBuffer->width, backBuffer->height);
-
-        Region newDirtyRegion;
-        if (inOutDirtyBounds) {
-            newDirtyRegion.set(static_cast<Rect const&>(*inOutDirtyBounds));
-            newDirtyRegion.andSelf(bounds);
-        } else {
-            newDirtyRegion.set(bounds);
-        }
-
-        // figure out if we can copy the frontbuffer back
-        const sp<GraphicBuffer>& frontBuffer(mPostedBuffer);
-        const bool canCopyBack = (frontBuffer != 0 &&
-                backBuffer->width  == frontBuffer->width &&
-                backBuffer->height == frontBuffer->height &&
-                backBuffer->format == frontBuffer->format);
-
-        if (canCopyBack) {
-            // copy the area that is invalid and not repainted this round
-            const Region copyback(mDirtyRegion.subtract(newDirtyRegion));
-            if (!copyback.isEmpty())
-                copyBlt(backBuffer, frontBuffer, copyback);
-        } else {
-            // if we can't copy-back anything, modify the user's dirty
-            // region to make sure they redraw the whole buffer
-            newDirtyRegion.set(bounds);
-            mDirtyRegion.clear();
-            Mutex::Autolock lock(mMutex);
-            for (size_t i=0 ; i<NUM_BUFFER_SLOTS ; i++) {
-                mSlots[i].dirtyRegion.clear();
-            }
-        }
-
-
-        { // scope for the lock
-            Mutex::Autolock lock(mMutex);
-            int backBufferSlot(getSlotFromBufferLocked(backBuffer.get()));
-            if (backBufferSlot >= 0) {
-                Region& dirtyRegion(mSlots[backBufferSlot].dirtyRegion);
-                mDirtyRegion.subtract(dirtyRegion);
-                dirtyRegion = newDirtyRegion;
-            }
-        }
-
-        mDirtyRegion.orSelf(newDirtyRegion);
-        if (inOutDirtyBounds) {
-            *inOutDirtyBounds = newDirtyRegion.getBounds();
-        }
-
-        void* vaddr;
-        status_t res = backBuffer->lock(
-                GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
-                newDirtyRegion.bounds(), &vaddr);
-
-        ALOGW_IF(res, "failed locking buffer (handle = %p)",
-                backBuffer->handle);
-
-        if (res != 0) {
-            err = INVALID_OPERATION;
-        } else {
-            mLockedBuffer = backBuffer;
-            outBuffer->width  = backBuffer->width;
-            outBuffer->height = backBuffer->height;
-            outBuffer->stride = backBuffer->stride;
-            outBuffer->format = backBuffer->format;
-            outBuffer->bits   = vaddr;
-        }
-    }
-    return err;
+    return INVALID_OPERATION;
 }
 
 status_t GonkNativeWindowClient::unlockAndPost()
 {
-    if (mLockedBuffer == 0) {
-        ALOGE("GonkNativeWindowClient::unlockAndPost failed, no locked buffer");
-        return INVALID_OPERATION;
-    }
-
-    status_t err = mLockedBuffer->unlock();
-    ALOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle);
-
-    err = queueBuffer(mLockedBuffer.get(), -1);
-    ALOGE_IF(err, "queueBuffer (handle=%p) failed (%s)",
-            mLockedBuffer->handle, strerror(-err));
-
-    mPostedBuffer = mLockedBuffer;
-    mLockedBuffer = 0;
-    return err;
+    return INVALID_OPERATION;
 }
 
 }; // namespace android
--- a/widget/gonk/nativewindow/GonkNativeWindowClientJB.h
+++ b/widget/gonk/nativewindow/GonkNativeWindowClientJB.h
@@ -14,26 +14,26 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 #ifndef NATIVEWINDOW_GONKNATIVEWINDOWCLIENT_JB_H
 #define NATIVEWINDOW_GONKNATIVEWINDOWCLIENT_JB_H
 
 #include <gui/IGraphicBufferProducer.h>
-#include <gui/GLConsumer.h>
-#include <gui/BufferQueue.h>
 
 #include <ui/ANativeObjectBase.h>
 #include <ui/Region.h>
 
 #include <utils/RefBase.h>
 #include <utils/threads.h>
 #include <utils/KeyedVector.h>
 
+#include "GonkBufferQueue.h"
+
 struct ANativeWindow_Buffer;
 
 namespace android {
 
 /*
  * An implementation of ANativeWindow that feeds graphics buffers into a
  * BufferQueue.
  *
@@ -143,17 +143,17 @@ protected:
     virtual int setCrop(Rect const* rect);
     virtual int setUsage(uint32_t reqUsage);
 
 public:
     virtual int lock(ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds);
     virtual int unlockAndPost();
 
 protected:
-    enum { NUM_BUFFER_SLOTS = BufferQueue::NUM_BUFFER_SLOTS };
+    enum { NUM_BUFFER_SLOTS = GonkBufferQueue::NUM_BUFFER_SLOTS };
     enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 };
 
 private:
     void freeAllBuffers();
     int getSlotFromBufferLocked(android_native_buffer_t* buffer) const;
 
     struct BufferSlot {
         sp<GraphicBuffer> buffer;
--- a/widget/gonk/nativewindow/GonkNativeWindowJB.cpp
+++ b/widget/gonk/nativewindow/GonkNativeWindowJB.cpp
@@ -15,36 +15,36 @@
  * limitations under the License.
  */
 
 //#define LOG_NDEBUG 0
 #define LOG_TAG "GonkNativeWindow"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 #include <utils/Log.h>
 
-#include <gui/BufferItemConsumer.h>
+#include "GonkNativeWindowJB.h"
+#include "GrallocImages.h"
 
-#define BI_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define BI_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define BI_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define BI_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define BI_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__)
+#define BI_LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
+#define BI_LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
+#define BI_LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
+#define BI_LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
+#define BI_LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
+
+using namespace mozilla::layers;
 
 namespace android {
 
-GonkNativeWindow::BufferItemConsumer(uint32_t consumerUsage,
-        int bufferCount, bool synchronousMode) :
-    ConsumerBase(new BufferQueue(true) )
+GonkNativeWindow::GonkNativeWindow() :
+    GonkConsumerBase(new GonkBufferQueue(true) )
 {
-    mBufferQueue->setConsumerUsageBits(consumerUsage);
-    mBufferQueue->setSynchronousMode(synchronousMode);
-    mBufferQueue->setMaxAcquiredBufferCount(bufferCount);
+    mBufferQueue->setMaxAcquiredBufferCount(GonkBufferQueue::MIN_UNDEQUEUED_BUFFERS);
 }
 
-GonkNativeWindow::~BufferItemConsumer() {
+GonkNativeWindow::~GonkNativeWindow() {
 }
 
 void GonkNativeWindow::setName(const String8& name) {
     Mutex::Autolock _l(mMutex);
     mName = name;
     mBufferQueue->setConsumerName(name);
 }
 
@@ -80,18 +80,17 @@ status_t GonkNativeWindow::acquireBuffer
 status_t GonkNativeWindow::releaseBuffer(const BufferItem &item,
         const sp<Fence>& releaseFence) {
     status_t err;
 
     Mutex::Autolock _l(mMutex);
 
     err = addReleaseFenceLocked(item.mBuf, releaseFence);
 
-    err = releaseBufferLocked(item.mBuf, EGL_NO_DISPLAY,
-            EGL_NO_SYNC_KHR);
+    err = releaseBufferLocked(item.mBuf);
     if (err != OK) {
         BI_LOGE("Failed to release buffer: %s (%d)",
                 strerror(-err), err);
     }
     return err;
 }
 
 status_t GonkNativeWindow::setDefaultBufferSize(uint32_t w, uint32_t h) {
@@ -99,9 +98,66 @@ status_t GonkNativeWindow::setDefaultBuf
     return mBufferQueue->setDefaultBufferSize(w, h);
 }
 
 status_t GonkNativeWindow::setDefaultBufferFormat(uint32_t defaultFormat) {
     Mutex::Autolock _l(mMutex);
     return mBufferQueue->setDefaultBufferFormat(defaultFormat);
 }
 
+already_AddRefed<GraphicBufferLocked>
+GonkNativeWindow::getCurrentBuffer()
+{
+    Mutex::Autolock _l(mMutex);
+    GonkBufferQueue::BufferItem item;
+
+    // In asynchronous mode the list is guaranteed to be one buffer
+    // deep, while in synchronous mode we use the oldest buffer.
+    status_t err = acquireBufferLocked(&item);
+    if (err != NO_ERROR) {
+        return NULL;
+    }
+
+  nsRefPtr<GraphicBufferLocked> ret =
+    new CameraGraphicBuffer(this, item.mBuf, mBufferQueue->getGeneration(), item.mSurfaceDescriptor);
+  return ret.forget();
+}
+
+bool
+GonkNativeWindow::returnBuffer(uint32_t aIndex, uint32_t aGeneration) {
+    BI_LOGD("GonkNativeWindow::returnBuffer: slot=%d (generation=%d)", aIndex, aGeneration);
+    Mutex::Autolock lock(mMutex);
+
+    if (aGeneration != mBufferQueue->getGeneration()) {
+        BI_LOGD("returnBuffer: buffer is from generation %d (current is %d)",
+          aGeneration, mBufferQueue->getGeneration());
+        return false;
+    }
+
+    status_t err = releaseBufferLocked(aIndex);
+    if (err != NO_ERROR) {
+        return false;
+    }
+  return true;
+}
+
+mozilla::layers::SurfaceDescriptor *
+GonkNativeWindow::getSurfaceDescriptorFromBuffer(ANativeWindowBuffer* buffer)
+{
+    Mutex::Autolock lock(mMutex);
+    return mBufferQueue->getSurfaceDescriptorFromBuffer(buffer);
+}
+void GonkNativeWindow::setNewFrameCallback(
+        GonkNativeWindowNewFrameCallback* aCallback) {
+    BI_LOGD("setNewFrameCallback");
+    Mutex::Autolock lock(mMutex);
+    mNewFrameCallback = aCallback;
+}
+
+void GonkNativeWindow::onFrameAvailable() {
+    GonkConsumerBase::onFrameAvailable();
+
+    if (mNewFrameCallback) {
+      mNewFrameCallback->OnNewFrame();
+    }
+}
+
 } // namespace android
--- a/widget/gonk/nativewindow/GonkNativeWindowJB.h
+++ b/widget/gonk/nativewindow/GonkNativeWindowJB.h
@@ -13,51 +13,65 @@
  * 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_GONKNATIVEWINDOW_JB_H
 #define NATIVEWINDOW_GONKNATIVEWINDOW_JB_H
 
-#include <gui/ConsumerBase.h>
-
 #include <ui/GraphicBuffer.h>
-
 #include <utils/String8.h>
 #include <utils/Vector.h>
 #include <utils/threads.h>
 
-#define ANDROID_GRAPHICS_BUFFERITEMCONSUMER_JNI_ID "mBufferItemConsumer"
+#include "CameraCommon.h"
+#include "GonkConsumerBase.h"
+#include "GrallocImages.h"
+#include "mozilla/layers/ImageBridgeChild.h"
+#include "mozilla/layers/LayersSurfaces.h"
+
+namespace mozilla {
+namespace layers {
+    class PGrallocBufferChild;
+}
+}
 
 namespace android {
 
+// The user of GonkNativeWindow who wants to receive notification of
+// new frames should implement this interface.
+class GonkNativeWindowNewFrameCallback {
+public:
+    virtual void OnNewFrame() = 0;
+};
+
 /**
- * GonkNativeWindow is a BufferQueue consumer endpoint that allows clients
- * access to the whole BufferItem entry from BufferQueue. Multiple buffers may
+ * GonkNativeWindow is a GonkBufferQueue consumer endpoint that allows clients
+ * access to the whole BufferItem entry from GonkBufferQueue. Multiple buffers may
  * be acquired at once, to be used concurrently by the client. This consumer can
  * operate either in synchronous or asynchronous mode.
  */
-class GonkNativeWindow: public ConsumerBase
+class GonkNativeWindow: public GonkConsumerBase
 {
+    typedef mozilla::layers::GraphicBufferLocked GraphicBufferLocked;
+    typedef mozilla::layers::SurfaceDescriptor SurfaceDescriptor;
   public:
-    typedef ConsumerBase::FrameAvailableListener FrameAvailableListener;
+    typedef GonkConsumerBase::FrameAvailableListener FrameAvailableListener;
 
-    typedef BufferQueue::BufferItem BufferItem;
+    typedef GonkBufferQueue::BufferItem BufferItem;
 
-    enum { INVALID_BUFFER_SLOT = BufferQueue::INVALID_BUFFER_SLOT };
-    enum { NO_BUFFER_AVAILABLE = BufferQueue::NO_BUFFER_AVAILABLE };
+    enum { INVALID_BUFFER_SLOT = GonkBufferQueue::INVALID_BUFFER_SLOT };
+    enum { NO_BUFFER_AVAILABLE = GonkBufferQueue::NO_BUFFER_AVAILABLE };
 
     // Create a new buffer item consumer. The consumerUsage parameter determines
     // the consumer usage flags passed to the graphics allocator. The
     // bufferCount parameter specifies how many buffers can be locked for user
     // access at the same time.
-    GonkNativeWindow(uint32_t consumerUsage,
-            int bufferCount = BufferQueue::MIN_UNDEQUEUED_BUFFERS,
-            bool synchronousMode = false);
+    GonkNativeWindow();
 
     virtual ~GonkNativeWindow();
 
     // set the name of the GonkNativeWindow that will be used to identify it in
     // log messages.
     void setName(const String8& name);
 
     // Gets the next graphics buffer from the producer, filling out the
@@ -88,13 +102,81 @@ class GonkNativeWindow: public ConsumerB
     // 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
     // GraphicBuffers of a defaultFormat if no format is specified
     // in dequeueBuffer
     status_t setDefaultBufferFormat(uint32_t defaultFormat);
+
+    // Get next frame from the queue, caller owns the returned buffer.
+    already_AddRefed<GraphicBufferLocked> getCurrentBuffer();
+
+    // Return the buffer to the queue and mark it as FREE. After that
+    // the buffer is useable again for the decoder.
+    bool returnBuffer(uint32_t index, uint32_t generation);
+
+    SurfaceDescriptor* getSurfaceDescriptorFromBuffer(ANativeWindowBuffer* buffer);
+
+    void setNewFrameCallback(GonkNativeWindowNewFrameCallback* aCallback);
+
+protected:
+    virtual void onFrameAvailable();
+
+private:
+    GonkNativeWindowNewFrameCallback* mNewFrameCallback;
+};
+
+// CameraGraphicBuffer maintains the buffer returned from GonkNativeWindow
+class CameraGraphicBuffer : public mozilla::layers::GraphicBufferLocked
+{
+    typedef mozilla::layers::SurfaceDescriptor SurfaceDescriptor;
+    typedef mozilla::layers::ImageBridgeChild ImageBridgeChild;
+
+public:
+    CameraGraphicBuffer(GonkNativeWindow* aNativeWindow,
+                        uint32_t aIndex,
+                        uint32_t aGeneration,
+                        SurfaceDescriptor aBuffer)
+        : GraphicBufferLocked(aBuffer)
+        , mNativeWindow(aNativeWindow)
+        , mIndex(aIndex)
+        , mGeneration(aGeneration)
+        , mLocked(true)
+    {
+        DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+    }
+
+    virtual ~CameraGraphicBuffer()
+    {
+        DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+    }
+
+    // Unlock either returns the buffer to the native window or
+    // destroys the buffer if the window is already released.
+    virtual void Unlock() MOZ_OVERRIDE
+    {
+        if (mLocked) {
+            // The window might have been destroyed. The buffer is no longer
+            // valid at that point.
+            sp<GonkNativeWindow> window = mNativeWindow.promote();
+            if (window.get() && window->returnBuffer(mIndex, mGeneration)) {
+                mLocked = false;
+            } else {
+                // If the window doesn't exist any more, release the buffer
+                // directly.
+                ImageBridgeChild *ibc = ImageBridgeChild::GetSingleton();
+                ibc->DeallocSurfaceDescriptorGralloc(mSurfaceDescriptor);
+            } 
+        }
+    }
+
+protected:
+    wp<GonkNativeWindow> mNativeWindow;
+    uint32_t mIndex;
+    uint32_t mGeneration;
+    bool mLocked;
 };
 
 } // namespace android
 
 #endif // NATIVEWINDOW_GONKNATIVEWINDOW_JB_H
--- a/widget/gonk/nativewindow/moz.build
+++ b/widget/gonk/nativewindow/moz.build
@@ -16,25 +16,41 @@
 
 MODULE = 'nativewindow'
 
 EXPORTS += [
     'GonkNativeWindow.h',
     'GonkNativeWindowClient.h',
 ]
 
-EXPORTS += [
-    'GonkNativeWindowClientICS.h',
-    'GonkNativeWindowICS.h',
-]
+if CONFIG['ANDROID_VERSION'] == '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']:
-    CPP_SOURCES += [
-        'GonkNativeWindowICS.cpp',
-        'GonkNativeWindowClientICS.cpp',
-    ]
+    if CONFIG['ANDROID_VERSION'] == '18':
+        CPP_SOURCES += [
+            'GonkBufferQueue.cpp',
+            'GonkConsumerBase.cpp',
+            'GonkNativeWindowJB.cpp',
+            'GonkNativeWindowClientJB.cpp',
+        ]
+    elif CONFIG['ANDROID_VERSION'] == '15':
+        CPP_SOURCES += [
+            'GonkNativeWindowClientICS.cpp',
+            'GonkNativeWindowICS.cpp',
+        ]
 
 FAIL_ON_WARNINGS = True
 
 LIBXUL_LIBRARY = True
 
 LIBRARY_NAME = 'nativewindow'