Merge "do not do bandwidth estimation if total data downloaded is too small"
diff --git a/camera/camera2/ICameraDeviceUser.cpp b/camera/camera2/ICameraDeviceUser.cpp
index 277b5db..d1d63d5 100644
--- a/camera/camera2/ICameraDeviceUser.cpp
+++ b/camera/camera2/ICameraDeviceUser.cpp
@@ -208,14 +208,11 @@
         return reply.readInt32();
     }
 
-    virtual status_t createStream(int width, int height, int format,
+    virtual status_t createStream(
                           const sp<IGraphicBufferProducer>& bufferProducer)
     {
         Parcel data, reply;
         data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
-        data.writeInt32(width);
-        data.writeInt32(height);
-        data.writeInt32(format);
 
         data.writeInt32(1); // marker that bufferProducer is not null
         data.writeString16(String16("unknown_name")); // name of surface
@@ -396,14 +393,6 @@
         } break;
         case CREATE_STREAM: {
             CHECK_INTERFACE(ICameraDeviceUser, data, reply);
-            int width, height, format;
-
-            width = data.readInt32();
-            ALOGV("%s: CREATE_STREAM: width = %d", __FUNCTION__, width);
-            height = data.readInt32();
-            ALOGV("%s: CREATE_STREAM: height = %d", __FUNCTION__, height);
-            format = data.readInt32();
-            ALOGV("%s: CREATE_STREAM: format = %d", __FUNCTION__, format);
 
             sp<IGraphicBufferProducer> bp;
             if (data.readInt32() != 0) {
@@ -419,7 +408,7 @@
             }
 
             status_t ret;
-            ret = createStream(width, height, format, bp);
+            ret = createStream(bp);
 
             reply->writeNoException();
             ALOGV("%s: CREATE_STREAM: write noException", __FUNCTION__);
diff --git a/include/camera/camera2/ICameraDeviceUser.h b/include/camera/camera2/ICameraDeviceUser.h
index 35488bb..bfc2aa0 100644
--- a/include/camera/camera2/ICameraDeviceUser.h
+++ b/include/camera/camera2/ICameraDeviceUser.h
@@ -101,7 +101,6 @@
 
     virtual status_t        deleteStream(int streamId) = 0;
     virtual status_t        createStream(
-            int width, int height, int format,
             const sp<IGraphicBufferProducer>& bufferProducer) = 0;
 
     // Create a request object from a template.
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index 2e1ed6c..3de0774 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -63,7 +63,7 @@
                                     // See AudioTimestamp for the information included with event.
     };
 
-    /* Client should declare Buffer on the stack and pass address to obtainBuffer()
+    /* Client should declare a Buffer and pass the address to obtainBuffer()
      * and releaseBuffer().  See also callback_t for EVENT_MORE_DATA.
      */
 
@@ -72,14 +72,20 @@
     public:
         // FIXME use m prefix
         size_t      frameCount;   // number of sample frames corresponding to size;
-                                  // on input it is the number of frames desired,
-                                  // on output is the number of frames actually filled
-                                  // (currently ignored, but will make the primary field in future)
+                                  // on input to obtainBuffer() it is the number of frames desired,
+                                  // on output from obtainBuffer() it is the number of available
+                                  //    [empty slots for] frames to be filled
+                                  // on input to releaseBuffer() it is currently ignored
 
         size_t      size;         // input/output in bytes == frameCount * frameSize
-                                  // on input it is unused
-                                  // on output is the number of bytes actually filled
-                                  // FIXME this is redundant with respect to frameCount.
+                                  // on input to obtainBuffer() it is ignored
+                                  // on output from obtainBuffer() it is the number of available
+                                  //    [empty slots for] bytes to be filled,
+                                  //    which is frameCount * frameSize
+                                  // on input to releaseBuffer() it is the number of bytes to
+                                  //    release
+                                  // FIXME This is redundant with respect to frameCount.  Consider
+                                  //    removing size and making frameCount the primary field.
 
         union {
             void*       raw;
@@ -484,10 +490,18 @@
      */
             status_t    attachAuxEffect(int effectId);
 
-    /* Obtains a buffer of up to "audioBuffer->frameCount" empty slots for frames.
+    /* Public API for TRANSFER_OBTAIN mode.
+     * Obtains a buffer of up to "audioBuffer->frameCount" empty slots for frames.
      * After filling these slots with data, the caller should release them with releaseBuffer().
      * If the track buffer is not full, obtainBuffer() returns as many contiguous
      * [empty slots for] frames as are available immediately.
+     *
+     * If nonContig is non-NULL, it is an output parameter that will be set to the number of
+     * additional non-contiguous frames that are predicted to be available immediately,
+     * if the client were to release the first frames and then call obtainBuffer() again.
+     * This value is only a prediction, and needs to be confirmed.
+     * It will be set to zero for an error return.
+     *
      * If the track buffer is full and track is stopped, obtainBuffer() returns WOULD_BLOCK
      * regardless of the value of waitCount.
      * If the track buffer is full and track is not stopped, obtainBuffer() blocks with a
@@ -496,7 +510,6 @@
      * is exhausted, at which point obtainBuffer() will either block
      * or return WOULD_BLOCK depending on the value of the "waitCount"
      * parameter.
-     * Each sample is 16-bit signed PCM.
      *
      * obtainBuffer() and releaseBuffer() are deprecated for direct use by applications,
      * which should use write() or callback EVENT_MORE_DATA instead.
@@ -508,24 +521,29 @@
      *
      * Buffer fields
      * On entry:
-     *  frameCount  number of frames requested
+     *  frameCount  number of [empty slots for] frames requested
+     *  size        ignored
+     *  raw         ignored
      * After error return:
      *  frameCount  0
      *  size        0
      *  raw         undefined
      * After successful return:
-     *  frameCount  actual number of frames available, <= number requested
+     *  frameCount  actual number of [empty slots for] frames available, <= number requested
      *  size        actual number of bytes available
      *  raw         pointer to the buffer
      */
-
     /* FIXME Deprecated public API for TRANSFER_OBTAIN mode */
-            status_t    obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
+            status_t    obtainBuffer(Buffer* audioBuffer, int32_t waitCount,
+                                size_t *nonContig = NULL)
                                 __attribute__((__deprecated__));
 
 private:
     /* If nonContig is non-NULL, it is an output parameter that will be set to the number of
-     * additional non-contiguous frames that are available immediately.
+     * additional non-contiguous frames that are predicted to be available immediately,
+     * if the client were to release the first frames and then call obtainBuffer() again.
+     * This value is only a prediction, and needs to be confirmed.
+     * It will be set to zero for an error return.
      * FIXME We could pass an array of Buffers instead of only one Buffer to obtainBuffer(),
      * in case the requested amount of frames is in two or more non-contiguous regions.
      * FIXME requested and elapsed are both relative times.  Consider changing to absolute time.
@@ -534,9 +552,17 @@
                                      struct timespec *elapsed = NULL, size_t *nonContig = NULL);
 public:
 
-    /* Release a filled buffer of "audioBuffer->frameCount" frames for AudioFlinger to process. */
+    /* Public API for TRANSFER_OBTAIN mode.
+     * Release a filled buffer of frames for AudioFlinger to process.
+     *
+     * Buffer fields:
+     *  frameCount  currently ignored but recommend to set to actual number of frames filled
+     *  size        actual number of bytes filled, must be multiple of frameSize
+     *  raw         ignored
+     *
+     */
     // FIXME make private when obtainBuffer() for TRANSFER_OBTAIN is removed
-            void        releaseBuffer(Buffer* audioBuffer);
+            void        releaseBuffer(const Buffer* audioBuffer);
 
     /* As a convenience we provide a write() interface to the audio buffer.
      * Input parameter 'size' is in byte units.
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 1d5fc95..0ad9cc0 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -1002,7 +1002,9 @@
             // use case 1: shared buffer
             (mSharedBuffer != 0) ||
             // use case 2: callback transfer mode
-            (mTransfer == TRANSFER_CALLBACK)) &&
+            (mTransfer == TRANSFER_CALLBACK) ||
+            // use case 3: obtain/release mode
+            (mTransfer == TRANSFER_OBTAIN)) &&
             // matching sample rate
             (mSampleRate == afSampleRate))) {
         ALOGW("AUDIO_OUTPUT_FLAG_FAST denied by client");
@@ -1236,7 +1238,7 @@
     return status;
 }
 
-status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
+status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount, size_t *nonContig)
 {
     if (audioBuffer == NULL) {
         return BAD_VALUE;
@@ -1263,7 +1265,7 @@
         ALOGE("%s invalid waitCount %d", __func__, waitCount);
         requested = NULL;
     }
-    return obtainBuffer(audioBuffer, requested);
+    return obtainBuffer(audioBuffer, requested, NULL /*elapsed*/, nonContig);
 }
 
 status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, const struct timespec *requested,
