Merge "Use audio_session_t consistently" into nyc-dev
diff --git a/include/media/AudioPolicy.h b/include/media/AudioPolicy.h
index c769a62..8528c7a 100644
--- a/include/media/AudioPolicy.h
+++ b/include/media/AudioPolicy.h
@@ -51,6 +51,7 @@
 
 #define MIX_ROUTE_FLAG_RENDER 0x1
 #define MIX_ROUTE_FLAG_LOOP_BACK (0x1 << 1)
+#define MIX_ROUTE_FLAG_ALL (MIX_ROUTE_FLAG_RENDER | MIX_ROUTE_FLAG_LOOP_BACK)
 
 #define MAX_MIXES_PER_POLICY 10
 #define MAX_CRITERIA_PER_MIX 20
@@ -81,7 +82,7 @@
     AudioMix(Vector<AudioMixMatchCriterion> criteria, uint32_t mixType, audio_config_t format,
              uint32_t routeFlags, String8 registrationId, uint32_t flags) :
         mCriteria(criteria), mMixType(mixType), mFormat(format),
-        mRouteFlags(routeFlags), mRegistrationId(registrationId), mCbFlags(flags){}
+        mRouteFlags(routeFlags), mDeviceAddress(registrationId), mCbFlags(flags){}
 
     status_t readFromParcel(Parcel *parcel);
     status_t writeToParcel(Parcel *parcel) const;
@@ -90,7 +91,8 @@
     uint32_t        mMixType;
     audio_config_t  mFormat;
     uint32_t        mRouteFlags;
-    String8         mRegistrationId;
+    audio_devices_t mDeviceType;
+    String8         mDeviceAddress;
     uint32_t        mCbFlags; // flags indicating which callbacks to use, see kCbFlag*
 };
 
diff --git a/media/img_utils/src/NOTICE b/media/img_utils/src/NOTICE
new file mode 100644
index 0000000..90cea57
--- /dev/null
+++ b/media/img_utils/src/NOTICE
@@ -0,0 +1,2 @@
+This product includes DNG technology under license by Adobe Systems
+Incorporated.
diff --git a/media/libmedia/AudioPolicy.cpp b/media/libmedia/AudioPolicy.cpp
index ea22b6c..d1f7525 100644
--- a/media/libmedia/AudioPolicy.cpp
+++ b/media/libmedia/AudioPolicy.cpp
@@ -67,7 +67,8 @@
     mFormat.channel_mask = (audio_channel_mask_t)parcel->readInt32();
     mFormat.format = (audio_format_t)parcel->readInt32();
     mRouteFlags = parcel->readInt32();
