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 159785 91d00574540191ef40fc7e9b7b348ca57e79ec75
parent 159784 4ab45ab4f80b5962348cc9bc6d24d794f94d9735
child 159786 4fc92e3e3ce0d3dc9d3d235ce4d497bc83212f9a
push id2961
push userlsblakk@mozilla.com
push dateMon, 28 Oct 2013 21:59:28 +0000
treeherdermozilla-beta@73ef4f13486f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjmuizelaar, mwu, doublec, mikeh, glandium
bugs871364
milestone26.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 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'