@@ -1338,8 +1340,9 @@
     return status;
 }
 
-void AudioTrack::releaseBuffer(Buffer* audioBuffer)
+void AudioTrack::releaseBuffer(const Buffer* audioBuffer)
 {
+    // FIXME add error checking on mode, by adding an internal version
     if (mTransfer == TRANSFER_SHARED) {
         return;
     }
diff --git a/media/libmediaplayerservice/Drm.cpp b/media/libmediaplayerservice/Drm.cpp
index 73f1a2a..d4f6fab 100644
--- a/media/libmediaplayerservice/Drm.cpp
+++ b/media/libmediaplayerservice/Drm.cpp
@@ -23,6 +23,8 @@
 
 #include "Drm.h"
 
+#include "DrmSessionClientInterface.h"
+#include "DrmSessionManager.h"
 #include <media/drm/DrmAPI.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AString.h>
@@ -33,6 +35,10 @@
 
 namespace android {
 
+static inline int getCallingPid() {
+    return IPCThreadState::self()->getCallingPid();
+}
+
 static bool checkPermission(const char* permissionString) {
 #ifndef HAVE_ANDROID_OS
     return true;
@@ -57,14 +63,41 @@
     return memcmp((void *)lhs.array(), (void *)rhs.array(), rhs.size()) < 0;
 }
 
+struct DrmSessionClient : public DrmSessionClientInterface {
+    DrmSessionClient(Drm* drm) : mDrm(drm) {}
+
+    virtual bool reclaimSession(const Vector<uint8_t>& sessionId) {
+        sp<Drm> drm = mDrm.promote();
+        if (drm == NULL) {
+            return true;
+        }
+        status_t err = drm->closeSession(sessionId);
+        if (err != OK) {
+            return false;
+        }
+        drm->sendEvent(DrmPlugin::kDrmPluginEventSessionReclaimed, 0, &sessionId, NULL);
+        return true;
+    }
+
+protected:
+    virtual ~DrmSessionClient() {}
+
+private:
+    wp<Drm> mDrm;
+
+    DISALLOW_EVIL_CONSTRUCTORS(DrmSessionClient);
+};
+
 Drm::Drm()
     : mInitCheck(NO_INIT),
+      mDrmSessionClient(new DrmSessionClient(this)),
       mListener(NULL),
       mFactory(NULL),
       mPlugin(NULL) {
 }
 
 Drm::~Drm() {
+    DrmSessionManager::Instance()->removeDrm(mDrmSessionClient);
     delete mPlugin;
     mPlugin = NULL;
     closeFactory();
@@ -289,7 +322,18 @@
         return -EINVAL;
     }
 
-    return mPlugin->openSession(sessionId);
+    status_t err = mPlugin->openSession(sessionId);
+    if (err == ERROR_DRM_RESOURCE_BUSY) {
+        bool retry = false;
+        retry = DrmSessionManager::Instance()->reclaimSession(getCallingPid());
+        if (retry) {
+            err = mPlugin->openSession(sessionId);
+        }
+    }
+    if (err == OK) {
+        DrmSessionManager::Instance()->addSession(getCallingPid(), mDrmSessionClient, sessionId);
+    }
+    return err;
 }
 
 status_t Drm::closeSession(Vector<uint8_t> const &sessionId) {
@@ -303,7 +347,11 @@
         return -EINVAL;
     }
 
-    return mPlugin->closeSession(sessionId);
+    status_t err = mPlugin->closeSession(sessionId);
+    if (err == OK) {
+        DrmSessionManager::Instance()->removeSession(sessionId);
+    }
+    return err;
 }
 
 status_t Drm::getKeyRequest(Vector<uint8_t> const &sessionId,
@@ -321,6 +369,8 @@
         return -EINVAL;
     }
 