-    mRegistrationId = parcel->readString8();
+    mDeviceType = (audio_devices_t) parcel->readInt32();
+    mDeviceAddress = parcel->readString8();
     mCbFlags = (uint32_t)parcel->readInt32();
     size_t size = (size_t)parcel->readInt32();
     if (size > MAX_CRITERIA_PER_MIX) {
@@ -89,7 +90,8 @@
     parcel->writeInt32(mFormat.channel_mask);
     parcel->writeInt32(mFormat.format);
     parcel->writeInt32(mRouteFlags);
-    parcel->writeString8(mRegistrationId);
+    parcel->writeInt32(mDeviceType);
+    parcel->writeString8(mDeviceAddress);
     parcel->writeInt32(mCbFlags);
     size_t size = mCriteria.size();
     if (size > MAX_CRITERIA_PER_MIX) {
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index e0fe7e3..520f599 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -2555,6 +2555,7 @@
             : OMX_AUDIO_AACStreamFormatMP4FF;
 
     OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE presentation;
+    InitOMXParams(&presentation);
     presentation.nMaxOutputChannels = maxOutputChannelCount;
     presentation.nDrcCut = drc.drcCut;
     presentation.nDrcBoost = drc.drcBoost;
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 59f839c..cb974ae 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -758,7 +758,7 @@
     mStartTimeUs = 0;
     mNumInputBuffers = 0;
     mEncoderFormat = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
-    mEncoderDataSpace = HAL_DATASPACE_BT709;
+    mEncoderDataSpace = HAL_DATASPACE_V0_BT709;
 
     if (meta) {
         int64_t startTimeUs;
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index b5f7b12..0a052d2 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -42,7 +42,7 @@
 
 const int32_t kDefaultSwVideoEncoderFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;
 const int32_t kDefaultHwVideoEncoderFormat = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
-const int32_t kDefaultVideoEncoderDataSpace = HAL_DATASPACE_BT709;
+const int32_t kDefaultVideoEncoderDataSpace = HAL_DATASPACE_V0_BT709;
 
 const int kStopTimeoutUs = 300000; // allow 1 sec for shutting down encoder
 
diff --git a/media/libstagefright/codecs/amrwbenc/inc/basic_op.h b/media/libstagefright/codecs/amrwbenc/inc/basic_op.h
index db3e058..8165f69 100644
--- a/media/libstagefright/codecs/amrwbenc/inc/basic_op.h
+++ b/media/libstagefright/codecs/amrwbenc/inc/basic_op.h
@@ -51,11 +51,11 @@
 #define vo_shr_r(var1, var2)        ((var1+((Word16)(1L<<(var2-1))))>>var2)
 #define vo_sub(a,b)         (a - b)
 #define vo_L_deposit_h(a)       ((Word32)((a) << 16))
-#define vo_round(a)         ((a + 0x00008000) >> 16)
+#define vo_round(a)         ((((a) >> 15) + 1) >> 1)
 #define vo_extract_l(a)         ((Word16)(a))
 #define vo_L_add(a,b)           (a + b)
 #define vo_L_sub(a,b)           (a - b)
-#define vo_mult_r(a,b)          ((( a * b ) + 0x4000 ) >> 15 )
+#define vo_mult_r(a,b)          (((( a * b ) >> 14) + 1 ) >> 1 )
 #define vo_negate(a)                (-a)
 #define vo_L_shr_r(L_var1, var2)        ((L_var1+((Word32)(1L<<(var2-1))))>>var2)
 
diff --git a/media/libstagefright/codecs/amrwbenc/src/c4t64fx.c b/media/libstagefright/codecs/amrwbenc/src/c4t64fx.c
index 8bf15ea..4d877f1 100644
--- a/media/libstagefright/codecs/amrwbenc/src/c4t64fx.c
+++ b/media/libstagefright/codecs/amrwbenc/src/c4t64fx.c
@@ -267,13 +267,13 @@
 
     for (i = 0; i < L_SUBFR/4; i++)
     {
-        s = (k_cn* (*p0++))+(k_dn * (*p1++));
+        s = L_add((k_cn* (*p0++)), (k_dn * (*p1++)));
         *p2++ = s >> 7;
-        s = (k_cn* (*p0++))+(k_dn * (*p1++));
+        s = L_add((k_cn* (*p0++)), (k_dn * (*p1++)));
         *p2++ = s >> 7;
-        s = (k_cn* (*p0++))+(k_dn * (*p1++));
+        s = L_add((k_cn* (*p0++)), (k_dn * (*p1++)));
         *p2++ = s >> 7;
-        s = (k_cn* (*p0++))+(k_dn * (*p1++));
+        s = L_add((k_cn* (*p0++)), (k_dn * (*p1++)));
         *p2++ = s >> 7;
     }
 
@@ -342,7 +342,7 @@
     {
         *h++ = 0;
         *h_inv++ = 0;
-        L_tmp += (H[i] * H[i]) << 1;
+        L_tmp = L_add(L_tmp, (H[i] * H[i]) << 1);
     }
     /* scale h[] down (/2) when energy of h[] is high with many pulses used */
     val = extract_h(L_tmp);
@@ -386,16 +386,16 @@
     cor = 0x00008000L;                             /* for rounding */
     for (i = 0; i < NB_POS; i++)
     {
-        cor += vo_L_mult((*ptr_h1), (*ptr_h1));
+        cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h1)));
         ptr_h1++;
         *p3-- = extract_h(cor);
-        cor += vo_L_mult((*ptr_h1), (*ptr_h1));
+        cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h1)));
         ptr_h1++;
         *p2-- = extract_h(cor);