+    DrmSessionManager::Instance()->useSession(sessionId);
+
     return mPlugin->getKeyRequest(sessionId, initData, mimeType, keyType,
                                   optionalParameters, request, defaultUrl);
 }
@@ -338,6 +388,8 @@
         return -EINVAL;
     }
 
+    DrmSessionManager::Instance()->useSession(sessionId);
+
     return mPlugin->provideKeyResponse(sessionId, response, keySetId);
 }
 
@@ -367,6 +419,8 @@
         return -EINVAL;
     }
 
+    DrmSessionManager::Instance()->useSession(sessionId);
+
     return mPlugin->restoreKeys(sessionId, keySetId);
 }
 
@@ -382,6 +436,8 @@
         return -EINVAL;
     }
 
+    DrmSessionManager::Instance()->useSession(sessionId);
+
     return mPlugin->queryKeyStatus(sessionId, infoMap);
 }
 
@@ -561,6 +617,8 @@
         return -EINVAL;
     }
 
+    DrmSessionManager::Instance()->useSession(sessionId);
+
     return mPlugin->setCipherAlgorithm(sessionId, algorithm);
 }
 
@@ -576,6 +634,8 @@
         return -EINVAL;
     }
 
+    DrmSessionManager::Instance()->useSession(sessionId);
+
     return mPlugin->setMacAlgorithm(sessionId, algorithm);
 }
 
@@ -594,6 +654,8 @@
         return -EINVAL;
     }
 
+    DrmSessionManager::Instance()->useSession(sessionId);
+
     return mPlugin->encrypt(sessionId, keyId, input, iv, output);
 }
 
@@ -612,6 +674,8 @@
         return -EINVAL;
     }
 
+    DrmSessionManager::Instance()->useSession(sessionId);
+
     return mPlugin->decrypt(sessionId, keyId, input, iv, output);
 }
 
@@ -629,6 +693,8 @@
         return -EINVAL;
     }
 
+    DrmSessionManager::Instance()->useSession(sessionId);
+
     return mPlugin->sign(sessionId, keyId, message, signature);
 }
 
@@ -647,6 +713,8 @@
         return -EINVAL;
     }
 
+    DrmSessionManager::Instance()->useSession(sessionId);
+
     return mPlugin->verify(sessionId, keyId, message, signature, match);
 }
 
@@ -669,6 +737,8 @@
         return -EPERM;
     }
 
+    DrmSessionManager::Instance()->useSession(sessionId);
+
     return mPlugin->signRSA(sessionId, algorithm, message, wrappedKey, signature);
 }
 
diff --git a/media/libmediaplayerservice/Drm.h b/media/libmediaplayerservice/Drm.h
index 0e1eb2c..0cea639 100644
--- a/media/libmediaplayerservice/Drm.h
+++ b/media/libmediaplayerservice/Drm.h
@@ -28,6 +28,7 @@
 
 struct DrmFactory;
 struct DrmPlugin;
+struct DrmSessionClientInterface;
 
 struct Drm : public BnDrm,
              public IBinder::DeathRecipient,
@@ -138,6 +139,8 @@
 
     status_t mInitCheck;
 
+    sp<DrmSessionClientInterface> mDrmSessionClient;
+
     sp<IDrmClient> mListener;
     mutable Mutex mEventLock;
     mutable Mutex mNotifyLock;
diff --git a/media/libmediaplayerservice/DrmSessionManager.cpp b/media/libmediaplayerservice/DrmSessionManager.cpp
index 43346e0..6e17eb1 100644
--- a/media/libmediaplayerservice/DrmSessionManager.cpp
+++ b/media/libmediaplayerservice/DrmSessionManager.cpp
@@ -23,6 +23,8 @@
 #include "DrmSessionClientInterface.h"
 #include "ProcessInfoInterface.h"
 #include <binder/IPCThreadState.h>
+#include <binder/IProcessInfoService.h>
+#include <binder/IServiceManager.h>
 #include <unistd.h>
 #include <utils/String8.h>
 
@@ -39,12 +41,25 @@
 struct ProcessInfo : public ProcessInfoInterface {
     ProcessInfo() {}
 
-    virtual int getPriority(int pid) {
-        // TODO: implement
-        // Get process state to determine priority.
-        // According to the define of PROCESS_STATE_***, higher the value lower
-        // the priority. So we will do a converting from state to priority here.
-        return -1;
+    virtual bool getPriority(int pid, int* priority) {
+        sp<IBinder> binder = defaultServiceManager()->getService(String16("processinfo"));
+        sp<IProcessInfoService> service = interface_cast<IProcessInfoService>(binder);
+
+        size_t length = 1;
+        int32_t states;
+        status_t err = service->getProcessStatesFromPids(length, &pid, &states);
+        if (err != OK) {
+            ALOGE("getProcessStatesFromPids failed");
+            return false;
+        }
+        ALOGV("pid %d states %d", pid, states);
+        if (states < 0) {
+            return false;
+        }
+
+        // Use process state as the priority. Lower the value, higher the priority.
+        *priority = states;
+        return true;
     }
 
 protected:
@@ -66,6 +81,11 @@
     return true;
 }
 
+sp<DrmSessionManager> DrmSessionManager::Instance() {
+    static sp<DrmSessionManager> drmSessionManager = new DrmSessionManager();
+    return drmSessionManager;
+}
+
 DrmSessionManager::DrmSessionManager()
     : mProcessInfo(new ProcessInfo()),
       mTime(0) {}
@@ -155,15 +175,18 @@
 
     sp<DrmSessionClientInterface> drm;
     Vector<uint8_t> sessionId;
+    int lowestPriorityPid;
+    int lowestPriority;
     {
         Mutex::Autolock lock(mLock);
-        int callingPriority = mProcessInfo->getPriority(callingPid);
-        int lowestPriorityPid;
-        int lowestPriority;
+        int callingPriority;
+        if (!mProcessInfo->getPriority(callingPid, &callingPriority)) {
+            return false;
+        }
         if (!getLowestPriority_l(&lowestPriorityPid, &lowestPriority)) {
             return false;
         }
-        if (lowestPriority >= callingPriority) {
+        if (lowestPriority <= callingPriority) {
             return false;
         }
 
@@ -176,6 +199,9 @@
         return false;
     }
 
+    ALOGV("reclaim session(%s) opened by pid %d",
+            GetSessionIdString(sessionId).string(), lowestPriorityPid);
+
     return drm->reclaimSession(sessionId);
 }
 
@@ -185,19 +211,23 @@
 
 bool DrmSessionManager::getLowestPriority_l(int* lowestPriorityPid, int* lowestPriority) {
     int pid = -1;
-    int priority = INT_MAX;
+    int priority = -1;
     for (size_t i = 0; i < mSessionMap.size(); ++i) {
         if (mSessionMap.valueAt(i).size() == 0) {
             // no opened session by this process.
             continue;
         }
         int tempPid = mSessionMap.keyAt(i);
-        int tempPriority = mProcessInfo->getPriority(tempPid);
+        int tempPriority;
+        if (!mProcessInfo->getPriority(tempPid, &tempPriority)) {
+            // shouldn't happen.
+            return false;
+        }
         if (pid == -1) {
             pid = tempPid;
             priority = tempPriority;
         } else {
-            if (tempPriority < priority) {
+            if (tempPriority > priority) {
                 pid = tempPid;
                 priority = tempPriority;
             }
diff --git a/media/libmediaplayerservice/DrmSessionManager.h b/media/libmediaplayerservice/DrmSessionManager.h
index 1d0ed43..ba5c268 100644
--- a/media/libmediaplayerservice/DrmSessionManager.h
+++ b/media/libmediaplayerservice/DrmSessionManager.h
@@ -42,6 +42,8 @@
 typedef KeyedVector<int, SessionInfos > PidSessionInfosMap;
 
 struct DrmSessionManager : public RefBase {
+    static sp<DrmSessionManager> Instance();
+
     DrmSessionManager();
     DrmSessionManager(sp<ProcessInfoInterface> processInfo);
 
diff --git a/media/libmediaplayerservice/ProcessInfoInterface.h b/media/libmediaplayerservice/ProcessInfoInterface.h
index bdcc1da..222f92d 100644
--- a/media/libmediaplayerservice/ProcessInfoInterface.h
+++ b/media/libmediaplayerservice/ProcessInfoInterface.h
@@ -22,7 +22,7 @@
 namespace android {
 
 struct ProcessInfoInterface : public RefBase {
-    virtual int getPriority(int pid) = 0;
+    virtual bool getPriority(int pid, int* priority) = 0;
 
 protected:
     virtual ~ProcessInfoInterface() {}
diff --git a/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp b/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
index a199ee1..27b482b 100644
--- a/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
+++ b/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
@@ -32,7 +32,12 @@
     FakeProcessInfo() {}
     virtual ~FakeProcessInfo() {}
 
-    virtual int getPriority(int pid) { return pid; }
+    virtual bool getPriority(int pid, int* priority) {
+        // For testing, use pid as priority.
+        // Lower the value higher the priority.
+        *priority = pid;
+        return true;
+    }
 
 private:
     DISALLOW_EVIL_CONSTRUCTORS(FakeProcessInfo);
@@ -57,7 +62,7 @@
     DISALLOW_EVIL_CONSTRUCTORS(FakeDrm);
 };
 
-static const int kTestPid1 = 10;
+static const int kTestPid1 = 30;
 static const int kTestPid2 = 20;
 static const uint8_t kTestSessionId1[] = {1, 2, 3};
 static const uint8_t kTestSessionId2[] = {4, 5, 6, 7, 8};
@@ -122,7 +127,9 @@
 
         EXPECT_EQ(kTestPid1, pid);
         FakeProcessInfo processInfo;
-        EXPECT_EQ(processInfo.getPriority(kTestPid1), priority);
+        int priority1;
+        processInfo.getPriority(kTestPid1, &priority1);
+        EXPECT_EQ(priority1, priority);
     }
 
     void testGetLeastUsedSession() {
@@ -210,9 +217,9 @@
     addSession();
 
     // calling pid priority is too low
-    EXPECT_FALSE(mDrmSessionManager->reclaimSession(5));
+    EXPECT_FALSE(mDrmSessionManager->reclaimSession(50));
 
-    EXPECT_TRUE(mDrmSessionManager->reclaimSession(30));
+    EXPECT_TRUE(mDrmSessionManager->reclaimSession(10));
     EXPECT_EQ(1, mTestDrm1->reclaimedSessions().size());
     EXPECT_TRUE(isEqualSessionId(mSessionId1, mTestDrm1->reclaimedSessions()[0]));
 
@@ -220,12 +227,12 @@
 
     // add a session from a higher priority process.
     sp<FakeDrm> drm = new FakeDrm;
-    const uint8_t ids[] = {456, 7890, 123};
+    const uint8_t ids[] = {1, 3, 5};
     Vector<uint8_t> sessionId;
     GetSessionId(ids, ARRAY_SIZE(ids), &sessionId);
-    mDrmSessionManager->addSession(30, drm, sessionId);
+    mDrmSessionManager->addSession(15, drm, sessionId);
 
-    EXPECT_TRUE(mDrmSessionManager->reclaimSession(40));
+    EXPECT_TRUE(mDrmSessionManager->reclaimSession(18));
     EXPECT_EQ(1, mTestDrm2->reclaimedSessions().size());
     // mSessionId2 is reclaimed.
     EXPECT_TRUE(isEqualSessionId(mSessionId2, mTestDrm2->reclaimedSessions()[0]));
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
index 1505f08..10937ec 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
@@ -975,6 +975,7 @@
         mBufferSizes.clear();
         mDecodedSizes.clear();
         mLastInHeader = NULL;
+        mEndOfInput = false;
     } else {
         int avail;
         while ((avail = outputDelayRingBufferSamplesAvailable()) > 0) {
@@ -989,6 +990,7 @@
             mOutputBufferCount++;
         }
         mOutputDelayRingBufferReadPos = mOutputDelayRingBufferWritePos;
+        mEndOfOutput = false;
     }
 }
 
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
index f266fe7..bb05417 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
@@ -91,13 +91,11 @@
     while (it != mBuffers.end()) {
         sp<ABuffer> buffer = *it;
         int32_t discontinuity;
-        if (buffer->meta()->findInt32("discontinuity", &discontinuity)) {
-            break;
-        }
-
-        sp<RefBase> object;
-        if (buffer->meta()->findObject("format", &object)) {
-            return mFormat = static_cast<MetaData*>(object.get());
+        if (!buffer->meta()->findInt32("discontinuity", &discontinuity)) {
+            sp<RefBase> object;
+            if (buffer->meta()->findObject("format", &object)) {
+                return mFormat = static_cast<MetaData*>(object.get());
+            }
         }
 
         ++it;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 3474f24..c1da6bc 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -741,6 +741,7 @@
         dprintf(fd, "thread %p may be deadlocked\n", this);
     }
 
+    dprintf(fd, "  Thread name: %s\n", mThreadName);
     dprintf(fd, "  I/O handle: %d\n", mId);
     dprintf(fd, "  TID: %d\n", getTid());
     dprintf(fd, "  Standby: %s\n", mStandby ? "yes" : "no");
@@ -764,6 +765,9 @@
     } else {
         dprintf(fd, " none\n");
     }
+    dprintf(fd, "  Output device: %#x (%s)\n", mOutDevice, devicesToString(mOutDevice).string());
+    dprintf(fd, "  Input device: %#x (%s)\n", mInDevice, devicesToString(mInDevice).string());
+    dprintf(fd, "  Audio source: %d (%s)\n", mAudioSource, sourceToString(mAudioSource));
 
     if (locked) {
         mLock.unlock();
@@ -1479,6 +1483,9 @@
 void AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& args)
 {
     dprintf(fd, "\nOutput thread %p type %d (%s):\n", this, type(), threadTypeToString(type()));
+
+    dumpBase(fd, args);
+
     dprintf(fd, "  Normal frame count: %zu\n", mNormalFrameCount);
     dprintf(fd, "  Last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime));
     dprintf(fd, "  Total writes: %d\n", mNumWrites);
@@ -1493,8 +1500,6 @@
     audio_output_flags_t flags = output != NULL ? output->flags : AUDIO_OUTPUT_FLAG_NONE;
     String8 flagsAsString = outputFlagsToString(flags);
     dprintf(fd, "  AudioStreamOut: %p flags %#x (%s)\n", output, flags, flagsAsString.string());
-
-    dumpBase(fd, args);
 }
 
 // Thread virtuals
@@ -1545,9 +1550,10 @@
               (
                 (sharedBuffer != 0)
               ) ||
-              // use case 2: callback handler and frame count is default or at least as large as HAL
+              // use case 2: frame count is default or at least as large as HAL
               (
-                (tid != -1) &&
+                // we formerly checked for a callback handler (non-0 tid),
+                // but that is no longer required for TRANSFER_OBTAIN mode
                 ((frameCount == 0) ||
                 (frameCount >= mFrameCount))
               )
@@ -6151,15 +6157,13 @@
 {
     dprintf(fd, "\nInput thread %p:\n", this);
 
-    if (mActiveTracks.size() > 0) {
-        dprintf(fd, "  Buffer size: %zu bytes\n", mBufferSize);
-    } else {
+    dumpBase(fd, args);
+
+    if (mActiveTracks.size() == 0) {
         dprintf(fd, "  No active record clients\n");
     }
     dprintf(fd, "  Fast capture thread: %s\n", hasFastCapture() ? "yes" : "no");
     dprintf(fd, "  Fast track available: %s\n", mFastTrackAvail ? "yes" : "no");
-
-    dumpBase(fd, args);
 }
 
 void AudioFlinger::RecordThread::dumpTracks(int fd, const Vector<String16>& args __unused)
diff --git a/services/camera/libcameraservice/CameraFlashlight.cpp b/services/camera/libcameraservice/CameraFlashlight.cpp
index 8e894cd..7a79750 100644
--- a/services/camera/libcameraservice/CameraFlashlight.cpp
+++ b/services/camera/libcameraservice/CameraFlashlight.cpp
@@ -388,7 +388,8 @@
     if (mAnw == NULL) {
         return NO_MEMORY;
     }
-    res = device->createStream(mAnw, width, height, format, &mStreamId);
+    res = device->createStream(mAnw, width, height, format,
+            HAL_DATASPACE_UNKNOWN, &mStreamId);
     if (res) {
         return res;
     }
diff --git a/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp b/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
index eadaa00..fd4e714 100644
--- a/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
@@ -155,7 +155,7 @@
                 callbackFormat, params.previewFormat);
         res = device->createStream(mCallbackWindow,
                 params.previewWidth, params.previewHeight,
-                callbackFormat, &mCallbackStreamId);
+                callbackFormat, HAL_DATASPACE_JFIF, &mCallbackStreamId);
         if (res != OK) {
             ALOGE("%s: Camera %d: Can't create output stream for callbacks: "
                     "%s (%d)", __FUNCTION__, mId,
diff --git a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
index 2772267..5b387f9 100644
--- a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
@@ -145,7 +145,8 @@
         // Create stream for HAL production
         res = device->createStream(mCaptureWindow,
                 params.pictureWidth, params.pictureHeight,
-                HAL_PIXEL_FORMAT_BLOB, &mCaptureStreamId);
+                HAL_PIXEL_FORMAT_BLOB, HAL_DATASPACE_JFIF,
+                &mCaptureStreamId);
         if (res != OK) {
             ALOGE("%s: Camera %d: Can't create output stream for capture: "
                     "%s (%d)", __FUNCTION__, mId,
diff --git a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
index 470624b..ea5dcdd 100644
--- a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
@@ -181,7 +181,8 @@
     if (mPreviewStreamId == NO_STREAM) {
         res = device->createStream(mPreviewWindow,
                 params.previewWidth, params.previewHeight,
-                CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, &mPreviewStreamId);
+                CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, HAL_DATASPACE_UNKNOWN,
+                &mPreviewStreamId);
         if (res != OK) {
             ALOGE("%s: Camera %d: Unable to create preview stream: %s (%d)",
                     __FUNCTION__, mId, strerror(-res), res);
@@ -420,9 +421,12 @@
 
     if (mRecordingStreamId == NO_STREAM) {
         mRecordingFrameCount = 0;
+        // Selecting BT.709 colorspace by default
+        // TODO: Wire this in from encoder side
         res = device->createStream(mRecordingWindow,
                 params.videoWidth, params.videoHeight,
-                CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, &mRecordingStreamId);
+                CAMERA2_HAL_PIXEL_FORMAT_OPAQUE,
+                HAL_DATASPACE_BT709, &mRecordingStreamId);
         if (res != OK) {
             ALOGE("%s: Camera %d: Can't create output stream for recording: "
                     "%s (%d)", __FUNCTION__, mId,
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
index 8b7e4b4..db7e10d 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
@@ -186,7 +186,7 @@
                 (int)HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
         res = device->createStream(mZslWindow,
                 params.fastInfo.arrayWidth, params.fastInfo.arrayHeight,
-                streamType, &mZslStreamId);
+                streamType, HAL_DATASPACE_UNKNOWN, &mZslStreamId);
         if (res != OK) {
             ALOGE("%s: Camera %d: Can't create output stream for ZSL: "
                     "%s (%d)", __FUNCTION__, mId,
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index acc092c..dde1779 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -314,11 +314,10 @@
     return res;
 }
 
-status_t CameraDeviceClient::createStream(int width, int height, int format,
+status_t CameraDeviceClient::createStream(
                       const sp<IGraphicBufferProducer>& bufferProducer)
 {
     ATRACE_CALL();
-    ALOGV("%s (w = %d, h = %d, f = 0x%x)", __FUNCTION__, width, height, format);
 
     status_t res;
     if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
@@ -370,7 +369,8 @@
     sp<IBinder> binder = IInterface::asBinder(bufferProducer);
     sp<ANativeWindow> anw = new Surface(bufferProducer, useAsync);
 
-    // TODO: remove w,h,f since we are ignoring them
+    int width, height, format;
+    android_dataspace dataSpace;
 
     if ((res = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, &width)) != OK) {
         ALOGE("%s: Camera %d: Failed to query Surface width", __FUNCTION__,
@@ -387,6 +387,12 @@
               mCameraId);
         return res;
     }
+    if ((res = anw->query(anw.get(), NATIVE_WINDOW_DEFAULT_DATASPACE,
+                            reinterpret_cast<int*>(&dataSpace))) != OK) {
+        ALOGE("%s: Camera %d: Failed to query Surface dataSpace", __FUNCTION__,
+              mCameraId);
+        return res;
+    }
 
     // FIXME: remove this override since the default format should be
     //       IMPLEMENTATION_DEFINED. b/9487482
@@ -399,14 +405,15 @@
 
     // Round dimensions to the nearest dimensions available for this format
     if (flexibleConsumer && !CameraDeviceClient::roundBufferDimensionNearest(width, height,
-            format, mDevice->info(), /*out*/&width, /*out*/&height)) {
+            format, dataSpace, mDevice->info(), /*out*/&width, /*out*/&height)) {
         ALOGE("%s: No stream configurations with the format %#x defined, failed to create stream.",
                 __FUNCTION__, format);
         return BAD_VALUE;
     }
 
     int streamId = -1;
-    res = mDevice->createStream(anw, width, height, format, &streamId);
+    res = mDevice->createStream(anw, width, height, format, dataSpace,
+            &streamId);
 
     if (res == OK) {
         mStreamMap.add(binder, streamId);
@@ -441,10 +448,12 @@
 
 
 bool CameraDeviceClient::roundBufferDimensionNearest(int32_t width, int32_t height,
-        int32_t format, const CameraMetadata& info,
+        int32_t format, android_dataspace dataSpace, const CameraMetadata& info,
         /*out*/int32_t* outWidth, /*out*/int32_t* outHeight) {
 
     camera_metadata_ro_entry streamConfigs =
+            (dataSpace == HAL_DATASPACE_DEPTH) ?
+            info.find(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS) :
             info.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
 
     int32_t bestWidth = -1;
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index e687175..c89c269 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -84,9 +84,6 @@
     virtual status_t      deleteStream(int streamId);
 
     virtual status_t      createStream(
-            int width,
-            int height,
-            int format,
             const sp<IGraphicBufferProducer>& bufferProducer);
 
     // Create a request object from a template.
@@ -161,7 +158,8 @@
     // a width <= ROUNDING_WIDTH_CAP
     static const int32_t ROUNDING_WIDTH_CAP = 1080;
     static bool roundBufferDimensionNearest(int32_t width, int32_t height, int32_t format,
-            const CameraMetadata& info, /*out*/int32_t* outWidth, /*out*/int32_t* outHeight);
+            android_dataspace dataSpace, const CameraMetadata& info,
+            /*out*/int32_t* outWidth, /*out*/int32_t* outHeight);
 
     // IGraphicsBufferProducer binder -> Stream ID
     KeyedVector<sp<IBinder>, int> mStreamMap;
diff --git a/services/camera/libcameraservice/api_pro/ProCamera2Client.cpp b/services/camera/libcameraservice/api_pro/ProCamera2Client.cpp
index 30a89c2..ba93554 100644
--- a/services/camera/libcameraservice/api_pro/ProCamera2Client.cpp
+++ b/services/camera/libcameraservice/api_pro/ProCamera2Client.cpp
@@ -281,7 +281,7 @@
     }
 
     return mDevice->createStream(window, width, height, format,
-                                 streamId);
+                                 HAL_DATASPACE_UNKNOWN, streamId);
 }
 
 // Create a request object from a template.
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index 06615f6..8764504 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -100,17 +100,14 @@
             nsecs_t timeout) = 0;
 
     /**
-     * Create an output stream of the requested size and format.
+     * Create an output stream of the requested size, format, and dataspace
      *
-     * If format is CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, then the HAL device selects
-     * an appropriate format; it can be queried with getStreamInfo.
-     *
-     * If format is HAL_PIXEL_FORMAT_COMPRESSED, the size parameter must be
-     * equal to the size in bytes of the buffers to allocate for the stream. For
-     * other formats, the size parameter is ignored.
+     * For HAL_PIXEL_FORMAT_BLOB formats, the width and height should be the
+     * logical dimensions of the buffer, not the number of bytes.
      */
     virtual status_t createStream(sp<ANativeWindow> consumer,
-            uint32_t width, uint32_t height, int format, int *id) = 0;
+            uint32_t width, uint32_t height, int format,
+            android_dataspace dataSpace, int *id) = 0;
 
     /**
      * Create an input reprocess stream that uses buffers from an existing
diff --git a/services/camera/libcameraservice/device2/Camera2Device.cpp b/services/camera/libcameraservice/device2/Camera2Device.cpp
index 43c8307..ee862a2 100644
--- a/services/camera/libcameraservice/device2/Camera2Device.cpp
+++ b/services/camera/libcameraservice/device2/Camera2Device.cpp
@@ -241,7 +241,8 @@
 }
 
 status_t Camera2Device::createStream(sp<ANativeWindow> consumer,
-        uint32_t width, uint32_t height, int format, int *id) {
+        uint32_t width, uint32_t height, int format,
+        android_dataspace /*dataSpace*/, int *id) {
     ATRACE_CALL();
     status_t res;
     ALOGV("%s: E", __FUNCTION__);
diff --git a/services/camera/libcameraservice/device2/Camera2Device.h b/services/camera/libcameraservice/device2/Camera2Device.h
index 1cc5482..e4c2856 100644
--- a/services/camera/libcameraservice/device2/Camera2Device.h
+++ b/services/camera/libcameraservice/device2/Camera2Device.h
@@ -57,7 +57,8 @@
     virtual status_t clearStreamingRequest(int64_t *lastFrameNumber = NULL);
     virtual status_t waitUntilRequestReceived(int32_t requestId, nsecs_t timeout);
     virtual status_t createStream(sp<ANativeWindow> consumer,
-            uint32_t width, uint32_t height, int format, int *id);
+            uint32_t width, uint32_t height, int format,
+            android_dataspace dataSpace, int *id);
     virtual status_t createReprocessStreamFromStream(int outputId, int *id);
     virtual status_t getStreamInfo(int id,
             uint32_t *width, uint32_t *height, uint32_t *format);
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index bca9bfd..529d249 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -801,12 +801,13 @@
 }
 
 status_t Camera3Device::createStream(sp<ANativeWindow> consumer,
-        uint32_t width, uint32_t height, int format, int *id) {
+        uint32_t width, uint32_t height, int format, android_dataspace dataSpace,
+        int *id) {
     ATRACE_CALL();
     Mutex::Autolock il(mInterfaceLock);
     Mutex::Autolock l(mLock);
-    ALOGV("Camera %d: Creating new stream %d: %d x %d, format %d",
-            mId, mNextStreamId, width, height, format);
+    ALOGV("Camera %d: Creating new stream %d: %d x %d, format %d, dataspace %d",
+            mId, mNextStreamId, width, height, format, dataSpace);
 
     status_t res;
     bool wasActive = false;
@@ -846,10 +847,10 @@
         }
 
         newStream = new Camera3OutputStream(mNextStreamId, consumer,
-                width, height, jpegBufferSize, format);
+                width, height, jpegBufferSize, format, dataSpace);
     } else {
         newStream = new Camera3OutputStream(mNextStreamId, consumer,
-                width, height, format);
+                width, height, format, dataSpace);
     }
     newStream->setStatusTracker(mStatusTracker);
 
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index de10cfe..e2ad1fa 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -95,7 +95,8 @@
     // If adding streams while actively capturing, will pause device before adding
     // stream, reconfiguring device, and unpausing.
     virtual status_t createStream(sp<ANativeWindow> consumer,
-            uint32_t width, uint32_t height, int format, int *id);
+            uint32_t width, uint32_t height, int format,
+            android_dataspace dataSpace, int *id);
     virtual status_t createInputStream(
             uint32_t width, uint32_t height, int format,
             int *id);
diff --git a/services/camera/libcameraservice/device3/Camera3DummyStream.cpp b/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
index 6656b09..6201484 100644
--- a/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
@@ -28,7 +28,7 @@
 
 Camera3DummyStream::Camera3DummyStream(int id) :
         Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, DUMMY_WIDTH, DUMMY_HEIGHT,
-                /*maxSize*/0, DUMMY_FORMAT) {
+                /*maxSize*/0, DUMMY_FORMAT, DUMMY_DATASPACE) {
 
 }
 