-        cor += vo_L_mult((*ptr_h1), (*ptr_h1));
+        cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h1)));
         ptr_h1++;
         *p1-- = extract_h(cor);
-        cor += vo_L_mult((*ptr_h1), (*ptr_h1));
+        cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h1)));
         ptr_h1++;
         *p0-- = extract_h(cor);
     }
@@ -425,19 +425,19 @@
 
         for (i = k + 1; i < NB_POS; i++)
         {
-            cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+            cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
             ptr_h1++;
             ptr_h2++;
             *p3 = extract_h(cor);
-            cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+            cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
             ptr_h1++;
             ptr_h2++;
             *p2 = extract_h(cor);
-            cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+            cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
             ptr_h1++;
             ptr_h2++;
             *p1 = extract_h(cor);
-            cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+            cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
             ptr_h1++;
             ptr_h2++;
             *p0 = extract_h(cor);
@@ -447,15 +447,15 @@
             p1 -= (NB_POS + 1);
             p0 -= (NB_POS + 1);
         }
-        cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+        cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
         ptr_h1++;
         ptr_h2++;
         *p3 = extract_h(cor);
-        cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+        cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
         ptr_h1++;
         ptr_h2++;
         *p2 = extract_h(cor);
-        cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+        cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
         ptr_h1++;
         ptr_h2++;
         *p1 = extract_h(cor);
@@ -482,19 +482,19 @@
 
         for (i = k + 1; i < NB_POS; i++)
         {
-            cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+            cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
             ptr_h1++;
             ptr_h2++;
             *p3 = extract_h(cor);
-            cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+            cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
             ptr_h1++;
             ptr_h2++;
             *p2 = extract_h(cor);
-            cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+            cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
             ptr_h1++;
             ptr_h2++;
             *p1 = extract_h(cor);
-            cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+            cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
             ptr_h1++;
             ptr_h2++;
             *p0 = extract_h(cor);
@@ -504,7 +504,7 @@
             p1 -= (NB_POS + 1);
             p0 -= (NB_POS + 1);
         }
-        cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+        cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
         ptr_h1++;
         ptr_h2++;
         *p3 = extract_h(cor);
@@ -698,7 +698,7 @@
         }
         /* memorise the best codevector */
         ps = vo_mult(ps, ps);
-        s = vo_L_msu(vo_L_mult(alpk, ps), psk, alp);
+        s = L_sub(vo_L_mult(alpk, ps), vo_L_mult(psk, alp));
         if (s > 0)
         {
             psk = ps;
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
index 6968a74..f73548d 100755
--- a/services/audiopolicy/common/include/policy.h
+++ b/services/audiopolicy/common/include/policy.h
@@ -42,9 +42,9 @@
  * A device mask for all audio input and output devices where matching inputs/outputs on device
  * type alone is not enough: the address must match too
  */
-#define APM_AUDIO_DEVICE_OUT_MATCH_ADDRESS_ALL (AUDIO_DEVICE_OUT_REMOTE_SUBMIX)
+#define APM_AUDIO_DEVICE_OUT_MATCH_ADDRESS_ALL (AUDIO_DEVICE_OUT_REMOTE_SUBMIX|AUDIO_DEVICE_OUT_BUS)
 
-#define APM_AUDIO_DEVICE_IN_MATCH_ADDRESS_ALL (AUDIO_DEVICE_IN_REMOTE_SUBMIX)
+#define APM_AUDIO_DEVICE_IN_MATCH_ADDRESS_ALL (AUDIO_DEVICE_IN_REMOTE_SUBMIX|AUDIO_DEVICE_IN_BUS)
 
 /**
  * Check if the state given correspond to an in call state.
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
index c952831..8f5ebef 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
@@ -54,7 +54,7 @@
 public:
     status_t getAudioPolicyMix(String8 address, sp<AudioPolicyMix> &policyMix) const;
 
-    status_t registerMix(String8 address, AudioMix mix);
+    status_t registerMix(String8 address, AudioMix mix, sp<SwAudioOutputDescriptor> desc);
 
     status_t unregisterMix(String8 address);
 
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 0fe1a84..c5fee50 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -315,14 +315,14 @@
     if ((oldGlobalRefCount == 0) && (mGlobalRefCount > 0)) {
         if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
         {
-            mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mRegistrationId,
+            mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mDeviceAddress,
                     MIX_STATE_MIXING);
         }
 
     } else if ((oldGlobalRefCount > 0) && (mGlobalRefCount == 0)) {
         if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
         {
-            mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mRegistrationId,
+            mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mDeviceAddress,
                     MIX_STATE_IDLE);
         }
     }
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index 3735c05..4af3d54 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -51,7 +51,8 @@
     return &mMix;
 }
 
-status_t AudioPolicyMixCollection::registerMix(String8 address, AudioMix mix)
+status_t AudioPolicyMixCollection::registerMix(String8 address, AudioMix mix,
+                                               sp<SwAudioOutputDescriptor> desc)
 {
     ssize_t index = indexOfKey(address);
     if (index >= 0) {
@@ -61,6 +62,11 @@
     sp<AudioPolicyMix> policyMix = new AudioPolicyMix();
     policyMix->setMix(mix);
     add(address, policyMix);
+
+    if (desc != 0) {
+        desc->mPolicyMix = policyMix->getMix();
+        policyMix->setOutput(desc);
+    }
     return NO_ERROR;
 }
 
@@ -128,7 +134,7 @@
                 // if there is an address match, prioritize that match
                 if (strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 &&
                         strncmp(attributes.tags + strlen("addr="),
-                                mix->mRegistrationId.string(),
+                                mix->mDeviceAddress.string(),
                                 AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) {
                     hasAddrMatch = true;
                     break;
@@ -207,7 +213,7 @@
             if (attributes.usage == AUDIO_USAGE_VIRTUAL_SOURCE &&
                     strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 &&
                     strncmp(attributes.tags + strlen("addr="),
-                            mix->mRegistrationId.string(),
+                            mix->mDeviceAddress.string(),
                             AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) {
                 desc = policyMix->getOutput();
             }
@@ -260,7 +266,7 @@
     for (size_t i = 0; i < size(); i++) {
             sp<AudioPolicyMix> policyMix = valueAt(i);
             AudioMix *mix = policyMix->getMix();
-            ALOGV("\tmix %zu address=%s", i, mix->mRegistrationId.string());
+            ALOGV("\tmix %zu address=%s", i, mix->mDeviceAddress.string());
     }
 #endif
 
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp
index ce9c170..da983c5 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp
@@ -79,7 +79,7 @@
         // if input maps to a dynamic policy with an activity listener, notify of state change
         if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
         {
-            mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mRegistrationId,
+            mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mDeviceAddress,
                     (event == RECORD_CONFIG_EVENT_START) ? MIX_STATE_MIXING : MIX_STATE_IDLE);
         }
 
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index c3b1529..1d7849c 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1096,7 +1096,7 @@
             outputDesc->mPolicyMix->mMixType == MIX_TYPE_RECORDERS) {
             setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
                     AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
-                    outputDesc->mPolicyMix->mRegistrationId,
+                    outputDesc->mPolicyMix->mDeviceAddress,
                     "remote-submix");
     }
 
@@ -1213,7 +1213,7 @@
                 outputDesc->mPolicyMix->mMixType == MIX_TYPE_RECORDERS) {
             setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
                     AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
-                    outputDesc->mPolicyMix->mRegistrationId,
+                    outputDesc->mPolicyMix->mDeviceAddress,
                     "remote-submix");
         }
     }
@@ -1388,7 +1388,7 @@
             return BAD_VALUE;
         }
         if (policyMix != NULL) {
-            address = policyMix->mRegistrationId;
+            address = policyMix->mDeviceAddress;
             if (policyMix->mMixType == MIX_TYPE_RECORDERS) {
                 // there is an external policy, but this input is attached to a mix of recorders,
                 // meaning it receives audio injected into the framework, so the recorder doesn't
@@ -1622,7 +1622,7 @@
         // if input maps to a dynamic policy with an activity listener, notify of state change
         if ((inputDesc->mPolicyMix != NULL)
                 && ((inputDesc->mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) {
-            mpClientInterface->onDynamicPolicyMixStateUpdate(inputDesc->mPolicyMix->mRegistrationId,
+            mpClientInterface->onDynamicPolicyMixStateUpdate(inputDesc->mPolicyMix->mDeviceAddress,
                     MIX_STATE_MIXING);
         }
 
@@ -1639,7 +1639,7 @@
             if (inputDesc->mPolicyMix == NULL) {
                 address = String8("0");
             } else if (inputDesc->mPolicyMix->mMixType == MIX_TYPE_PLAYERS) {
-                address = inputDesc->mPolicyMix->mRegistrationId;
+                address = inputDesc->mPolicyMix->mDeviceAddress;
             }
             if (address != "") {
                 setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
@@ -1686,7 +1686,7 @@
         // if input maps to a dynamic policy with an activity listener, notify of state change
         if ((inputDesc->mPolicyMix != NULL)
                 && ((inputDesc->mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) {
-            mpClientInterface->onDynamicPolicyMixStateUpdate(inputDesc->mPolicyMix->mRegistrationId,
+            mpClientInterface->onDynamicPolicyMixStateUpdate(inputDesc->mPolicyMix->mDeviceAddress,
                     MIX_STATE_IDLE);
         }
 
@@ -1697,7 +1697,7 @@
             if (inputDesc->mPolicyMix == NULL) {
                 address = String8("0");
             } else if (inputDesc->mPolicyMix->mMixType == MIX_TYPE_PLAYERS) {
-                address = inputDesc->mPolicyMix->mRegistrationId;
+                address = inputDesc->mPolicyMix->mDeviceAddress;
             }
             if (address != "") {
                 setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
@@ -2010,94 +2010,152 @@
 
 status_t AudioPolicyManager::registerPolicyMixes(Vector<AudioMix> mixes)
 {
-    sp<HwModule> module;
-    for (size_t i = 0; i < mHwModules.size(); i++) {
-        if (strcmp(AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX, mHwModules[i]->mName) == 0 &&
-                mHwModules[i]->mHandle != 0) {
-            module = mHwModules[i];
+    ALOGV("registerPolicyMixes() %zu mix(es)", mixes.size());
+    status_t res = NO_ERROR;
+
+    sp<HwModule> rSubmixModule;
+    // examine each mix's route type
+    for (size_t i = 0; i < mixes.size(); i++) {
+        // we only support MIX_ROUTE_FLAG_LOOP_BACK or MIX_ROUTE_FLAG_RENDER, not the combination
+        if ((mixes[i].mRouteFlags & MIX_ROUTE_FLAG_ALL) == MIX_ROUTE_FLAG_ALL) {
+            res = INVALID_OPERATION;
             break;
         }
-    }
+        if ((mixes[i].mRouteFlags & MIX_ROUTE_FLAG_LOOP_BACK) == MIX_ROUTE_FLAG_LOOP_BACK) {
+            // Loop back through "remote submix"
+            if (rSubmixModule == 0) {
+                for (size_t j = 0; i < mHwModules.size(); j++) {
+                    if (strcmp(AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX, mHwModules[j]->mName) == 0
+                            && mHwModules[j]->mHandle != 0) {
+                        rSubmixModule = mHwModules[j];
+                        break;
+                    }
+                }
+            }
 
-    if (module == 0) {
-        return INVALID_OPERATION;
-    }
+            ALOGV("registerPolicyMixes() mix %zu of %zu is LOOP_BACK", i, mixes.size());
 
-    ALOGV("registerPolicyMixes() num mixes %zu", mixes.size());
+            if (rSubmixModule == 0) {
+                ALOGE(" Unable to find audio module for submix, aborting mix %zu registration", i);
+                res = INVALID_OPERATION;
+                break;
+            }
 
-    for (size_t i = 0; i < mixes.size(); i++) {
-        String8 address = mixes[i].mRegistrationId;
+            String8 address = mixes[i].mDeviceAddress;
 
-        if (mPolicyMixes.registerMix(address, mixes[i]) != NO_ERROR) {
-            continue;
-        }
-        audio_config_t outputConfig = mixes[i].mFormat;
-        audio_config_t inputConfig = mixes[i].mFormat;
-        // NOTE: audio flinger mixer does not support mono output: configure remote submix HAL in
-        // stereo and let audio flinger do the channel conversion if needed.
-        outputConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
-        inputConfig.channel_mask = AUDIO_CHANNEL_IN_STEREO;
-        module->addOutputProfile(address, &outputConfig,
-                                 AUDIO_DEVICE_OUT_REMOTE_SUBMIX, address);
-        module->addInputProfile(address, &inputConfig,
-                                 AUDIO_DEVICE_IN_REMOTE_SUBMIX, address);
+            if (mPolicyMixes.registerMix(address, mixes[i], 0 /*output desc*/) != NO_ERROR) {
+                ALOGE(" Error regisering mix %zu for address %s", i, address.string());
+                res = INVALID_OPERATION;
+                break;
+            }
+            audio_config_t outputConfig = mixes[i].mFormat;
+            audio_config_t inputConfig = mixes[i].mFormat;
+            // NOTE: audio flinger mixer does not support mono output: configure remote submix HAL in
+            // stereo and let audio flinger do the channel conversion if needed.
+            outputConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+            inputConfig.channel_mask = AUDIO_CHANNEL_IN_STEREO;
+            rSubmixModule->addOutputProfile(address, &outputConfig,
+                    AUDIO_DEVICE_OUT_REMOTE_SUBMIX, address);
+            rSubmixModule->addInputProfile(address, &inputConfig,
+                    AUDIO_DEVICE_IN_REMOTE_SUBMIX, address);
 