diff --git a/services/camera/libcameraservice/device3/Camera3DummyStream.h b/services/camera/libcameraservice/device3/Camera3DummyStream.h
index 3e42623..7f52d84 100644
--- a/services/camera/libcameraservice/device3/Camera3DummyStream.h
+++ b/services/camera/libcameraservice/device3/Camera3DummyStream.h
@@ -75,6 +75,7 @@
     static const int DUMMY_WIDTH = 320;
     static const int DUMMY_HEIGHT = 240;
     static const int DUMMY_FORMAT = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
+    static const android_dataspace DUMMY_DATASPACE = HAL_DATASPACE_UNKNOWN;
     static const uint32_t DUMMY_USAGE = GRALLOC_USAGE_HW_COMPOSER;
 
     /**
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
index cc66459..ff0acbb 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
@@ -30,9 +30,10 @@
 namespace camera3 {
 
 Camera3IOStreamBase::Camera3IOStreamBase(int id, camera3_stream_type_t type,
-        uint32_t width, uint32_t height, size_t maxSize, int format) :
+        uint32_t width, uint32_t height, size_t maxSize, int format,
+        android_dataspace dataSpace) :
         Camera3Stream(id, type,
-                width, height, maxSize, format),
+                width, height, maxSize, format, dataSpace),
         mTotalBufferCount(0),
         mHandoutTotalBufferCount(0),
         mHandoutOutputBufferCount(0),
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
index a35c290..83d4350 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
@@ -33,7 +33,8 @@
         public Camera3Stream {
   protected:
     Camera3IOStreamBase(int id, camera3_stream_type_t type,
-            uint32_t width, uint32_t height, size_t maxSize, int format);
+            uint32_t width, uint32_t height, size_t maxSize, int format,
+            android_dataspace dataSpace);
 
   public:
 
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.cpp b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
index 319be1d..85ed88d 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
@@ -29,7 +29,7 @@
 Camera3InputStream::Camera3InputStream(int id,
         uint32_t width, uint32_t height, int format) :
         Camera3IOStreamBase(id, CAMERA3_STREAM_INPUT, width, height,
-                            /*maxSize*/0, format) {
+                            /*maxSize*/0, format, HAL_DATASPACE_UNKNOWN) {
 
     if (format == HAL_PIXEL_FORMAT_BLOB) {
         ALOGE("%s: Bad format, BLOB not supported", __FUNCTION__);
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index 77ad503..103d90b 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -33,9 +33,10 @@
 
 Camera3OutputStream::Camera3OutputStream(int id,
         sp<ANativeWindow> consumer,
-        uint32_t width, uint32_t height, int format) :
+        uint32_t width, uint32_t height, int format,
+        android_dataspace dataSpace) :
         Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, width, height,
-                            /*maxSize*/0, format),
+                            /*maxSize*/0, format, dataSpace),
         mConsumer(consumer),
         mTransform(0),
         mTraceFirstBuffer(true) {
@@ -48,9 +49,10 @@
 
 Camera3OutputStream::Camera3OutputStream(int id,
         sp<ANativeWindow> consumer,
-        uint32_t width, uint32_t height, size_t maxSize, int format) :
+        uint32_t width, uint32_t height, size_t maxSize, int format,
+        android_dataspace dataSpace) :
         Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, width, height, maxSize,