-        if (mixes[i].mMixType == MIX_TYPE_PLAYERS) {
-            setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
-                                     AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
-                                     address.string(), "remote-submix");
-        } else {
-            setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
-                                     AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
-                                     address.string(), "remote-submix");
+            if (mixes[i].mMixType == MIX_TYPE_PLAYERS) {
+                setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
+                        AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+                        address.string(), "remote-submix");
+            } else {
+                setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
+                        AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+                        address.string(), "remote-submix");
+            }
+        } else if ((mixes[i].mRouteFlags & MIX_ROUTE_FLAG_RENDER) == MIX_ROUTE_FLAG_RENDER) {
+            ALOGV("registerPolicyMixes() mix %zu of %zu is RENDER", i, mixes.size());
+            String8 address = mixes[i].mDeviceAddress;
+
+            audio_devices_t device = mixes[i].mDeviceType;
+
+            for (size_t j = 0 ; j < mOutputs.size() ; j++) {
+                sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(j);
+                sp<AudioPatch> patch = mAudioPatches.valueFor(desc->getPatchHandle());
+                if ((patch != 0) && (patch->mPatch.num_sinks != 0)
+                        && (patch->mPatch.sinks[0].type == AUDIO_PORT_TYPE_DEVICE)
+                        && (patch->mPatch.sinks[0].ext.device.type == device)
+                        && (patch->mPatch.sinks[0].ext.device.address == address)) {
+
+                    if (mPolicyMixes.registerMix(address, mixes[i], desc) != NO_ERROR) {
+                        res = INVALID_OPERATION;
+                    }
+                    break;
+                }
+            }
+
+            if (res != NO_ERROR) {
+                ALOGE(" Error registering mix %zu for device 0x%X addr %s",
+                        i,device, address.string());
+                res = INVALID_OPERATION;
+                break;
+            }
         }
     }