-                            format),
+                            format, dataSpace),
         mConsumer(consumer),
         mTransform(0),
         mTraceFirstBuffer(true) {
@@ -69,10 +71,11 @@
 
 Camera3OutputStream::Camera3OutputStream(int id, camera3_stream_type_t type,
                                          uint32_t width, uint32_t height,
-                                         int format) :
+                                         int format,
+                                         android_dataspace dataSpace) :
         Camera3IOStreamBase(id, type, width, height,
                             /*maxSize*/0,
-                            format),
+                            format, dataSpace),
         mTransform(0) {
 
     // Subclasses expected to initialize mConsumer themselves
@@ -323,6 +326,14 @@
         return res;
     }
 
+    res = native_window_set_buffers_data_space(mConsumer.get(),
+            camera3_stream::data_space);
+    if (res != OK) {
+        ALOGE("%s: Unable to configure stream dataspace %#x for stream %d",
+                __FUNCTION__, camera3_stream::data_space, mId);
+        return res;
+    }
+
     int maxConsumerBuffers;
     res = mConsumer->query(mConsumer.get(),
             NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &maxConsumerBuffers);
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h
index be278c5..f016d60 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h
@@ -39,14 +39,16 @@
      * Set up a stream for formats that have 2 dimensions, such as RAW and YUV.
      */
     Camera3OutputStream(int id, sp<ANativeWindow> consumer,
-            uint32_t width, uint32_t height, int format);
+            uint32_t width, uint32_t height, int format,
+            android_dataspace dataSpace);
 
     /**
      * Set up a stream for formats that have a variable buffer size for the same
      * dimensions, such as compressed JPEG.
      */
     Camera3OutputStream(int id, sp<ANativeWindow> consumer,
-            uint32_t width, uint32_t height, size_t maxSize, int format);
+            uint32_t width, uint32_t height, size_t maxSize, int format,
+            android_dataspace dataSpace);
 
     virtual ~Camera3OutputStream();
 