-    return NO_ERROR;
+    if (res != NO_ERROR) {
+        unregisterPolicyMixes(mixes);
+    }
+    return res;
 }
 
 status_t AudioPolicyManager::unregisterPolicyMixes(Vector<AudioMix> mixes)
 {
-    sp<HwModule> module;
-    for (size_t i = 0; i < mHwModules.size(); i++) {
-        if (strcmp(AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX, mHwModules[i]->mName) == 0 &&
-                mHwModules[i]->mHandle != 0) {
-            module = mHwModules[i];
-            break;
-        }
-    }
-
-    if (module == 0) {
-        return INVALID_OPERATION;
-    }
-
     ALOGV("unregisterPolicyMixes() num mixes %zu", mixes.size());
-
+    status_t res = NO_ERROR;
+    sp<HwModule> rSubmixModule;
+    // examine each mix's route type
     for (size_t i = 0; i < mixes.size(); i++) {
-        String8 address = mixes[i].mRegistrationId;
+        if ((mixes[i].mRouteFlags & MIX_ROUTE_FLAG_LOOP_BACK) == MIX_ROUTE_FLAG_LOOP_BACK) {
 
-        if (mPolicyMixes.unregisterMix(address) != NO_ERROR) {
-            continue;
-        }
+            if (rSubmixModule == 0) {
+                for (size_t j = 0; i < mHwModules.size(); j++) {
+                    if (strcmp(AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX, mHwModules[j]->mName) == 0
+                            && mHwModules[j]->mHandle != 0) {
+                        rSubmixModule = mHwModules[j];
+                        break;
+                    }
+                }
+            }
+            if (rSubmixModule == 0) {
+                res = INVALID_OPERATION;
+                continue;
+            }
 
-        if (getDeviceConnectionState(AUDIO_DEVICE_IN_REMOTE_SUBMIX, address.string()) ==
-                                             AUDIO_POLICY_DEVICE_STATE_AVAILABLE)
-        {
-            setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
-                                     AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
-                                     address.string(), "remote-submix");
-        }
+            String8 address = mixes[i].mDeviceAddress;
 
-        if (getDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, address.string()) ==
-                                             AUDIO_POLICY_DEVICE_STATE_AVAILABLE)
-        {
-            setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
-                                     AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
-                                     address.string(), "remote-submix");
+            if (mPolicyMixes.unregisterMix(address) != NO_ERROR) {
+                res = INVALID_OPERATION;
+                continue;
+            }
+
+            if (getDeviceConnectionState(AUDIO_DEVICE_IN_REMOTE_SUBMIX, address.string()) ==
+                    AUDIO_POLICY_DEVICE_STATE_AVAILABLE)  {
+                setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
+                        AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+                        address.string(), "remote-submix");
+            }
+            if (getDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, address.string()) ==
+                    AUDIO_POLICY_DEVICE_STATE_AVAILABLE)  {
+                setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
+                        AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+                        address.string(), "remote-submix");
+            }
+            rSubmixModule->removeOutputProfile(address);
+            rSubmixModule->removeInputProfile(address);
+
+        } if ((mixes[i].mRouteFlags & MIX_ROUTE_FLAG_RENDER) == MIX_ROUTE_FLAG_RENDER) {
+            if (mPolicyMixes.unregisterMix(mixes[i].mDeviceAddress) != NO_ERROR) {
+                res = INVALID_OPERATION;
+                continue;
+            }
         }