@@ -64,7 +66,8 @@
 
   protected:
     Camera3OutputStream(int id, camera3_stream_type_t type,
-            uint32_t width, uint32_t height, int format);
+            uint32_t width, uint32_t height, int format,
+            android_dataspace dataSpace);
 
     /**
      * Note that we release the lock briefly in this function
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index 3c0e908..f829741 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -46,7 +46,8 @@
 
 Camera3Stream::Camera3Stream(int id,
         camera3_stream_type type,
-        uint32_t width, uint32_t height, size_t maxSize, int format) :
+        uint32_t width, uint32_t height, size_t maxSize, int format,
+        android_dataspace dataSpace) :
     camera3_stream(),
     mId(id),
     mName(String8::format("Camera3Stream[%d]", id)),
@@ -58,6 +59,7 @@
     camera3_stream::width = width;
     camera3_stream::height = height;
     camera3_stream::format = format;
+    camera3_stream::data_space = dataSpace;
     camera3_stream::usage = 0;
     camera3_stream::max_buffers = 0;
     camera3_stream::priv = NULL;
@@ -84,6 +86,10 @@
     return camera3_stream::format;
 }
 
+android_dataspace Camera3Stream::getDataSpace() const {
+    return camera3_stream::data_space;
+}
+
 camera3_stream* Camera3Stream::startConfiguration() {
     ATRACE_CALL();
     Mutex::Autolock l(mLock);
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.h b/services/camera/libcameraservice/device3/Camera3Stream.h
index d0e1337..72f3ee9 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.h
+++ b/services/camera/libcameraservice/device3/Camera3Stream.h
@@ -119,9 +119,10 @@
     /**
      * Get the stream's dimensions and format
      */
-    uint32_t         getWidth() const;
-    uint32_t         getHeight() const;
-    int              getFormat() const;
+    uint32_t          getWidth() const;
+    uint32_t          getHeight() const;
+    int               getFormat() const;
+    android_dataspace getDataSpace() const;
 
     /**
      * Start the stream configuration process. Returns a handle to the stream's
@@ -264,7 +265,8 @@
     mutable Mutex mLock;
 
     Camera3Stream(int id, camera3_stream_type type,
-            uint32_t width, uint32_t height, size_t maxSize, int format);
+            uint32_t width, uint32_t height, size_t maxSize, int format,
+            android_dataspace dataSpace);
 
     /**
      * Interface to be implemented by derived classes
diff --git a/services/camera/libcameraservice/device3/Camera3ZslStream.cpp b/services/camera/libcameraservice/device3/Camera3ZslStream.cpp
index 81330ea..5bf7a4c 100644
--- a/services/camera/libcameraservice/device3/Camera3ZslStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3ZslStream.cpp
@@ -114,7 +114,8 @@
         int bufferCount) :
         Camera3OutputStream(id, CAMERA3_STREAM_BIDIRECTIONAL,
                             width, height,
-                            HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED),
+                            HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
+                            HAL_DATASPACE_UNKNOWN),
         mDepth(bufferCount) {
 
     sp<IGraphicBufferProducer> producer;