-        module->removeOutputProfile(address);
-        module->removeInputProfile(address);
     }
-    return NO_ERROR;
+    return res;
 }
 
 
diff --git a/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp b/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
index 5f4fb22..b4b269a 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,
-                HAL_DATASPACE_JFIF, CAMERA3_STREAM_ROTATION_0, &mCallbackStreamId);
+                HAL_DATASPACE_V0_JFIF, CAMERA3_STREAM_ROTATION_0, &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 3923853..e97618c 100644
--- a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
@@ -145,7 +145,7 @@
         // Create stream for HAL production
         res = device->createStream(mCaptureWindow,
                 params.pictureWidth, params.pictureHeight,
-                HAL_PIXEL_FORMAT_BLOB, HAL_DATASPACE_JFIF,
+                HAL_PIXEL_FORMAT_BLOB, HAL_DATASPACE_V0_JFIF,
                 CAMERA3_STREAM_ROTATION_0, &mCaptureStreamId);
         if (res != OK) {
             ALOGE("%s: Camera %d: Can't create output stream for capture: "
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index d4022cd..5779176 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -872,7 +872,7 @@
 
     // Set up initial state for non-Camera.Parameters state variables
     videoFormat = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
-    videoDataSpace = HAL_DATASPACE_BT709;
+    videoDataSpace = HAL_DATASPACE_V0_BT709;
     videoBufferMode = hardware::ICamera::VIDEO_BUFFER_MODE_DATA_CALLBACK_YUV;
     playShutterSound = true;
     enableFaceDetect = false;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 05c5323..331f10d 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -410,6 +410,31 @@
     return measured;
 }
 
+/**
+ * Map Android N dataspace definitions back to Android M definitions, for
+ * use with HALv3.3 or older.
+ *
+ * Only map where correspondences exist, and otherwise preserve the value.
+ */
+android_dataspace Camera3Device::mapToLegacyDataspace(android_dataspace dataSpace) {
+    switch (dataSpace) {
+        case HAL_DATASPACE_V0_SRGB_LINEAR:
+            return HAL_DATASPACE_SRGB_LINEAR;
+        case HAL_DATASPACE_V0_SRGB:
+            return HAL_DATASPACE_SRGB;
+        case HAL_DATASPACE_V0_JFIF:
+            return HAL_DATASPACE_JFIF;
+        case HAL_DATASPACE_V0_BT601_625:
+            return HAL_DATASPACE_BT601_625;
+        case HAL_DATASPACE_V0_BT601_525:
+            return HAL_DATASPACE_BT601_525;
+        case HAL_DATASPACE_V0_BT709:
+            return HAL_DATASPACE_BT709;
+        default:
+            return dataSpace;
+    }
+}
+
 ssize_t Camera3Device::getJpegBufferSize(uint32_t width, uint32_t height) const {
     // Get max jpeg size (area-wise).
     Size maxJpegResolution = getMaxJpegResolution();
@@ -1006,6 +1031,10 @@
     if (mDeviceVersion <= CAMERA_DEVICE_API_VERSION_3_2) {
         streamSetId = CAMERA3_STREAM_SET_ID_INVALID;
     }
+    // Use legacy dataspace values for older HALs
+    if (mDeviceVersion <= CAMERA_DEVICE_API_VERSION_3_3) {
+        dataSpace = mapToLegacyDataspace(dataSpace);
+    }
     if (format == HAL_PIXEL_FORMAT_BLOB) {
         ssize_t blobBufferSize;
         if (dataSpace != HAL_DATASPACE_DEPTH) {
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 5b1c87e..ba092d0 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -404,6 +404,11 @@
      */
     static nsecs_t getMonoToBoottimeOffset();
 
+    /**
+     * Helper function to map between legacy and new dataspace enums
+     */
+    static android_dataspace mapToLegacyDataspace(android_dataspace dataSpace);
+
     struct RequestTrigger {
         // Metadata tag number, e.g. android.control.aePrecaptureTrigger
         uint32_t metadataTag;